Own context menu and swipe actions on rows (Views tree first) #242

Closed
opened 2026-10-18 07:57:17 +00:00 by kayg · 14 comments
Owner

Owner, 2026-10-18 (screenshot of the Views sidebar, Console section, right-click on a session row shows the browser's own menu: Look Up, Copy, Search Google, Print, Inspect…): "i feel like we should have our own context menu and support swipe gestures here (both horizontal scroll, magic mouse/trackpad swipes)".

Builds on D127 (session manager: attach, rename inline, open beside, end with confirmation; trackpad, Magic Mouse and touch swipe gestures where appropriate) and the palette-reaches-everything rule. Also seen in the screenshot: right-click selects the row's text ("shell" highlighted), which a row should never do.

Plan: owner answers the open questions (items, swipe directions, scope, browser-menu escape), then a mockup round in apps/tracer + packages/ui (reusing anchored-popover / branched menu), owner approval, then the build.

Owner, 2026-10-18 (screenshot of the Views sidebar, Console section, right-click on a session row shows the browser's own menu: Look Up, Copy, Search Google, Print, Inspect…): "i feel like we should have our own context menu and support swipe gestures here (both horizontal scroll, magic mouse/trackpad swipes)". Builds on D127 (session manager: attach, rename inline, open beside, end with confirmation; trackpad, Magic Mouse and touch swipe gestures where appropriate) and the palette-reaches-everything rule. Also seen in the screenshot: right-click selects the row's text ("shell" highlighted), which a row should never do. Plan: owner answers the open questions (items, swipe directions, scope, browser-menu escape), then a mockup round in apps/tracer + packages/ui (reusing anchored-popover / branched menu), owner approval, then the build.
Author
Owner

Mockup round, branch mockup-row-menu, head 57f4787c2a4fbf904f6ca10433b4ba7e8fea8657 (base 4356e7989, D309 first bullet).

Open the mock: build with INFRATERNAL_CLUSTERS_PREVIEW=1 bun run build.ts in apps/tracer, serve it (TRACER_TEST_PORT=47601 python3 scripts/latency_proxy.py serve-tracer), open /?mock=1&proto=clusters&scene=3, open the sidebar (top-left button). Right-click, long-press, Shift+F10 or swipe a row. Trackpad: two-finger horizontal scroll on a row.

What is real vs mock: one shared component (packages/ui/src/row-menu.ts) plus the sidebar tree's per-list items (toolbar/row-actions.ts). The inventory, windows and palette are the real code against the test double; only the host removal is a stub (toast, nothing removed).

  • Session row: Open, Open beside, Rename (in place), Copy name, End session… (asks, names what is running). Swipe left = End (red), right = Open beside; short reveals, long performs (End still asks first).
  • Host caption: Open shell, Copy name, Remove host… (stub). Mesh node: Open, Copy name. Window row: Open, Copy name, Close window (swipe left).
  • Shift+right-click is left to the browser (nothing shows it). Right-click selects no text. Context-menu key and Shift+F10 open the same menu, instant, focus on the first row, no ring. Every action of the focused row is also a palette row.
  • Gzip JS, production build without the mock: 418,845 B to 422,836 B (+3,991 B concatenated; +4,172 B summed per file). Handler cost per wheel event p50 0.2 ms, p95 0.9 ms (headless Chromium, software rendering: frame times in that setup are 33-100 ms for ANY change inside the sidebar, e.g. a plain transform or hover fill, so they say nothing about devices; needs a real-device pass).
  • bun run check passes; test/row-menu.spec.ts (5 tests) passes.

Screenshots (desktop 1440x900 ink and paper; phone 393x852 and 375x667):
d-ink-menu-session.png
d-ink-menu-host2.png
d-ink-menu-mesh.png
d-ink-swipe-left-mid.png
d-ink-swipe-left-rest.png
d-ink-swipe-right-rest.png
d-ink-end-confirm-menu.png
d-ink-menu-keyboard.png
d-ink-palette-row.png
d-paper-menu-session.png
d-paper-swipe-left-rest.png
p393-ink-menu-session.png
p393-ink-menu-host.png
p393-ink-menu-mesh.png
p393-ink-swipe-left-mid.png
p393-ink-swipe-right-mid.png
p393-ink-end-confirm.png
p375-paper-menu-session.png
swipe-phone.webm

Mockup round, branch `mockup-row-menu`, head `57f4787c2a4fbf904f6ca10433b4ba7e8fea8657` (base 4356e7989, D309 first bullet). **Open the mock:** build with `INFRATERNAL_CLUSTERS_PREVIEW=1 bun run build.ts` in `apps/tracer`, serve it (`TRACER_TEST_PORT=47601 python3 scripts/latency_proxy.py serve-tracer`), open `/?mock=1&proto=clusters&scene=3`, open the sidebar (top-left button). Right-click, long-press, Shift+F10 or swipe a row. Trackpad: two-finger horizontal scroll on a row. **What is real vs mock:** one shared component (`packages/ui/src/row-menu.ts`) plus the sidebar tree's per-list items (`toolbar/row-actions.ts`). The inventory, windows and palette are the real code against the test double; only the host removal is a stub (toast, nothing removed). - Session row: Open, Open beside, Rename (in place), Copy name, End session… (asks, names what is running). Swipe left = End (red), right = Open beside; short reveals, long performs (End still asks first). - Host caption: Open shell, Copy name, Remove host… (stub). Mesh node: Open, Copy name. Window row: Open, Copy name, Close window (swipe left). - Shift+right-click is left to the browser (nothing shows it). Right-click selects no text. Context-menu key and Shift+F10 open the same menu, instant, focus on the first row, no ring. Every action of the focused row is also a palette row. - Gzip JS, production build without the mock: 418,845 B to 422,836 B (+3,991 B concatenated; +4,172 B summed per file). Handler cost per wheel event p50 0.2 ms, p95 0.9 ms (headless Chromium, software rendering: frame times in that setup are 33-100 ms for ANY change inside the sidebar, e.g. a plain transform or hover fill, so they say nothing about devices; needs a real-device pass). - `bun run check` passes; `test/row-menu.spec.ts` (5 tests) passes. Screenshots (desktop 1440x900 ink and paper; phone 393x852 and 375x667): ![d-ink-menu-session.png](https://git.kayg.org/attachments/fb5628f8-7bf4-49f3-a47b-e0feeb941f52) ![d-ink-menu-host2.png](https://git.kayg.org/attachments/719cb4e0-1a0a-4509-b45d-206a1d4c5f18) ![d-ink-menu-mesh.png](https://git.kayg.org/attachments/29166fd4-73eb-494a-8f68-61e1e86d1df7) ![d-ink-swipe-left-mid.png](https://git.kayg.org/attachments/09399066-06fc-4cd9-a963-161d38c86825) ![d-ink-swipe-left-rest.png](https://git.kayg.org/attachments/d212c761-8b9c-4c1c-a76e-0b60a492b691) ![d-ink-swipe-right-rest.png](https://git.kayg.org/attachments/040db656-5d3e-4d7f-8ee2-f57c8fc5a07c) ![d-ink-end-confirm-menu.png](https://git.kayg.org/attachments/1e32c9ca-2b34-4a70-aeeb-69025a0c58bb) ![d-ink-menu-keyboard.png](https://git.kayg.org/attachments/630ef233-8f13-44d7-8cdf-97a80680a7e2) ![d-ink-palette-row.png](https://git.kayg.org/attachments/d9cf717b-3f8f-44b7-85e2-2d86993313a7) ![d-paper-menu-session.png](https://git.kayg.org/attachments/ba35afca-f2e4-4ea6-af9a-726de04cfb94) ![d-paper-swipe-left-rest.png](https://git.kayg.org/attachments/2a883ba7-353c-4418-9e3d-94317ebe02e9) ![p393-ink-menu-session.png](https://git.kayg.org/attachments/f4408c4d-85dd-40f9-88b3-c626d6b4674d) ![p393-ink-menu-host.png](https://git.kayg.org/attachments/7d0623fd-29f2-42dc-9e83-32ea3ade17e6) ![p393-ink-menu-mesh.png](https://git.kayg.org/attachments/91b3790d-1e2e-4598-8678-cc096a59a117) ![p393-ink-swipe-left-mid.png](https://git.kayg.org/attachments/c51e0089-03e9-4b0c-b437-d9c6618123dc) ![p393-ink-swipe-right-mid.png](https://git.kayg.org/attachments/ce3bb02b-7149-431e-9af6-345e4a58986e) ![p393-ink-end-confirm.png](https://git.kayg.org/attachments/32fcddc2-a2e4-450e-92ab-448098f6a2a7) ![p375-paper-menu-session.png](https://git.kayg.org/attachments/11a85ff5-7aeb-4550-9e55-103e8e8a4538) [swipe-phone.webm](https://git.kayg.org/attachments/f454cb5b-fa34-4a7e-889d-bb089b323821)
Author
Owner

Rebuilt on current dev for the owner's review. Branch mockups-2026-10-31, head 586cd2b13 (base dev 42ab33035, 2026-10-31). Test double only; nothing is real or saved. Not merged, not deployed. Old previews are gone; this replaces them.

Preview (NetBird, bound to infraternal-dev-02-std; index of every mockup: http://10.69.69.117:47650/mockups.html):

How: Open the sidebar (top left). Right-click, long-press, Shift+F10 or swipe a row; on a trackpad scroll sideways over a row.

Note: Rebased only: no design change since the round in D309. The mesh-node and window-row menus are in the same build.

Captures are Chromium on the production build of the mockup, taken by apps/tracer/test/capture-mockups.ts; I have read them for wrong states, not judged them as final.

Desktop 1440×900 @2x, ink

host-menu
session-menu
swipe-other-way
swipe-short-reveal

Desktop 1440×900 @2x, paper

host-menu
session-menu
swipe-other-way
swipe-short-reveal

Phone 393×852 @3x, ink

host-menu
session-menu
swipe-other-way
swipe-short-reveal

Phone 393×852 @3x, paper (first state only)

session-menu

Rebuilt on current dev for the owner's review. Branch `mockups-2026-10-31`, head `586cd2b13` (base dev `42ab33035`, 2026-10-31). Test double only; nothing is real or saved. Not merged, not deployed. Old previews are gone; this replaces them. **Preview** (NetBird, bound to infraternal-dev-02-std; index of every mockup: http://10.69.69.117:47650/mockups.html): - http://10.69.69.117:47650/?mock=1&proto=clusters&scene=3 **How:** Open the sidebar (top left). Right-click, long-press, Shift+F10 or swipe a row; on a trackpad scroll sideways over a row. **Note:** Rebased only: no design change since the round in D309. The mesh-node and window-row menus are in the same build. Captures are Chromium on the production build of the mockup, taken by `apps/tracer/test/capture-mockups.ts`; I have read them for wrong states, not judged them as final. **Desktop 1440×900 @2x, ink** ![host-menu](https://git.kayg.org/attachments/518f1f59-67d2-4fa1-aefd-816c30641788) ![session-menu](https://git.kayg.org/attachments/cdd98fa8-1ebb-4f99-a5b9-52d755a94f97) ![swipe-other-way](https://git.kayg.org/attachments/9b285b6c-3819-4b00-8c05-f17d0506913b) ![swipe-short-reveal](https://git.kayg.org/attachments/8873077d-fd44-4eb6-a242-ed30a6ced33e) **Desktop 1440×900 @2x, paper** ![host-menu](https://git.kayg.org/attachments/631677e5-841b-495d-9240-ff6ed3596565) ![session-menu](https://git.kayg.org/attachments/4ab94884-6284-4da6-b366-669fb215bd1a) ![swipe-other-way](https://git.kayg.org/attachments/2647052c-a2a6-46fc-a970-36a1055c6159) ![swipe-short-reveal](https://git.kayg.org/attachments/f5feb99a-815d-459a-b8eb-753049414765) **Phone 393×852 @3x, ink** ![host-menu](https://git.kayg.org/attachments/b024f926-a111-42d1-91c3-9655fa7a3b76) ![session-menu](https://git.kayg.org/attachments/a7df2ed6-e399-45f9-815d-e291abe69a1c) ![swipe-other-way](https://git.kayg.org/attachments/99f894d6-3781-4c22-b9b6-87b8f92bdf77) ![swipe-short-reveal](https://git.kayg.org/attachments/f175b8ae-8c08-4df4-8a76-95f5210125fb) **Phone 393×852 @3x, paper (first state only)** ![session-menu](https://git.kayg.org/attachments/b59077ec-c112-4066-b34f-5b432694cdbb)
Author
Owner

Update to the comment above: the branch head is now 57871651f (the preview at http://10.69.69.117:47650/mockups.html runs it). The captures above were taken one build earlier; the only difference is that the window terminals there hide their cursor until attached, a production change that was since removed from the branch. Gate output, what is left out, and the budget finding: #272.

Update to the comment above: the branch head is now `57871651f` (the preview at http://10.69.69.117:47650/mockups.html runs it). The captures above were taken one build earlier; the only difference is that the window terminals there hide their cursor until attached, a production change that was since removed from the branch. Gate output, what is left out, and the budget finding: #272.
Author
Owner

J52 start (design sub-agent, 2026-11-01). Owner feedback on the #242 mockup:

"God I love our product. The swipes are fantastic in the sidebar, what i do wanna critique is that dialog that appears with "End" — that should be just text appearing in the same row asking for confirmation. also the left to right swipe → creating a new session could be smoother."

Plan: (1) TASTE.md rows, own docs commit on taste-2026-11-01 from origin/dev; (2) End asks inline in its row; the right swipe (Open beside) follows the finger 1:1, settles with a spring and no snap-back, threshold cue; frame times measured in Chromium; (3) Option on the window split buttons, tracked in #280.

Branch mockups-2026-11-01-j52 (tracks mockups-2026-10-31), base 57871651f + merge of origin/dev f4b61cd6c (6b9e6d6bd). A linear rebase stops at a Mesh commit (#183) that dev reworked; the merge is conflict-free, so I merged.

**J52 start** (design sub-agent, 2026-11-01). Owner feedback on the #242 mockup: > "God I love our product. The swipes are fantastic in the sidebar, what i do wanna critique is that dialog that appears with "End" — that should be just text appearing in the same row asking for confirmation. also the left to right swipe → creating a new session could be smoother." Plan: (1) TASTE.md rows, own docs commit on `taste-2026-11-01` from origin/dev; (2) End asks inline in its row; the right swipe (Open beside) follows the finger 1:1, settles with a spring and no snap-back, threshold cue; frame times measured in Chromium; (3) Option on the window split buttons, tracked in #280. Branch `mockups-2026-11-01-j52` (tracks `mockups-2026-10-31`), base `57871651f` + merge of `origin/dev` `f4b61cd6c` (`6b9e6d6bd`). A linear rebase stops at a Mesh commit (#183) that dev reworked; the merge is conflict-free, so I merged.
Author
Owner

J52 evidence: End asks in its row, and the right swipe is one continuous motion (branch mockups-2026-10-31, head 7e0497605; production build, Chromium 155, headless; screenshots at 1440×900 DPR 2 and 393×852 DPR 3; Playwright videos of both). Served at http://10.69.69.117:47650/mockups.html (card "Row menu and swipes"). Not judged as final visuals.

End. The dialog is gone; the row's own text becomes End session? End · Cancel at the row's height. Attached: question-in-row (d, p), cancelled-row-restored, question-from-menu, cancel-focused (keyboard), videos end-asks-in-row.
row-ask.spec.ts: no .ui-confirm-tip or alert dialog in the DOM, the row's and its neighbour's layout boxes are identical before/during/after, the whole question sits inside the row's box, keyboard (menu → End lands on End, ←/→, Enter ends, Escape cancels and refocuses the row), a press elsewhere cancels, the palette's "End session 'deploy'" asks in the row too.
A first capture showed the question cut ("End sessio…") in the 200 px rows: fixed (tighter spacing, shortQuestion fallback "End?" only if still too narrow) and asserted in the spec.

Right swipe (Open beside), measured on the same drag (393×852, DPR 3, 24 touch moves), original head 57871651f vs now, three runs each:

before after
row behind the finger while dragging 11.6–18.9 px (the leaf had a 140 ms CSS transition on its transform) 0 px
furthest the row travels after release 277–280 px (thrown to the screen edge) 210–212 px (where the finger was)
largest single-frame step 128–130 px (the snap back) 21 px
settle after release edge → instant jump to 150 → … 210 → 205 → 189 → 169 → 148 → … → 0, no crossing to the other side

Frame times in row-swipe-continuity.spec.ts (headless, 60 Hz): p50 16.7 ms, p95 16.8 ms, max 16.8 ms, largest row step 10.6 px (finger step 8.75 px + slop catch-up). Attached: revealed, building, armed (accent fill builds, icon pops at the threshold), settling, after-release; video swipe-right-continuous.

Unit/spec results on this head: row-ask 3/3, row-swipe-continuity 2/2, window-option-new 6/6, bun run check clean, spring + icon-morph unit tests pass.

**J52 evidence: End asks in its row, and the right swipe is one continuous motion** (branch `mockups-2026-10-31`, head `7e0497605`; production build, Chromium 155, headless; screenshots at 1440×900 DPR 2 and 393×852 DPR 3; Playwright videos of both). Served at http://10.69.69.117:47650/mockups.html (card "Row menu and swipes"). Not judged as final visuals. **End.** The dialog is gone; the row's own text becomes `End session? End · Cancel` at the row's height. Attached: `question-in-row` (d, p), `cancelled-row-restored`, `question-from-menu`, `cancel-focused` (keyboard), videos `end-asks-in-row`. `row-ask.spec.ts`: no `.ui-confirm-tip` or alert dialog in the DOM, the row's and its neighbour's layout boxes are identical before/during/after, the whole question sits inside the row's box, keyboard (menu → End lands on End, ←/→, Enter ends, Escape cancels and refocuses the row), a press elsewhere cancels, the palette's "End session 'deploy'" asks in the row too. A first capture showed the question cut ("End sessio…") in the 200 px rows: fixed (tighter spacing, `shortQuestion` fallback "End?" only if still too narrow) and asserted in the spec. **Right swipe (Open beside), measured on the same drag (393×852, DPR 3, 24 touch moves), original head `57871651f` vs now, three runs each:** | | before | after | |---|---|---| | row behind the finger while dragging | 11.6–18.9 px (the leaf had a 140 ms CSS transition on its transform) | 0 px | | furthest the row travels after release | 277–280 px (thrown to the screen edge) | 210–212 px (where the finger was) | | largest single-frame step | 128–130 px (the snap back) | 21 px | | settle after release | edge → instant jump to 150 → … | 210 → 205 → 189 → 169 → 148 → … → 0, no crossing to the other side | Frame times in `row-swipe-continuity.spec.ts` (headless, 60 Hz): p50 16.7 ms, p95 16.8 ms, max 16.8 ms, largest row step 10.6 px (finger step 8.75 px + slop catch-up). Attached: `revealed`, `building`, `armed` (accent fill builds, icon pops at the threshold), `settling`, `after-release`; video `swipe-right-continuous`. Unit/spec results on this head: row-ask 3/3, row-swipe-continuity 2/2, window-option-new 6/6, `bun run check` clean, spring + icon-morph unit tests pass.
Author
Owner

J52 finish (design sub-agent, 2026-11-01). Branch mockups-2026-10-31, head 4c389a2f4 (base: 57871651f + merge of origin/dev f4b61cd6c; a linear rebase stops at a Mesh commit of #183, the merge is conflict-free). Docs branch taste-2026-11-01, head 2b3957574 (from origin/dev f4b61cd6c; four TASTE rows with the owner's quotes: in-row confirmation, continuous create-swipes, Option on split buttons, icon/text centre line, UI size).

Done (each has its own issue comment with evidence): End asks in its row (#242), continuous right swipe with before/after numbers (#242), Option on split buttons (#280), icon/text alignment fixed at the source with an audit and spec (#282), UI size slider 50–150 % (#283). Index trimmed to what awaits review; re-served at http://10.69.69.117:47650/mockups.html: UI size (#283), Row menu and swipes (#242), Machine cards (#94), Host rename/remove + privileged access consent (#215), Boot machines (#156, marked "deferred until PXE booting"), Sessions UI (#104). Removed as approved: #189, #212, #216, #224, #280 (the code stays).

Gate. scripts/verify fast was run on compute01 at 1ef44b4c5 (since then only TypeScript, CSS and docs changed; git diff origin/dev HEAD -- crates Cargo.toml Cargo.lock is empty). Verbatim:

| Rust gate                 | Result       |
+---------------------------+--------------+
| fmt                       | PASS         |
| VT native fmt             | PASS         |
| CLI plugin compile-out    | PASS         |
| clippy                    | PASS         |
| SSH runtime test helper   | PASS         |
| real-binary fixture paths | PASS         |
| test                      | FAIL (101)   |
| SSH inode reuse fixture   | PASS         |
| shim process-per-user     | PASS         |
| cargo-deny                | PASS         |
| gate architecture         | PASS         |
| static builds             | PASS         |
+---------------------------+--------------+

The one failing row is latency_fixture_accepts_the_unsolicited_startup_inventory (crates/infraternal/tests/agent_sessions.rs:405, a 1 s socket read in scripts/agent_fixture.py timing out, VM at load average 17). Rerun alone on the same tree: test result: ok. 4 passed; 0 failed; finished in 0.75s. No Rust source differs from origin/dev, so it is not caused by this branch.
TypeScript half of the gate on the final head (dev-02-std, the exact commands of ts_verify_fast minus the Rust stream oracle): bun test scripts/release/build-metadata.test.ts 2 pass; Ghostty checksums OK; protocol tsc rc=0; tracer bun run check clean; 417 pass 0 fail, 105 pass 0 fail, 17 pass 0 fail. The bundle transfer budget fails ("production critical-path JavaScript exceeds the compressed transfer budget"), and also on the unmodified original head 57871651f (a mockups branch carries mockup code): critical gzip 339,238 B before, 340,652 B now (+1,414 B; brotli 284,608 → 285,838, +1,230 B; limit 307,200 / 256,000), deferred gzip +1,350 B, onDemand +551 B. Not production numbers; the orchestrator ratchets on merge.
Specs on a production build (headless Chromium): row-ask 3/3, row-swipe-continuity 2/2, window-option-new 6/6, icon-text-centre 16/16, ui-size 6/6, sidebar-resize 8/8, row-menu 5/5, palette-navigation, footer-cards-break 64/64. clusters-top-right fails on the unmodified original head too (gap 62 px, expected ≤ 24): not from this work.

Needs the owner: (1) whether windows should grow with the UI size (#283 list item 1); (2) the three approved mockups above were removed from the index on the orchestrator's word. Not done / stray: none of my own processes are left running on dev-02-std except the shared preview server on :47650; compute01 ~/worktrees/j52 holds a Rust target (to delete when you say so). dev-02-std's disk is at 96 % from other jobs, so build-slot would not admit anything while I worked; I ran light browser specs directly with nice.

**J52 finish** (design sub-agent, 2026-11-01). Branch `mockups-2026-10-31`, head **`4c389a2f4`** (base: `57871651f` + merge of origin/dev `f4b61cd6c`; a linear rebase stops at a Mesh commit of #183, the merge is conflict-free). Docs branch `taste-2026-11-01`, head `2b3957574` (from origin/dev `f4b61cd6c`; four TASTE rows with the owner's quotes: in-row confirmation, continuous create-swipes, Option on split buttons, icon/text centre line, UI size). **Done** (each has its own issue comment with evidence): End asks in its row (#242), continuous right swipe with before/after numbers (#242), Option on split buttons (#280), icon/text alignment fixed at the source with an audit and spec (#282), UI size slider 50–150 % (#283). Index trimmed to what awaits review; re-served at http://10.69.69.117:47650/mockups.html: **UI size (#283), Row menu and swipes (#242), Machine cards (#94), Host rename/remove + privileged access consent (#215), Boot machines (#156, marked "deferred until PXE booting"), Sessions UI (#104)**. Removed as approved: #189, #212, #216, #224, #280 (the code stays). **Gate.** `scripts/verify fast` was run on compute01 at `1ef44b4c5` (since then only TypeScript, CSS and docs changed; `git diff origin/dev HEAD -- crates Cargo.toml Cargo.lock` is empty). Verbatim: ``` | Rust gate | Result | +---------------------------+--------------+ | fmt | PASS | | VT native fmt | PASS | | CLI plugin compile-out | PASS | | clippy | PASS | | SSH runtime test helper | PASS | | real-binary fixture paths | PASS | | test | FAIL (101) | | SSH inode reuse fixture | PASS | | shim process-per-user | PASS | | cargo-deny | PASS | | gate architecture | PASS | | static builds | PASS | +---------------------------+--------------+ ``` The one failing row is `latency_fixture_accepts_the_unsolicited_startup_inventory` (`crates/infraternal/tests/agent_sessions.rs:405`, a 1 s socket read in `scripts/agent_fixture.py` timing out, VM at load average 17). Rerun alone on the same tree: `test result: ok. 4 passed; 0 failed; finished in 0.75s`. No Rust source differs from origin/dev, so it is not caused by this branch. TypeScript half of the gate on the **final head** (dev-02-std, the exact commands of `ts_verify_fast` minus the Rust stream oracle): `bun test scripts/release/build-metadata.test.ts` 2 pass; Ghostty checksums OK; protocol `tsc` rc=0; tracer `bun run check` clean; `417 pass 0 fail`, `105 pass 0 fail`, `17 pass 0 fail`. The bundle **transfer budget fails** ("production critical-path JavaScript exceeds the compressed transfer budget"), and also on the unmodified original head `57871651f` (a mockups branch carries mockup code): critical gzip 339,238 B before, 340,652 B now (+1,414 B; brotli 284,608 → 285,838, +1,230 B; limit 307,200 / 256,000), deferred gzip +1,350 B, onDemand +551 B. Not production numbers; the orchestrator ratchets on merge. Specs on a production build (headless Chromium): row-ask 3/3, row-swipe-continuity 2/2, window-option-new 6/6, icon-text-centre 16/16, ui-size 6/6, sidebar-resize 8/8, row-menu 5/5, palette-navigation, footer-cards-break 64/64. `clusters-top-right` fails on the unmodified original head too (gap 62 px, expected ≤ 24): not from this work. **Needs the owner:** (1) whether windows should grow with the UI size (#283 list item 1); (2) the three approved mockups above were removed from the index on the orchestrator's word. **Not done / stray:** none of my own processes are left running on dev-02-std except the shared preview server on :47650; compute01 `~/worktrees/j52` holds a Rust target (to delete when you say so). dev-02-std's disk is at 96 % from other jobs, so `build-slot` would not admit anything while I worked; I ran light browser specs directly with `nice`.
Author
Owner

J52: the in-row question now starts where the row labels start (owner, 2026-11-01: "the 'end session' should start from where the other rows also start from, please pay attention UI detail. like alignment is the most basic thing here"). Branch mockups-2026-10-31, commit 97597e740; re-served at http://10.69.69.117:47650/mockups.html. TASTE alignment row updated with the quote and the rule (taste-2026-11-01, aa2c1066c).

Measured before the fix (1440 page): the question began at x = 91, the labels at x = 119: 28 px apart (87 vs 115 on the phone), over the status dot's column. Now: attached crops at 4x (desktop) and 3x (phone) with a red guide line at the labels' x: the "E" of "End session?" is on it, the dot keeps its column, same line, same size, "End · Cancel" follow on the same line without clipping.

Fix at the shared source: row-confirm.ts takes the row's label (alignTo) and starts the question at that label's offset inside the leaf (a difference of two rects, so a swipe in flight does not move it); only the leaf's words fade, the status dot stays. The answers did not fit once moved right (1440: 5 px short; the row is 218 px, the label starts 34 px in), so their side padding is tightened (3 px, hit area unchanged through ::after; 8 px on touch) rather than shortening "End session?".

Spec apps/tracer/test/replacement-alignment.spec.ts (5/5, at 1440×900 DPR 2 and 393×852 DPR 3, ≤ 0.5 px): the question's left edge against its own row's label and the other rows' labels; same centre line; same text size; the dot in the other rows' dot column and on the question's centre line; Cancel inside the row; the full "End session?". Audit of the other in-place replacements, same spec: the rename field (text left = label left: already right, now held), a copied value (its text does not move while the inline tick shows: already right, now held). Swipe left to right unchanged ("just fine"): row-swipe-continuity 2/2, row-ask 3/3, row-menu 5/5, icon-text-centre 16/16.

**J52: the in-row question now starts where the row labels start** (owner, 2026-11-01: "the 'end session' should start from where the other rows also start from, please pay attention UI detail. like alignment is the most basic thing here"). Branch `mockups-2026-10-31`, commit `97597e740`; re-served at http://10.69.69.117:47650/mockups.html. TASTE alignment row updated with the quote and the rule (`taste-2026-11-01`, `aa2c1066c`). **Measured before the fix** (1440 page): the question began at x = 91, the labels at x = 119: 28 px apart (87 vs 115 on the phone), over the status dot's column. **Now:** attached crops at 4x (desktop) and 3x (phone) with a red guide line at the labels' x: the "E" of "End session?" is on it, the dot keeps its column, same line, same size, "End · Cancel" follow on the same line without clipping. **Fix at the shared source:** `row-confirm.ts` takes the row's label (`alignTo`) and starts the question at that label's offset inside the leaf (a difference of two rects, so a swipe in flight does not move it); only the leaf's words fade, the status dot stays. The answers did not fit once moved right (1440: 5 px short; the row is 218 px, the label starts 34 px in), so their side padding is tightened (3 px, hit area unchanged through `::after`; 8 px on touch) rather than shortening "End session?". **Spec** `apps/tracer/test/replacement-alignment.spec.ts` (5/5, at 1440×900 DPR 2 and 393×852 DPR 3, ≤ 0.5 px): the question's left edge against its own row's label and the other rows' labels; same centre line; same text size; the dot in the other rows' dot column and on the question's centre line; Cancel inside the row; the full "End session?". Audit of the other in-place replacements, same spec: the **rename field** (text left = label left: already right, now held), a **copied value** (its text does not move while the inline tick shows: already right, now held). Swipe left to right unchanged ("just fine"): `row-swipe-continuity` 2/2, `row-ask` 3/3, `row-menu` 5/5, `icon-text-centre` 16/16.
Author
Owner

J106 start (UI job, Sonnet 5.5, 2026-11-02). Owner approved today: "both sidebar rows and rename are approved" (#242 row menu and swipes; #215 sidebar rename/remove). This job builds both into the real product, no mock flag.

Branch row-actions-242-215, worktree ~/Developer/Worktrees/infraternal-j106, base origin/dev = 17d282a18. Reference: origin/mockups-2026-10-31 (heads 4c389a2f4 / 97597e740, J52 last iteration). Builds and browsers on the VMs only, through build-slot.

Coordination with J73 (#292)

git branch -r on origin and forgejo has no sidebar-292 (J73's branch lives on code-minipc01, not pushed), so there is nothing to build on. I keep to row actions: new shared files packages/ui/src/row-menu.ts, row-swipe.ts, row-confirm.ts (ported unchanged from the mockup head, so J73's planned copy of row-confirm.ts is the same file and merges clean if it is taken from 97597e740), toolbar/row-actions.ts, and a small change to toolbar/tree.ts. I do not touch session-tree.on-demand.ts (host rows without sessions, +, selection, drag): that stays J73's. J73: please do not copy row-confirm.ts from before 97597e740 (the alignTo fix).

What the code has, what it lacks (evidence)

Piece State on dev Plan
Session rename inv.rename live; syncs through the canvas layout stream (#293 bf6d4cd52, on dev) reuse
Host removal adapters.hostRemoval exists (product.ts:201), server /remote/hosts/remove/{start,finish} (passkey proof) reuse as the mockup's host-row "Remove host…"
End session live-inventory.ts has can.end = false ("cannot end sessions until #100"); the server never signals a shim (contracts/wire.md), no leg-A verb missing backend. I build the in-row End + left swipe behind can.end (the mockup already does), so they appear when #100 lands. Not inventing a backend.
Host rename no server route, hosts are named by their enrolment missing backend: host rename is left out (session rename only); the mock's host rename field is not ported.
Privileged access (Access level row, consent) no route to change an agent's privilege missing backend. Port the Access level row and consent card against an adapters.privilege interface that the product leaves unset (row absent) until the endpoint exists; Playwright drives a test adapter.

Plan

Step What Est.
1 Port row-menu / row-swipe / row-confirm / spring fling, CSS, tooltips needed (one commit per concern, no unrelated mockup-branch change: no UI-size rem conversion, no Mesh) 2 h
2 row-actions.ts + tree.ts: session/host/window rows; palette rows for the focused row 1.5 h
3 #215: hover action pill, double-click and F2 rename (shared inline-rename), Delete, remove-host in-row confirm 2 h
4 #215: Access level row in the Host tab + consent card, adapter-driven 2 h
5 Playwright, desktop 1440x900 and phone 393x852: right-click, long-press, Shift+F10, trackpad sideways scroll, left/right swipe, in-row End, hover pill, double-click, F2, Delete, consent; alignment (+-0.5 px) and in-row confirmation checks 3 h
6 Production-build screenshots DPR 2/3, scripts/verify fast, push, comment 2 h

Total about 12.5 h. I stop and report at 25 h.

**J106 start** (UI job, Sonnet 5.5, 2026-11-02). Owner approved today: "both sidebar rows and rename are approved" (#242 row menu and swipes; #215 sidebar rename/remove). This job builds both into the real product, no mock flag. Branch `row-actions-242-215`, worktree `~/Developer/Worktrees/infraternal-j106`, base `origin/dev` = `17d282a18`. Reference: `origin/mockups-2026-10-31` (heads `4c389a2f4` / `97597e740`, J52 last iteration). Builds and browsers on the VMs only, through `build-slot`. ## Coordination with J73 (#292) `git branch -r` on origin and forgejo has **no** `sidebar-292` (J73's branch lives on code-minipc01, not pushed), so there is nothing to build on. I keep to row actions: new shared files `packages/ui/src/row-menu.ts`, `row-swipe.ts`, `row-confirm.ts` (ported unchanged from the mockup head, so J73's planned copy of `row-confirm.ts` is the same file and merges clean if it is taken from `97597e740`), `toolbar/row-actions.ts`, and a small change to `toolbar/tree.ts`. I do not touch `session-tree.on-demand.ts` (host rows without sessions, `+`, selection, drag): that stays J73's. J73: please do not copy `row-confirm.ts` from before `97597e740` (the alignTo fix). ## What the code has, what it lacks (evidence) | Piece | State on dev | Plan | |---|---|---| | Session rename | `inv.rename` live; syncs through the canvas layout stream (#293 `bf6d4cd52`, on dev) | reuse | | Host removal | `adapters.hostRemoval` exists (`product.ts:201`), server `/remote/hosts/remove/{start,finish}` (passkey proof) | reuse as the mockup's host-row "Remove host…" | | End session | `live-inventory.ts` has `can.end = false` ("cannot end sessions until #100"); the server never signals a shim (`contracts/wire.md`), no leg-A verb | **missing backend**. I build the in-row End + left swipe behind `can.end` (the mockup already does), so they appear when #100 lands. Not inventing a backend. | | Host rename | no server route, hosts are named by their enrolment | **missing backend**: host rename is left out (session rename only); the mock's host rename field is not ported. | | Privileged access (Access level row, consent) | no route to change an agent's privilege | **missing backend**. Port the Access level row and consent card against an `adapters.privilege` interface that the product leaves unset (row absent) until the endpoint exists; Playwright drives a test adapter. | ## Plan | Step | What | Est. | |---|---|---| | 1 | Port `row-menu` / `row-swipe` / `row-confirm` / spring fling, CSS, tooltips needed (one commit per concern, no unrelated mockup-branch change: no UI-size rem conversion, no Mesh) | 2 h | | 2 | `row-actions.ts` + tree.ts: session/host/window rows; palette rows for the focused row | 1.5 h | | 3 | #215: hover action pill, double-click and F2 rename (shared `inline-rename`), Delete, remove-host in-row confirm | 2 h | | 4 | #215: Access level row in the Host tab + consent card, adapter-driven | 2 h | | 5 | Playwright, desktop 1440x900 and phone 393x852: right-click, long-press, Shift+F10, trackpad sideways scroll, left/right swipe, in-row End, hover pill, double-click, F2, Delete, consent; alignment (+-0.5 px) and in-row confirmation checks | 3 h | | 6 | Production-build screenshots DPR 2/3, `scripts/verify fast`, push, comment | 2 h | Total about 12.5 h. I stop and report at 25 h.
Author
Owner

J106 progress (2026-11-02). Branch row-actions-242-215 (pushed), head bfaf96155; typecheck (bun run check) clean on dev-02 at 15bfac3c5.

Done, one commit per concern:

  1. 33e91b0c9 merge of sidebar-pill-259 (#259, scope added by the owner) onto origin/dev 17d282a18. Conflicts: the two inline-rename.ts modules (dev's account card and #259's) are now one field: #259's beginInlineRename / placeOverName / onDoubleActivate; dev's inlineRename(target, …) stays as a thin wrapper over it (account card unchanged), .ui-rename-input became .ui-inline-rename. Data path of a rename stays dev's (#293).
  2. 08c1cef27 shared row-menu.ts + row-confirm.ts (+ Spring.fling, window menu opening at a point, danger row), ported from 97597e740.
  3. 7eefe5674 toolbar/row-actions.ts + tree wiring: right-click, long press, Shift+F10/menu key, trackpad/touch swipes, End asks in its row, Rename through BranchedMenu.rename(id) (the shared field), palette rows for the focused row.
  4. 79da821ac hover action pill, F2, Delete (#215).
  5. kv-list panel + 15bfac3c5 Access level row and consent (#215, D286).
  6. bfaf96155 Playwright specs (row-menu, row-gestures, row-ask, replacement-alignment, row-swipe-continuity, sidebar-rename-remove, access-level).

Missing backends (not invented):

  • End session: the product inventory has can.end = false (#100; no leg-A verb, contracts/wire.md: the server never signals a shim). The in-row End, the left swipe and Delete-on-a-session are built behind can.end; in the product they do not appear until #100 lands (the test double can end).
  • Privileged access: no server endpoint raises the agent's privileges with a once-used secret. The row and consent are built against Adapters.privilege (sessions/privilege.ts, a PrivilegeService); the product leaves it unset, so the "Access level" row does not show. The test double implements it (?privilege=<scenario>).
  • Host removal and host rename are real: removal uses adapters.hostRemoval (/remote/hosts/remove/*, passkey flow, so it asks in its own card, not in the row); a host renames through mesh.node.rename (#259), so only a host the Mesh knows has Rename.
  • The consent's ? goes to the Docs view when it exists; there is no "privileges" docs page yet.

One decision for the owner: on touch the #215 mockup revealed the action pill with a left swipe; #242 gives the left swipe to End/Close. I kept #242's swipes and the long-press menu on touch; the hover pill is pointer-only.

Next: run the new specs, production-build screenshots at DPR 2/3, scripts/verify fast.

**J106 progress** (2026-11-02). Branch `row-actions-242-215` (pushed), head `bfaf96155`; typecheck (`bun run check`) clean on dev-02 at `15bfac3c5`. Done, one commit per concern: 1. `33e91b0c9` merge of `sidebar-pill-259` (#259, scope added by the owner) onto `origin/dev` `17d282a18`. Conflicts: the two `inline-rename.ts` modules (dev's account card and #259's) are now **one** field: #259's `beginInlineRename` / `placeOverName` / `onDoubleActivate`; dev's `inlineRename(target, …)` stays as a thin wrapper over it (account card unchanged), `.ui-rename-input` became `.ui-inline-rename`. Data path of a rename stays dev's (#293). 2. `08c1cef27` shared `row-menu.ts` + `row-confirm.ts` (+ `Spring.fling`, window menu opening at a point, danger row), ported from `97597e740`. 3. `7eefe5674` `toolbar/row-actions.ts` + tree wiring: right-click, long press, Shift+F10/menu key, trackpad/touch swipes, End asks in its row, Rename through `BranchedMenu.rename(id)` (the shared field), palette rows for the focused row. 4. `79da821ac` hover action pill, F2, Delete (#215). 5. kv-list `panel` + `15bfac3c5` Access level row and consent (#215, D286). 6. `bfaf96155` Playwright specs (row-menu, row-gestures, row-ask, replacement-alignment, row-swipe-continuity, sidebar-rename-remove, access-level). **Missing backends (not invented):** - **End session**: the product inventory has `can.end = false` (#100; no leg-A verb, `contracts/wire.md`: the server never signals a shim). The in-row End, the left swipe and Delete-on-a-session are built behind `can.end`; in the product they do not appear until #100 lands (the test double can end). - **Privileged access**: no server endpoint raises the agent's privileges with a once-used secret. The row and consent are built against `Adapters.privilege` (`sessions/privilege.ts`, a `PrivilegeService`); the product leaves it unset, so the "Access level" row does not show. The test double implements it (`?privilege=<scenario>`). - **Host removal** and **host rename** are real: removal uses `adapters.hostRemoval` (`/remote/hosts/remove/*`, passkey flow, so it asks in its own card, not in the row); a host renames through `mesh.node.rename` (#259), so only a host the Mesh knows has Rename. - The consent's `?` goes to the Docs view when it exists; there is no "privileges" docs page yet. **One decision for the owner:** on touch the #215 mockup revealed the action pill with a left swipe; #242 gives the left swipe to End/Close. I kept #242's swipes and the long-press menu on touch; the hover pill is pointer-only. Next: run the new specs, production-build screenshots at DPR 2/3, `scripts/verify fast`.
Author
Owner

J106 evidence for #242: row menu, swipes and End asking in its row, in the real product (production build of the tracer, Chromium, headless; against the test double, where the inventory can end sessions). Branch row-actions-242-215. Screenshots at 1440×900 DPR 2 (desktop) and 393×852 DPR 3 (phone), ink and paper. I read each one at full size; they are not judged as final visuals.

What the captures show: the session menu (right-click / long press), the host menu, End asking in its own row starting at the label's x ("End?" is the short form the desktop's 218 px row needs; the phone's row has room for "End session?"), the phone swipes (End revealed after a short left swipe, Open beside after a short right swipe).

Note: End and the left swipe appear in the product only once the inventory can end a session (#100); the test double can.

desktop-ink-session-menu
desktop-ink-host-menu
desktop-ink-end-asks-in-row
desktop-paper-session-menu
desktop-paper-end-asks-in-row
phone-ink-session-menu
phone-ink-swipe-end-revealed
phone-ink-end-asks-in-row
phone-ink-swipe-beside-revealed
phone-paper-session-menu
phone-paper-swipe-end-revealed
phone-paper-end-asks-in-row

**J106 evidence for #242: row menu, swipes and End asking in its row, in the real product (production build of the tracer, Chromium, headless; against the test double, where the inventory can end sessions).** Branch `row-actions-242-215`. Screenshots at 1440×900 DPR 2 (desktop) and 393×852 DPR 3 (phone), ink and paper. I read each one at full size; they are not judged as final visuals. What the captures show: the session menu (right-click / long press), the host menu, End asking in its own row starting at the label's x ("End?" is the short form the desktop's 218 px row needs; the phone's row has room for "End session?"), the phone swipes (End revealed after a short left swipe, Open beside after a short right swipe). Note: End and the left swipe appear in the product only once the inventory can end a session (#100); the test double can. ![desktop-ink-session-menu](https://git.kayg.org/attachments/15a4b34a-3aeb-44e4-bd3f-67f1404204df) ![desktop-ink-host-menu](https://git.kayg.org/attachments/be5b9ac6-8669-477a-aa1e-91016b9441b9) ![desktop-ink-end-asks-in-row](https://git.kayg.org/attachments/b36d9645-92ae-4271-b9ae-5fb180beab65) ![desktop-paper-session-menu](https://git.kayg.org/attachments/90c9d4b8-d693-4567-bc31-9e5dda089f53) ![desktop-paper-end-asks-in-row](https://git.kayg.org/attachments/be41adbf-e7c9-4f41-bf05-010f28384fd6) ![phone-ink-session-menu](https://git.kayg.org/attachments/ed442ddd-3d23-4bdd-8e9a-a50dde63ab8d) ![phone-ink-swipe-end-revealed](https://git.kayg.org/attachments/5258bde9-9bf4-4a84-b34c-850717a4fd1a) ![phone-ink-end-asks-in-row](https://git.kayg.org/attachments/b54e47aa-99be-409d-b397-b830baa693b9) ![phone-ink-swipe-beside-revealed](https://git.kayg.org/attachments/8aa2dfe9-01c2-495a-81ef-7b6d91ebffdc) ![phone-paper-session-menu](https://git.kayg.org/attachments/fc89acbc-5ecf-4955-b851-497b54feef4c) ![phone-paper-swipe-end-revealed](https://git.kayg.org/attachments/817b9843-11fb-413c-b4c0-eb8c28a21980) ![phone-paper-end-asks-in-row](https://git.kayg.org/attachments/098d316b-ebe3-4caf-a629-ba3eed48b5f8)
Author
Owner

J106 finish. Branch row-actions-242-215, head 82c54c678, pushed (base origin/dev 17d282a18, merged with dev 99668d8ab along the way). Built into the real product, no mock flag. Evidence screenshots (production build, DPR 2 and 3) are in the two comments above on #242 and #215.

What is built

  • #259 brought in as the base: merge of sidebar-pill-259; the two inline-rename.ts modules (dev's and #259's) are now one field (#259's beginInlineRename; dev's inlineRename is a thin wrapper, .ui-rename-input is gone). Rename's data path is dev's (#293).
  • #242: right-click, long press, Shift+F10 / menu key, trackpad sideways scroll, left and right swipes; End asks in its own row starting at the label's x; the continuous right swipe; every action of the focused row is a palette row. Escape closes a revealed row or the question first.
  • #215: hover pill (Rename, End/Remove; pointer only), double click and double tap rename (through the shared field), F2, Delete, remove host; "Access level" row and the consent from a window's pill → Host tab; palette "Allow full access on ".
  • Row actions, menu, swipes and pill load with the sidebar (on-demand chunk), not with the canvas.

Missing backends (not invented, see earlier comment): End session (inventory can.end is false, #100): End, the left swipe and Delete-on-a-session do not appear in the product until it lands; privileged access (no server endpoint): the row and consent exist behind Adapters.privilege, unset in the product; host rename works only for hosts the Mesh knows (mesh.node.rename); host removal uses the existing passkey flow (its own card, not in-row). The consent's "?" goes to the Docs view; there is no privileges docs page yet.

For the owner: on touch #215's mockup revealed the pill with a left swipe, #242 gives the left swipe to End/Close: I kept #242's swipes and the long-press menu on touch; the pill is hover-only.

Tests (Playwright, production build, test double; desktop 1440×900 and phone 393×852): row-menu, row-gestures, row-ask, replacement-alignment (≤ 0.5 px, DPR 2 and 3), row-swipe-continuity, sidebar-rename-remove, access-level, plus #259's mesh-rename adapted to dev. Last full set (head 91440dc79): 94 passed, 4 failed: 3 in sessions-canvas.spec.ts (lines 170, 370, 479) fail identically on unmodified origin/dev 17d282a18 (measured: 3 failed / 19 passed there), and the 4th (double click on an exited session whose list re-sorts) was fixed afterwards; sidebar-rename-remove.spec.ts on 82c54c678: 10 passed.

Gate: scripts/verify fast does NOT pass: one failure, the deferred JavaScript budget. The full gate ran on 8c548ce0c (dev-02); since then only TypeScript changed (git diff 8c548ce0c HEAD -- crates Cargo.toml Cargo.lock scripts is empty). Rust part, verbatim:

| Rust gate                 | Result       |
+---------------------------+--------------+
| fmt                       | PASS         |
| VT native fmt             | PASS         |
| CLI plugin compile-out    | PASS         |
| clippy                    | PASS         |
| SSH runtime test helper   | PASS         |
| real-binary fixture paths | PASS         |
| test                      | PASS         |
| SSH inode reuse fixture   | PASS         |
| shim process-per-user     | PASS         |
| cargo-deny                | PASS         |
| gate architecture         | PASS         |
| static builds             | PASS         |
+---------------------------+--------------+
x86_64: size 22422864 bytes; baseline 22418256; delta +4608 bytes (report only, D243 amended 2026-11-01)
aarch64: size 20454096 bytes; baseline 20453280; delta +816 bytes (report only)

TypeScript part re-run on the final head (82c54c678, tsc and every bun test group: 0 fail), then:

JavaScript transfer, critical: identity=1006850 gzip=313843/327680 brotli=261710/273408 bytes
JavaScript transfer, deferred: identity=179031 gzip=62025/61440 brotli=54702/55296 bytes
JavaScript transfer, onDemand: identity=304405 gzip=121081/20480 brotli=107917/18432 bytes
JavaScript transfer, onDemand largest chunk chunk-f7w4g32v.js: gzip=15464/20480 brotli=13803/18432 bytes (class total gzip=121081 brotli=107917, not limited)
error: production deferred JavaScript exceeds its compressed transfer budget

Measured against dev (99668d8ab, same command): critical 311,046 gzip, deferred 61,276 (164 B under its cap), onDemand 109,459. Before I moved the row code on demand the deferred class was 68,009; now it is 62,025, i.e. 585 B gzip over the 60 KiB cap (brotli is under). By the source diff the rest is the Mesh host rename of #259 and the tree's rename routing; I did not measure it per module, and I did not touch the gate. Needs the orchestrator/owner: ratchet the deferred cap (D188 rule: measured size rounded up to a KiB plus a margin) or tell me what to cut.

Commits (oldest first):

82c54c678 test(tracer): the rename double click aims at the name, as a person does (#215)
03701a66c ui: a double click is still one when the second release lands on the gap the rebuilt list left (#259, #215)
91440dc79 details: the consent pane stays in view while it grows into the popover (#215)
86ad8dc65 ui: a double click renames the row the first press was on, even if the list re-sorted under the pointer (#259, #215)
73f0710cc perf: the row menu, swipes and hover pill load with the sidebar, not with the canvas (D188, #242, #215)
8e0150821 sidebar: the pill ends a session with the stop square, and hides while the name is being edited (#215)
2f4ab7945 details: the consent pane spans the whole row and is brought into view when it opens (#215)
a61603233 ui: a double click renames even when the first click rebuilt the list (#259, #215)
8c548ce0c sidebar: the hover pill sits left of a row's marks and notes, which keep their tooltips (#215, #259)
1f041d24f Merge origin/dev (99668d8ab) into row-actions-242-215
30094bf01 test(tracer): opt-in review captures of the row menu, swipes, rename and consent (#242, #215)
2fe75432f test(tracer): #259's rename checks follow dev's connection icon and the renamable sessions (#259, #212, #215)
fa3131756 ui: a rename field takes the free room after a name that a clip cuts short (#259, #215)
99668d8ab Merge decisions-2026-11-02: D163 GotaTun on Linux, D317 docs structure
1d8af5c4a decisions: D163 Linux engine is GotaTun; D317 user docs structure
cdff83eb0 Merge taste-2026-11-02: owner review rows from 2026-11-02
9ef53bbb9 taste: windows start at the layout's size and never overlap
d67670c56 taste: descriptions say what a thing does, not what state it is in
d251c0ad8 taste: content sits inside its container with an even inset
69ba50588 taste: Settings rows scroll as a whole, not window by window
203fd67d3 taste: pill menus centre on their pill; no dead buttons
4c8e22611 taste: windows keep their natural width and the canvas scrolls; popovers follow their anchor
a479a8760 Merge size-baseline-ratchet: static size baselines match current dev (D243)
a8926703a verify: ratchet the static size baselines to the current dev measurement (D243)
c85e53e54 ui: a rename field on a fine pointer types in the size of the name it replaces (#259, #215)
3213ae21a palette: "Allow full access on <host>" opens the machine's consent (#215, D286)
3f2c9aeab test(tracer): every gesture and key of the sidebar's row menu, swipes, rename and consent (#242, #215)
0a4dd245b details: an "Access level" row and a consent that asks before the agent gets full access (#215, D286)
fea95e752 ui: a key/value row can carry a pane that opens under it (#215, D160)
5784444f1 sidebar: an action pill on hover, F2 renames and Delete removes the focused row (#215)
1b3992370 sidebar: right-click, long press, Shift+F10 and swipes on rows; End asks in its row (#242, D309)
a6498b99c ui: one row menu and swipe component, and the in-row question, for every list of rows (#242, D309)
294042b56 Merge fix-dev-red: dev green again after #291 (#307)
d7984ca7d ui: the anchored popover opens at a point, the window menu gets a danger row
9919b28b1 ui: a spring can be flung, so a released drag carries on from the finger's speed (#242, D70)
33e91b0c9 Merge sidebar-pill-259: rename Mesh hosts in place, detached icon, pinned account pill (#259)
502d0fc7e Stabilize clean shim exit observation under load #307
f15a74866 Fix J96 server test regressions after #291
66d25769d sidebar: the tick, cross and dot on a session row get a tooltip in plain words (#259)
e60f12434 test: the sidebar's tick, cross and dot explain themselves in a tooltip (#259)
44b3256f1 sidebar: a detached session shows an icon, not the word (#259)
648cc7774 test: a detached session in the sidebar shows an icon with a "Detached" tooltip (#259)
85cb920ee test: the rename field and the widened name pill never overlap the → pill (#259)
9fe1b7041 ui: the inline rename field stays inside the name's own box (#259)
c747d9fbb test: the rename field must not sit under the status dot (#259)
e86c2baf2 test: opt-in review captures of the pinned sidebar pill (#259)
845aa3e2c test: browser spec for renaming Mesh hosts in place (#259)
126c97190 palette: "Rename <host>" for the Mesh's hosts (#259)
16756de44 sidebar: rename a Mesh host by double click or double tap in the Views tree (#259)
cae06fe17 mesh: rename a host by double click or double tap on its card (#259)
ce31a7b52 ui: field placed over a name, and a double tap that survives a rebuilt list (#259)
e3d803ff2 mesh: rename a host through mesh.node.rename in the Mesh API adapter (#259)
711032f75 ui: one inline-rename field and one double-tap gesture for every in-place rename (#259)
0172555f7 sidebar: the account pill stays pinned once the inbox card has come and gone (#259)

VM cleanup: my Rust and tracer build dirs on dev-02 are deleted; worktrees ~/worktrees/j106* remain until the orchestrator prunes them.

**J106 finish.** Branch `row-actions-242-215`, head **`82c54c678`**, pushed (base `origin/dev` `17d282a18`, merged with dev `99668d8ab` along the way). Built into the real product, no mock flag. Evidence screenshots (production build, DPR 2 and 3) are in the two comments above on #242 and #215. **What is built** - #259 brought in as the base: merge of `sidebar-pill-259`; the two `inline-rename.ts` modules (dev's and #259's) are now one field (#259's `beginInlineRename`; dev's `inlineRename` is a thin wrapper, `.ui-rename-input` is gone). Rename's data path is dev's (#293). - #242: right-click, long press, Shift+F10 / menu key, trackpad sideways scroll, left and right swipes; End asks in its own row starting at the label's x; the continuous right swipe; every action of the focused row is a palette row. Escape closes a revealed row or the question first. - #215: hover pill (Rename, End/Remove; pointer only), double click and double tap rename (through the shared field), F2, Delete, remove host; "Access level" row and the consent from a window's pill → Host tab; palette "Allow full access on <host>". - Row actions, menu, swipes and pill load with the sidebar (on-demand chunk), not with the canvas. **Missing backends (not invented, see earlier comment):** End session (inventory `can.end` is false, #100): End, the left swipe and Delete-on-a-session do not appear in the product until it lands; privileged access (no server endpoint): the row and consent exist behind `Adapters.privilege`, unset in the product; host rename works only for hosts the Mesh knows (`mesh.node.rename`); host removal uses the existing passkey flow (its own card, not in-row). The consent's "?" goes to the Docs view; there is no privileges docs page yet. **For the owner:** on touch #215's mockup revealed the pill with a left swipe, #242 gives the left swipe to End/Close: I kept #242's swipes and the long-press menu on touch; the pill is hover-only. **Tests** (Playwright, production build, test double; desktop 1440×900 and phone 393×852): `row-menu`, `row-gestures`, `row-ask`, `replacement-alignment` (≤ 0.5 px, DPR 2 and 3), `row-swipe-continuity`, `sidebar-rename-remove`, `access-level`, plus #259's `mesh-rename` adapted to dev. Last full set (head `91440dc79`): 94 passed, 4 failed: 3 in `sessions-canvas.spec.ts` (lines 170, 370, 479) fail identically on unmodified `origin/dev` `17d282a18` (measured: 3 failed / 19 passed there), and the 4th (double click on an exited session whose list re-sorts) was fixed afterwards; `sidebar-rename-remove.spec.ts` on `82c54c678`: 10 passed. **Gate: `scripts/verify fast` does NOT pass: one failure, the deferred JavaScript budget.** The full gate ran on `8c548ce0c` (dev-02); since then only TypeScript changed (`git diff 8c548ce0c HEAD -- crates Cargo.toml Cargo.lock scripts` is empty). Rust part, verbatim: ``` | Rust gate | Result | +---------------------------+--------------+ | fmt | PASS | | VT native fmt | PASS | | CLI plugin compile-out | PASS | | clippy | PASS | | SSH runtime test helper | PASS | | real-binary fixture paths | PASS | | test | PASS | | SSH inode reuse fixture | PASS | | shim process-per-user | PASS | | cargo-deny | PASS | | gate architecture | PASS | | static builds | PASS | +---------------------------+--------------+ x86_64: size 22422864 bytes; baseline 22418256; delta +4608 bytes (report only, D243 amended 2026-11-01) aarch64: size 20454096 bytes; baseline 20453280; delta +816 bytes (report only) ``` TypeScript part re-run on the final head (`82c54c678`, `tsc` and every `bun test` group: 0 fail), then: ``` JavaScript transfer, critical: identity=1006850 gzip=313843/327680 brotli=261710/273408 bytes JavaScript transfer, deferred: identity=179031 gzip=62025/61440 brotli=54702/55296 bytes JavaScript transfer, onDemand: identity=304405 gzip=121081/20480 brotli=107917/18432 bytes JavaScript transfer, onDemand largest chunk chunk-f7w4g32v.js: gzip=15464/20480 brotli=13803/18432 bytes (class total gzip=121081 brotli=107917, not limited) error: production deferred JavaScript exceeds its compressed transfer budget ``` Measured against dev (`99668d8ab`, same command): critical 311,046 gzip, deferred **61,276** (164 B under its cap), onDemand 109,459. Before I moved the row code on demand the deferred class was 68,009; now it is 62,025, i.e. **585 B gzip over the 60 KiB cap** (brotli is under). By the source diff the rest is the Mesh host rename of #259 and the tree's rename routing; I did not measure it per module, and I did not touch the gate. **Needs the orchestrator/owner: ratchet the deferred cap (D188 rule: measured size rounded up to a KiB plus a margin) or tell me what to cut.** Commits (oldest first): ``` 82c54c678 test(tracer): the rename double click aims at the name, as a person does (#215) 03701a66c ui: a double click is still one when the second release lands on the gap the rebuilt list left (#259, #215) 91440dc79 details: the consent pane stays in view while it grows into the popover (#215) 86ad8dc65 ui: a double click renames the row the first press was on, even if the list re-sorted under the pointer (#259, #215) 73f0710cc perf: the row menu, swipes and hover pill load with the sidebar, not with the canvas (D188, #242, #215) 8e0150821 sidebar: the pill ends a session with the stop square, and hides while the name is being edited (#215) 2f4ab7945 details: the consent pane spans the whole row and is brought into view when it opens (#215) a61603233 ui: a double click renames even when the first click rebuilt the list (#259, #215) 8c548ce0c sidebar: the hover pill sits left of a row's marks and notes, which keep their tooltips (#215, #259) 1f041d24f Merge origin/dev (99668d8ab) into row-actions-242-215 30094bf01 test(tracer): opt-in review captures of the row menu, swipes, rename and consent (#242, #215) 2fe75432f test(tracer): #259's rename checks follow dev's connection icon and the renamable sessions (#259, #212, #215) fa3131756 ui: a rename field takes the free room after a name that a clip cuts short (#259, #215) 99668d8ab Merge decisions-2026-11-02: D163 GotaTun on Linux, D317 docs structure 1d8af5c4a decisions: D163 Linux engine is GotaTun; D317 user docs structure cdff83eb0 Merge taste-2026-11-02: owner review rows from 2026-11-02 9ef53bbb9 taste: windows start at the layout's size and never overlap d67670c56 taste: descriptions say what a thing does, not what state it is in d251c0ad8 taste: content sits inside its container with an even inset 69ba50588 taste: Settings rows scroll as a whole, not window by window 203fd67d3 taste: pill menus centre on their pill; no dead buttons 4c8e22611 taste: windows keep their natural width and the canvas scrolls; popovers follow their anchor a479a8760 Merge size-baseline-ratchet: static size baselines match current dev (D243) a8926703a verify: ratchet the static size baselines to the current dev measurement (D243) c85e53e54 ui: a rename field on a fine pointer types in the size of the name it replaces (#259, #215) 3213ae21a palette: "Allow full access on <host>" opens the machine's consent (#215, D286) 3f2c9aeab test(tracer): every gesture and key of the sidebar's row menu, swipes, rename and consent (#242, #215) 0a4dd245b details: an "Access level" row and a consent that asks before the agent gets full access (#215, D286) fea95e752 ui: a key/value row can carry a pane that opens under it (#215, D160) 5784444f1 sidebar: an action pill on hover, F2 renames and Delete removes the focused row (#215) 1b3992370 sidebar: right-click, long press, Shift+F10 and swipes on rows; End asks in its row (#242, D309) a6498b99c ui: one row menu and swipe component, and the in-row question, for every list of rows (#242, D309) 294042b56 Merge fix-dev-red: dev green again after #291 (#307) d7984ca7d ui: the anchored popover opens at a point, the window menu gets a danger row 9919b28b1 ui: a spring can be flung, so a released drag carries on from the finger's speed (#242, D70) 33e91b0c9 Merge sidebar-pill-259: rename Mesh hosts in place, detached icon, pinned account pill (#259) 502d0fc7e Stabilize clean shim exit observation under load #307 f15a74866 Fix J96 server test regressions after #291 66d25769d sidebar: the tick, cross and dot on a session row get a tooltip in plain words (#259) e60f12434 test: the sidebar's tick, cross and dot explain themselves in a tooltip (#259) 44b3256f1 sidebar: a detached session shows an icon, not the word (#259) 648cc7774 test: a detached session in the sidebar shows an icon with a "Detached" tooltip (#259) 85cb920ee test: the rename field and the widened name pill never overlap the → pill (#259) 9fe1b7041 ui: the inline rename field stays inside the name's own box (#259) c747d9fbb test: the rename field must not sit under the status dot (#259) e86c2baf2 test: opt-in review captures of the pinned sidebar pill (#259) 845aa3e2c test: browser spec for renaming Mesh hosts in place (#259) 126c97190 palette: "Rename <host>" for the Mesh's hosts (#259) 16756de44 sidebar: rename a Mesh host by double click or double tap in the Views tree (#259) cae06fe17 mesh: rename a host by double click or double tap on its card (#259) ce31a7b52 ui: field placed over a name, and a double tap that survives a rebuilt list (#259) e3d803ff2 mesh: rename a host through mesh.node.rename in the Mesh API adapter (#259) 711032f75 ui: one inline-rename field and one double-tap gesture for every in-place rename (#259) 0172555f7 sidebar: the account pill stays pinned once the inbox card has come and gone (#259) ``` VM cleanup: my Rust and tracer build dirs on dev-02 are deleted; worktrees `~/worktrees/j106*` remain until the orchestrator prunes them.
Author
Owner

Decision recorded (owner, 2026-11-02, J106 round 2): on touch, #242's swipes (left = End/Close, right = Open beside) and the long-press menu win; #215's swipe-to-reveal pill is not built. The hover action pill is pointer-only (hover and a fine pointer). The backends flagged earlier (End behind #100, privileged access with no endpoint) stay hidden in the product.

Round 2 progress (branch row-actions-242-215, head 187f81759): deferred JS is cut, not the cap raised. Per-module numbers are in the commit messages of 59f6f46e2 and 3b05ee668. Deferred gzip 62,041 → 60,107 B (cap 61,440, headroom 1,333 B; brotli 52,994 of 55,296); merged with J100's ui-no-overshoot-scroll 58,696 B. Running verify fast and the browser specs on this head now.

**Decision recorded (owner, 2026-11-02, J106 round 2):** on touch, #242's swipes (left = End/Close, right = Open beside) and the long-press menu win; #215's swipe-to-reveal pill is not built. The hover action pill is pointer-only (hover and a fine pointer). The backends flagged earlier (End behind #100, privileged access with no endpoint) stay hidden in the product. **Round 2 progress (branch `row-actions-242-215`, head `187f81759`):** deferred JS is cut, not the cap raised. Per-module numbers are in the commit messages of `59f6f46e2` and `3b05ee668`. Deferred gzip 62,041 → 60,107 B (cap 61,440, headroom 1,333 B; brotli 52,994 of 55,296); merged with J100's `ui-no-overshoot-scroll` 58,696 B. Running `verify fast` and the browser specs on this head now.
Author
Owner

J106 round 2 finish. Branch row-actions-242-215, head 5fa6334d7, pushed. Based on and merged with dev 816f9ab3e (J100 merged; also docs sections #311 and recovery #309). The cap is not raised: the code is cut.

Deferred JS (gzip bytes, bun run build && bun transfer-budget.ts)

dev 816f9ab3e this head
deferred 59,889 / 61,440 (brotli 52,786 / 55,296) 58,737 / 61,440 (brotli 51,856 / 55,296): headroom 2,703 B, brotli 3,440 B
critical 311,553 / 327,680 313,050
onDemand largest chunk 15,447 / 20,480 15,472

Per module, against dev 816f9ab3e (identity B / estimated gzip B: each module's share of its chunk by bytes in the output, from the bundler's metafile; head 9b3365e02, the last numbers are within 20 B of this head):

  • deferred: toolbar/tree.ts +495 / +170 (the hooks only: loader of the row actions, the openRename hook, the phone's close delay), sessions/live.ts +62 / +30, mesh/lazy.ts +40 / +15, mesh/index.ts +39 / +15, toolbar/palette.ts +36 / +18, model/reconcile.ts +27 / +13, views/world.ts -146 / -37, toolbar/viewlist.ts -2,092 / -693, pill-morph.ts -2,719 / -994 (both now on demand behind a thin hook).
  • critical: branched.ts +1,126 / +636, double-activate.ts (the gesture, new) +759 / +430, tooltip.ts +239 / +105, icons.ts +158 / +61, spring.ts +51 / +21, core-screen.ts +35 / +18 (13.2 KB under its cap).
  • on demand now (no longer in either class): the rename field (inline-rename.on-demand.ts), toolbar/row-rename.on-demand.ts, mesh/rename.on-demand.ts, toolbar/palette-hosts.on-demand.ts (remove host, allow full access, rename a Mesh host rows), toolbar/viewlist.on-demand.ts, and with them the row menu, swipes, pill and the in-row question.
    Merged with J100 alone (before J100 reached dev, ui-no-overshoot-scroll onto this branch): deferred 58,696.
    Lesson recorded in the commit message: a dynamic import from deferred code of a module that on-demand chunks also import statically is turned into a static link by the bundler and moves nothing, so every importer of an on-demand module has to be on demand too.

Behaviour notes. Right-click, swipes and the pill attach a few milliseconds after the sidebar first opens (#tree[data-rows="ready"]); a double click before that does nothing. The view list opens from the first tap (it waits for its small chunk if idle loading has not finished). The palette's host rows are fetched as the canvas comes up. The row swipe has no bounce now (J100's rule; it did not compile against the new spring type, found by merging).

Gate: scripts/verify fast exit 0 on 5fa6334d7 (dev-02), verbatim:

5fa6334d7 test(tracer): the typing check puts the focus back on the page instead of waiting for a textarea (#259)
| Rust gate                 | Result       |
+---------------------------+--------------+
| fmt                       | PASS         |
| VT native fmt             | PASS         |
| CLI plugin compile-out    | PASS         |
| clippy                    | PASS         |
| SSH runtime test helper   | PASS         |
| real-binary fixture paths | PASS         |
| test                      | PASS         |
| SSH inode reuse fixture   | PASS         |
| shim process-per-user     | PASS         |
| cargo-deny                | PASS         |
| gate architecture         | PASS         |
| static builds             | PASS         |
+---------------------------+--------------+

==> Compiler metadata generator checks
8452:PT_INTERP: absent; size: 22468304 bytes; baseline 22418256; delta +50048 bytes (report only, D243 amended 2026-11-01)
8488:PT_INTERP: absent; size: 20487864 bytes; baseline 20453280; delta +34584 bytes (report only, D243 amended 2026-11-01)
9617:JavaScript transfer, critical: identity=1005057 gzip=313050/327680 brotli=261034/273408 bytes
9618:JavaScript transfer, deferred: identity=168016 gzip=58737/61440 brotli=51856/55296 bytes
9619:JavaScript transfer, onDemand: identity=325049 gzip=130653/20480 brotli=116421/18432 bytes
9620:JavaScript transfer, onDemand largest chunk chunk-jvsymf4e.js: gzip=15472/20480 brotli=13810/18432 bytes (class total gzip=130653 brotli=116421, not limited)
9235: 517 pass 9236: 0 fail 9446: 107 pass 9447: 0 fail 9517: 17 pass 9518: 0 fail 9708: 39 pass 9709: 0 fail VERIFY_EXIT=0

(Earlier runs failed on this branch and were fixed, in order: a tsc error in the row spring vs the no-overshoot type; two unit tests (the palette rename test and a cubic-bezier overshoot in the swipe icon, caught by J100's no-overshoot.test.ts); a Rust vt_credit test and a 5 s unit test timeout on a loaded machine, each passing when rerun alone and in the next full run.)

Browser specs (production build, test double, 1440×900 / 393×852; last full run on 75078b6d7): 194 passed, 12 failed. Eleven fail identically on unmodified dev 816f9ab3e (measured there: canvas.spec 302, 345, 626; clusters.spec 702, 837; glass-ghost 4 cases; sessions-canvas 170 and the manager-on-demand check), and the twelfth, "another device typed last" (sessions-canvas), was a focus race that fails about half the runs on dev (5 of 9) and every run here; fixed in the spec (the focus probe shows build-01's textarea holding the focus while nix-cache is active) and passing 4 of 4 on 5fa6334d7. palette-polish (375×667) and mesh-rename desktop failed in some runs and pass in the final one; the palette label measured 57.866 px on dev as well.

Commits of this round (oldest first):

5fa6334d7 test(tracer): the typing check puts the focus back on the page instead of waiting for a textarea (#259)
75078b6d7 test(tracer): "typing takes the size over" types into the window it is about (#259)
433b2781b test(tracer): #259's tree rename checks wait for the row actions to attach (#259, #215)
8faf00970 palette: the host rows' chunk is fetched as the palette is installed, not at idle (D188, #215)
b0cea3b72 test(tracer): the row-menu right-click check waits for the menu before Escape (#242)
1da414c09 test, ui: the palette rename test follows the Mesh rename module; the armed swipe icon eases without overshoot (#215, #242)
2690c3346 ui: the row spring is typed as a SpringConfig, so it compiles against the no-overshoot spring (#242)
9b3365e02 Merge origin/dev (816f9ab3e, J100 merged) into row-actions-242-215
816f9ab3e Merge ui-no-overshoot-scroll: no elastic overshoot; wheel scrolls the content under it (#308, D275)
fae83a7b1 sidebar: row actions announce when they are attached; the palette's host rows load promptly (D188, #242, #215)
b5099e3be Merge docs/j114-sections: user docs in D317 sections (#311)
79a43ae3c ui: the row spring states `bounce: 0`, which both the current and the no-overshoot spring types accept (#242)
0ef98fea8 docs: one heading per setting, with its default and range only in its quick facts (#311, D317)
7dd462e9e docs: sections, nested addresses, redirects and a check for "?" targets (#311, D317)
4b40ac8b4 tracer: moving a window and the free canvas's gestures load on demand (D188, #308)
187f81759 Merge origin/dev (92ee8d5ea) into row-actions-242-215
3464c4e13 ui: the row swipe settles without a bounce (#242, TASTE "No overshoot, ever")
3b05ee668 perf: the view list and its pill morph load on demand behind a thin hook (D188)
59f6f46e2 perf: the rename field, the tree's rename routing, the Mesh host rename and the host rows of the palette load on demand (D188, #215, #259)
92ee8d5ea Merge fix-recovery-restart: account recovery always waits 24 measured hours (#309, D25)
77616905a Checkpoint measured recovery progress each minute and at shutdown (#309)
52ad241ae Confirm recovery countdown readiness with server status (#309, D25)
c56854dbb tracer: wheel specs and TASTE rule for the wheel over docs pages and terminals (D275, #308)
7788d5bd8 tracer: a vertical wheel scrolls the content under the pointer; no elastic bump at the ends (D275, #308)
c400f6f94 taste: no overshoot, ever (#308)
214f4eea4 tracer: a unit check rejects springs and easings that overshoot (#308)
7dd27c0b7 ui: every spring is critically damped and every curve ends without overshoot (#308)
716183781 Send recovery completion notice in revoked socket teardown (#309)
3b0123b4b Measure recovery waits with persisted monotonic uptime (#309, D25)
8440d50e9 Restart expired recovery with fresh safety deadlines (#309)

VM: my ~/worktrees/j106* worktrees and targets on dev-02 are pruned.

**J106 round 2 finish.** Branch `row-actions-242-215`, head **`5fa6334d7`**, pushed. Based on and merged with dev `816f9ab3e` (J100 merged; also docs sections #311 and recovery #309). The cap is not raised: the code is cut. **Deferred JS (gzip bytes, `bun run build && bun transfer-budget.ts`)** | | dev 816f9ab3e | this head | |---|---|---| | deferred | 59,889 / 61,440 (brotli 52,786 / 55,296) | **58,737** / 61,440 (brotli 51,856 / 55,296): headroom **2,703 B**, brotli 3,440 B | | critical | 311,553 / 327,680 | 313,050 | | onDemand largest chunk | 15,447 / 20,480 | 15,472 | Per module, against dev 816f9ab3e (identity B / estimated gzip B: each module's share of its chunk by bytes in the output, from the bundler's metafile; head `9b3365e02`, the last numbers are within 20 B of this head): - **deferred:** `toolbar/tree.ts` +495 / +170 (the hooks only: loader of the row actions, the `openRename` hook, the phone's close delay), `sessions/live.ts` +62 / +30, `mesh/lazy.ts` +40 / +15, `mesh/index.ts` +39 / +15, `toolbar/palette.ts` +36 / +18, `model/reconcile.ts` +27 / +13, `views/world.ts` -146 / -37, **`toolbar/viewlist.ts` -2,092 / -693, `pill-morph.ts` -2,719 / -994** (both now on demand behind a thin hook). - **critical:** `branched.ts` +1,126 / +636, `double-activate.ts` (the gesture, new) +759 / +430, `tooltip.ts` +239 / +105, `icons.ts` +158 / +61, `spring.ts` +51 / +21, `core-screen.ts` +35 / +18 (13.2 KB under its cap). - **on demand now (no longer in either class):** the rename field (`inline-rename.on-demand.ts`), `toolbar/row-rename.on-demand.ts`, `mesh/rename.on-demand.ts`, `toolbar/palette-hosts.on-demand.ts` (remove host, allow full access, rename a Mesh host rows), `toolbar/viewlist.on-demand.ts`, and with them the row menu, swipes, pill and the in-row question. Merged with J100 alone (before J100 reached dev, `ui-no-overshoot-scroll` onto this branch): deferred 58,696. Lesson recorded in the commit message: a dynamic import from deferred code of a module that on-demand chunks also import statically is turned into a static link by the bundler and moves nothing, so every importer of an on-demand module has to be on demand too. **Behaviour notes.** Right-click, swipes and the pill attach a few milliseconds after the sidebar first opens (`#tree[data-rows="ready"]`); a double click before that does nothing. The view list opens from the first tap (it waits for its small chunk if idle loading has not finished). The palette's host rows are fetched as the canvas comes up. The row swipe has no bounce now (J100's rule; it did not compile against the new spring type, found by merging). **Gate: `scripts/verify fast` exit 0** on `5fa6334d7` (dev-02), verbatim: ``` 5fa6334d7 test(tracer): the typing check puts the focus back on the page instead of waiting for a textarea (#259) | Rust gate | Result | +---------------------------+--------------+ | fmt | PASS | | VT native fmt | PASS | | CLI plugin compile-out | PASS | | clippy | PASS | | SSH runtime test helper | PASS | | real-binary fixture paths | PASS | | test | PASS | | SSH inode reuse fixture | PASS | | shim process-per-user | PASS | | cargo-deny | PASS | | gate architecture | PASS | | static builds | PASS | +---------------------------+--------------+ ==> Compiler metadata generator checks 8452:PT_INTERP: absent; size: 22468304 bytes; baseline 22418256; delta +50048 bytes (report only, D243 amended 2026-11-01) 8488:PT_INTERP: absent; size: 20487864 bytes; baseline 20453280; delta +34584 bytes (report only, D243 amended 2026-11-01) 9617:JavaScript transfer, critical: identity=1005057 gzip=313050/327680 brotli=261034/273408 bytes 9618:JavaScript transfer, deferred: identity=168016 gzip=58737/61440 brotli=51856/55296 bytes 9619:JavaScript transfer, onDemand: identity=325049 gzip=130653/20480 brotli=116421/18432 bytes 9620:JavaScript transfer, onDemand largest chunk chunk-jvsymf4e.js: gzip=15472/20480 brotli=13810/18432 bytes (class total gzip=130653 brotli=116421, not limited) 9235: 517 pass 9236: 0 fail 9446: 107 pass 9447: 0 fail 9517: 17 pass 9518: 0 fail 9708: 39 pass 9709: 0 fail VERIFY_EXIT=0 ``` (Earlier runs failed on this branch and were fixed, in order: a `tsc` error in the row spring vs the no-overshoot type; two unit tests (the palette rename test and a `cubic-bezier` overshoot in the swipe icon, caught by J100's `no-overshoot.test.ts`); a Rust `vt_credit` test and a 5 s unit test timeout on a loaded machine, each passing when rerun alone and in the next full run.) **Browser specs** (production build, test double, 1440×900 / 393×852; last full run on `75078b6d7`): 194 passed, 12 failed. Eleven fail identically on unmodified dev `816f9ab3e` (measured there: `canvas.spec` 302, 345, 626; `clusters.spec` 702, 837; `glass-ghost` 4 cases; `sessions-canvas` 170 and the manager-on-demand check), and the twelfth, "another device typed last" (`sessions-canvas`), was a focus race that fails about half the runs on dev (5 of 9) and every run here; fixed in the spec (the focus probe shows build-01's textarea holding the focus while nix-cache is active) and passing 4 of 4 on `5fa6334d7`. `palette-polish` (375×667) and `mesh-rename` desktop failed in some runs and pass in the final one; the palette label measured 57.866 px on dev as well. Commits of this round (oldest first): ``` 5fa6334d7 test(tracer): the typing check puts the focus back on the page instead of waiting for a textarea (#259) 75078b6d7 test(tracer): "typing takes the size over" types into the window it is about (#259) 433b2781b test(tracer): #259's tree rename checks wait for the row actions to attach (#259, #215) 8faf00970 palette: the host rows' chunk is fetched as the palette is installed, not at idle (D188, #215) b0cea3b72 test(tracer): the row-menu right-click check waits for the menu before Escape (#242) 1da414c09 test, ui: the palette rename test follows the Mesh rename module; the armed swipe icon eases without overshoot (#215, #242) 2690c3346 ui: the row spring is typed as a SpringConfig, so it compiles against the no-overshoot spring (#242) 9b3365e02 Merge origin/dev (816f9ab3e, J100 merged) into row-actions-242-215 816f9ab3e Merge ui-no-overshoot-scroll: no elastic overshoot; wheel scrolls the content under it (#308, D275) fae83a7b1 sidebar: row actions announce when they are attached; the palette's host rows load promptly (D188, #242, #215) b5099e3be Merge docs/j114-sections: user docs in D317 sections (#311) 79a43ae3c ui: the row spring states `bounce: 0`, which both the current and the no-overshoot spring types accept (#242) 0ef98fea8 docs: one heading per setting, with its default and range only in its quick facts (#311, D317) 7dd462e9e docs: sections, nested addresses, redirects and a check for "?" targets (#311, D317) 4b40ac8b4 tracer: moving a window and the free canvas's gestures load on demand (D188, #308) 187f81759 Merge origin/dev (92ee8d5ea) into row-actions-242-215 3464c4e13 ui: the row swipe settles without a bounce (#242, TASTE "No overshoot, ever") 3b05ee668 perf: the view list and its pill morph load on demand behind a thin hook (D188) 59f6f46e2 perf: the rename field, the tree's rename routing, the Mesh host rename and the host rows of the palette load on demand (D188, #215, #259) 92ee8d5ea Merge fix-recovery-restart: account recovery always waits 24 measured hours (#309, D25) 77616905a Checkpoint measured recovery progress each minute and at shutdown (#309) 52ad241ae Confirm recovery countdown readiness with server status (#309, D25) c56854dbb tracer: wheel specs and TASTE rule for the wheel over docs pages and terminals (D275, #308) 7788d5bd8 tracer: a vertical wheel scrolls the content under the pointer; no elastic bump at the ends (D275, #308) c400f6f94 taste: no overshoot, ever (#308) 214f4eea4 tracer: a unit check rejects springs and easings that overshoot (#308) 7dd27c0b7 ui: every spring is critically damped and every curve ends without overshoot (#308) 716183781 Send recovery completion notice in revoked socket teardown (#309) 3b0123b4b Measure recovery waits with persisted monotonic uptime (#309, D25) 8440d50e9 Restart expired recovery with fresh safety deadlines (#309) ``` VM: my `~/worktrees/j106*` worktrees and targets on dev-02 are pruned.
Author
Owner

Closed by the orchestrator during the 2026-11-09 night housekeeping (owner order: "close stale prs/issues"). The work has landed on dev, and the latest note here is a finish or merge note (J387 inventory on #436). Reopen if anything is still missing.

Closed by the orchestrator during the 2026-11-09 night housekeeping (owner order: "close stale prs/issues"). The work has landed on dev, and the latest note here is a finish or merge note (J387 inventory on #436). Reopen if anything is still missing.
kayg closed this issue 2026-11-08 19:04:27 +00:00
Sign in to join this conversation.
No labels
launch-qa
No milestone
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
kayg/infraternal#242
No description provided.