Mockup: Settings in sections (components, tabs, nested sidebar, one setting per ⌘K hit) #304
Open
opened 2026-11-02 05:59:21 +00:00 by kayg
·
28 comments
No Branch/Tag specified
main
j470b-server-mesh-rejoin
mesh-compat-382
j444b-d381-key-wins-flood
j461b-macos-utun-reader-thread
j475b-remove-host-motion
fix-reconnect-new-link
j481-d380
dev
j479-mesh-soak
fix/j476-host-facts
j475-motion-pill-split
j470-mac-node-join
root-upgrade-d376
j474-review-merge
latency-targets-120hz
nightly-suite-shards
gotatun-pin-j469
macos-utun-reader-thread
fix-flood-echo-stall
wip/j416
motion-fast-ease-out
mesh-addhost-j259
takeover-close-terminals-d368
kbd-instant-followups
fix-trust-key-double-click
nightly-suite-partial-report
appwin-icons-j207
rusqlite-slice1
swipe-content-first-d374
mesh-mtu-381
addhost-instant-open
glass-contrast-d365-mock
glass-contrast-d365
signout-followups-442
fix-startup-toast-red
research-gotatun-matrix-j317
themes-sync-j304
fix-load-flakes
fix-nix-zig-patch
fix-compute01-browser-baseline
ratchet-size-baseline-419
predict-auto-d130
revoke-coverage-d367
nightly-suite-queue-timeout
nightly-browser-suite
fix-rustsec-2026-0459
fonts-ioskeley-obel
log-retention-d375
fix-kbd-no-anim-427
fix-dev-red-specs-2
takeover-proof-305-j205
wip/j410-server-pump
ui-consistency-d372
fix-osc52-clipboard
libghostty-vt-1.0
forget-retired-host-d369
j404-merge-426
fix-setup-lock-race
fix-touch-select-426
revoke-access-report-ui
fix-predictive-echo-specs
fix-selinux-agent-exec
wip/j395-checkpoint2
wip/j395
j391-review-scratch
ui-consistency-j195-deferred-rebased
fix-rustc-paths-421
decisions-wording-341
fix-install-suite-red
fix-dev-rtt-specs
fix-pending-removal-align
fix-privileged-skip
fix-install-suite-404
review-j368
mesh-dns-j254
revoke-access-report-d356b
revoke-privilege-round5
fix-removal-confirm
review-j360
gotatun-rotation-367
deps-refresh-340
review-j354
review-J351
review-j350
addhost-takeover-d359
revoke-report-items-347
revoke-end-sessions-d362
review-j348
size-mesh-ssh-346
size-trim-337
revoke-access-diff-d356
j259-pre-rebase-b06c5a6
j305-ended-at-start-spec
addhost-sudo-consent
fix-layout-real-specs-411
fix-shell-open-411
fix-console-hosts-373
fix-shell-exit
fuzz-host-name-353
fix-host-details-410
macos-filter-j197
research-gotatun-tricks
revoke-p3-j216l
stale-state-pill
revoke-followups-j216k
revoke-progress-j216e
backup/macos01-20261106/lume/j197
backup/macos01-20261106/lume/appwin-icons-j207-stash0
backup/macos01-20261106/claude/stash-0
backup/macos01-20261106/claude/stash-1
backup/macos01-20261106/claude/J80-macos-s1
backup/macos01-20261106/claude/J80
backup/macos01-20261106/claude/J80-slice1-20261102
backup/macos01-20261106/claude/J16b-appwin-on-dev
backup/macos01-20261106/claude/appwin-launch-idle-146
backup/macos01-20261106/claude/J80-s1-run
wip/j259
trust-285-p3c
runtime-lock-j216f
mesh-ssh-p3-j175
tun-proof-p3b
trust-285-p3
terminal-polish-j271
tun-proof-p3
ssh-install-flakes-j216i
fuzz-fixes-j264
trust-285-a
trust-285-b
restart-oversized-fixture-j198
backup/macos01-20261106/lume/appwin-icons-j207
restart-bound-j216h
up-preflight-p3-j198
backup/macos01-20261106/lume/j251
up-preflight-j198
wip/up-preflight-j198-j245-p2
wip/up-preflight-j198-j245-p1
agent-fsync-offloop-j196
wip/up-preflight-j198-j245
settings-offscreen-j231
wip/up-preflight-j198-j226-inspection
wip/j103f
themes-j206
wip/up-preflight-j198-j226
flakes-j216c
backup/macos01-20261106/claude/j197
flakes-j216b
backup/macos01-20261106/claude/j197-red
wip/up-preflight-j198-review
flakes-j216
backup/macos01-20261106/claude/appwin-icons-j207
engineering-j208b
appwin-mock-j209
toast-stack-j165
engineering-j208
decisions-d351
decisions-d350
decisions-d349
appearance-presets-mock-j129
decisions-d348
docs-audit-spec
doc-coverage-baseline-raise
decisions-d347
decisions-d346b
decisions-d346
j88h-profile
ui-consistency-j195-deferred
ui-consistency-j195
engineering-practices-j194
preferred-login-ui-j166
signin-pools-263-j174
macos-node-265-s1
decisions-d345
decisions-d344
proxy-cgroup-j164
verify-quick-fuzz-329
proxy-start-io-j168
timing-flakes-j163
up-263-s1
mcp-events-j147
verify-quick-fuzz-j158
proxy-p3-j159
agent-resource-j157-detect
wip/j103d-final
remote-cancel-hang-j155
proxy-traefik-281-j62d
j149-verify-quick
proxy-traefik-281-j62b
j150-drop-unnamed
wip/j79d-red-r4
wip/j103d-d332
rootless-toast-j142
wip/j103d-head
wip/j103d
j125c-mcp
macos-build-j136
backup/macos01-20261106/claude/j136
wip/j79d-red-cli
wip/j79d-red-server
j121-link-liveness
j118c-tracer-failures
wip/j79c-head
release-desktop-j131
j124c-signed-macos
wip/j79c-red-p3
wip/j79c-red-p23
wip/j79c-red-p22
merge-j128-check
perf-deferred-j128
sidebar-toggle-260
j127-shortcut-changed-dot
j125-mcp
j118-tracer-failures
j126-account-summary
settings-sections-mock-j92
j120-pinch-lock
sidebar-292
backup/macos01-20261106/claude/j120
taste-2026-11-03
row-actions-242-215
backup/macos01-20261106/claude/stash-0-untracked
backup/macos01-20261106/claude/J80-265-s1-run
backup/macos01-20261106/claude/J80-macos-s1-20261102
j112-canvas-commands
ui-no-overshoot-scroll
fix-recovery-restart
backup/macos01-20261106/claude/stash-1-untracked
taste-2026-11-02
size-baseline-ratchet
machine-cards-structure-j108
j109-boot-copy-mockups
fix-dev-red
wip/up-263-s1
j95b-settings-rows
proxy-traefik-281
j95-option-rows
docs-human-j91
docs-keys-palette
fix-flood-1013-270-j38d
mesh-ssh-s1
mesh-ssh-s0
addhost-d291-tunnel
test-stability-load
mesh-relay-220
repro-296
shim-thp-off-24
mesh-pins-258-v2
mesh-dns
signin-d311-merged
docs-pages
ui-size-283
fix-ui-batch-specs
wip/j12b-edge-update
gate-on-arm
fix-rename-sync-293
trust-285-j60b
fix-focus-ring-clip
integ-ui-1101
edge-update-v2
signin-d311
taste-2026-11-01
layout-per-tab-250
ui-approved-splitopt-224
ui-approved-splitopt-224-on-dev
icon-text-centre-282
ui-approved-189-212-216
research-reverse-proxy
transfer-budget-320
review-mesh-pins-258-r2
sidebar-pill-259
review-mesh-relay-220
wip/j12-edge-update-v2
nix-package
status-crash-loop-237
fix-dev-test-failures
fix-fixture-socket-path
wip/mesh-relay-220-pre-dev-advance-rebase
fix-canvas-side-clip
research-head-to-head
frosted-real-256
review-mesh-pins-258
wip/mesh-relay-220-pre-final-rebase
review-layout-per-tab-250-r2
broad-suite-triage
nix-devshell
review-status-crash-loop-237-r3
wip/nix-devshell-pre-p3
taste-frosted-real
wip/code-serve-demo-2026-10-30
wip/code-serve-glass-2026-10-30
wip/code-serve-clusters-2026-10-30
wip/code-merge-release94-dev-2026-10-30
wip/rproxy-delta-scratch-2026-10-30
wip/stale-note-257-staged-2026-10-30
wip/d241-size-staged-2026-10-30
review-broad-suite-207
wip/mesh-pins-258-pre-split
wip/mesh-relay-220-pre-rebase
mesh-measure-220
plan-211-update
review-edge-autoupdate-r3
perf24-reconnect
review-stale-note-r2
release-prod-live
d241-shell-marker
review-mesh-pins-server-258
review-revocation-r3
review-setup-token-r2
review-sync-journal-r3
wip/review-mesh-pins-258-prune-review-1995fee46
frosted-scroll-256
sync-journal-r3
revocation-per-account-wip
review-tokio-asyncfd-0386
review-sync-p3s
wip/stash-8by64-stash0-2026-10-30
mesh-drag-r2
setup-token-data-wip
release-9-4
auth-busy-1013
mesh-view-overlap
sync-p3s
review-auth-busy-wake
review-readd-r8-wip
mesh-drag-bounds
audit-auth-93
app-windows-stream-start
review-authority-cap-r3
app-windows-r7-measure
readd-minimal-r6
readd-minimal-r5
app-windows-r7-soak
readd-minimal-r4
app-windows-r7
app-windows-r6
readd-minimal-r3
readd-minimal-r2
readd-minimal
merge-release8-dev
review-busy-page-liveness-r2
review-busy-page-liveness
mesh-view-trim
review-authority-read-retry-r2
review-remove-uninstall-r2
release-retry-reattach
release-retry
review-remove-uninstall
review-authority-read-retry
app-windows-ship
mesh-autoswitch-p2
mesh-ssh
mesh-relay
mesh-macos-node
screen-and-control
session-labels
review-real-logins-r5
review-real-logins-r4
review-real-logins-r3
shim-memory-r2
review-real-logins-r2
shim-memory
shadow-addhost-instant
shadow-real-logins
shadow-same-session-flood
shadow-prod-perf-fix
hosts-from-server
app-windows-real
app-windows-transport
release-prod-6w
mesh-policy-verify
quiet-close-toast
dev-merge-r4
review-mesh-agent-transport
review-app-windows-transport
settings-roundtrip
review-release-pipeline-r4
mesh-agent-transport
ended-strip-fix
review-audit-ca-update-d244
settings-rows
phone-width
signout-clear
fix-restart-tests
dev-merge-rp
signer-hardening
review-audit-ca-update
terminal-fidelity
review-audit-ca-update-wip
mesh-integrate
review-mesh-agent-transport-515d3712
review-mesh-dataplane-feec1988
mesh-dataplane
signout
research-canvas-node
wip/review-renderer-cost
wip/review-terminal-fidelity
padlock-glyph
review-release-pipeline-2e95b689
phone-polish
sidebar-polish
inbox-generic
review-mesh-dataplane-378d4055
prod-batch
ui-inbox
ui-ca-unlock
ui-machine-sections
review-mesh-dataplane-a5f744fb
tls-session-prod
session-bounds-prod
fix-dead-session
session-bounds
tls-session
palette-polish
shortcuts-d222
research-appmeta
phone-gutter
ui-centre-button
wip/ui-centre-button
wip/tls-session
review-addhost-breakit
ui-platform
renderer-cost
remote-agents
mesh-api
ssh-bootstrap
prod-hotfix2
prod-fixes
review-remote-agents
review-mesh-dataplane
session-life
research-browser
review-mesh-api
research-capture
review-mesh-api-round3
review-mesh-api-round1
gate-stability
review-gate-stability
review-relay-direct
review-mesh-api-findings
proto-sessions
font-picker
proto-addhost
proto-windows
mesh-core
latency-gate
research-bsd
research-discovery
keytray-mods
mock-core
ui-tweaks
fix-motion-sel
fix-motion
integrate2
fix-robust
t-web
t-server
vt-ghostty
fix-snap-echo
t-web-auth
review-vt2
t-agent
lane-protocol
lane-shim
lane-auth
s1-base
s1-contracts
s1-workspace
No results found.
No labels
launch-qa
Milestone
Clear milestone
No items
No milestone
Projects
Clear projects
No items
No project
Assignees
Clear assignees
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#304
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Mockup (J92): Settings in sections — components on the left, tabs inside, nested in the sidebar, one setting per ⌘K hit.
Request (owner, 2026-11-02)
Settings need better sections: "a row per subcomponent? imitating a sidebar selection + tabs? of course in our actual sidebar this would appear as nested settings."
Proposed structure (to refine):
.internal) | Rulesupcode 10 min)Each key setting shows its default, its allowed range, a Reset and a one-line plain explanation; out-of-range values are refused inline.
Deliverable: a LIVE mockup in the mock harness (
?mock=1&proto=clusters…): the Settings window with a left column of components and tabs inside; the main sidebar showing nested Settings › Component › Tab; ⌘K jumping straight to one setting; desktop and phone (on phone the drill-down list replaces the left column). Served on dev-02, linked from the mockups index. Screenshots at 1440×900 DPR 2 and 393×852 DPR 3; ±0.5 px alignment checked.Not product code. Nothing is saved, no server API is touched. The owner reviews the visuals.
Plan and estimate (posted within 15 min of start)
Base:
origin/devb0e79b31e. Branch:settings-sections-mock-j92.validate(setting, text)that refuses out-of-range input with a plain message, and onesearch(query)used by ⌘K. ~30 min.packages/ui— reuse the capsule tabs, key/value rows, switch, slider, icon buttons and warm tooltip. New there: only a setting row (title, one-line explanation, value field with unit, "default · range" caption, Reset icon) and a section list (left column on desktop, drill-down list on phone). Look first for anything existing to extend. ~1.5 h.?settings=1) — a Settings view window with the two-pane layout; sidebar tree rows nested Settings › Component › Tab (tree.ts / branched.ts); ⌘K rows per setting that open the component, tab and the row (highlighted); phone drill-down with back. Existing sections move into the model (Appearance, Terminal, Phones, About reuse their current panels as tabs). ~1.5 h.mockups.html; Playwright check of left edges and centre lines (±0.5 px); screenshots 1440×900 @2 and 393×852 @3 on this issue. ~1 h.Estimate: about 4.5 h in total. I stop and report at 9 h.
NOT building: persistence, server API, real validation on the server, the Forwarding feature (shown as "later"), any change to the product Settings view, general form framework.
Questions for the owner are listed on the issue as I find them (I will pick the obvious default and move on).
Started. Branch
settings-sections-mock-j92, baseorigin/devb0e79b31e3. Worktree~/Developer/Worktrees/infraternal-J92on the control host (edit only); builds and captures oninfraternal-dev-02-std. Plan and estimate are in the issue body (about 4.5 h).Correction from the owner (2026-11-02), replaces the plan in the issue body
No tabs anywhere. New model:
Settings › Mesh › Keys, following the focused window. Each pill navigates: Settings opens the view list, Mesh lists the components (jump to a row), Keys lists the groups of this row.Where each setting lives is still being decided
The whole map is ONE table (
catalog.ts: component → groups → settings, with default, range, unit, explanation). Placeholders where unsure (flagged in the table). Moving a setting is a one-line edit.How I build the rows (decision, so the owner can overrule)
The canvas already has a grid of windows (D212: a window may span columns, band heights are shared). Desktop: one group of columns, one band per component, each window one group; a row with fewer groups gives the spare width to its last window. Phone: the same windows as plain columns (column = n-th group of each component), because a 3-screen-wide window cannot exist on a phone. The breadcrumb and sidebar read the same table, so they stay right either way.
Steps and estimate (from now): about 6 h; I stop and report at 12 h
packages/ui: a setting row (title, one-line explanation, value field with unit, "Default · range", Reset icon button, inline refusal). Reuse key/value list, switch, icon buttons, tooltip. 1 h.?settings=sections: the Settings view built from the table (desktop grid, phone columns); each window body renders its group. Existing sections (Appearance, Window sizes, Toolbar, Shortcuts, About, Hosts…) become groups of rows (they reuse their current panels unchanged). 1.5 h.depthon tree leaves); ⌘K rows per setting and per group. 1.5 h.NOT building: persistence, server API, tabs, the Forwarding feature (an empty "later" window), changes to the product Settings view.
Ready for review: Settings as rows of windows (mockup)
Try it: http://10.69.69.117:47650/mockups.html (first entry, #304), or directly http://10.69.69.117:47660/?mock=1&proto=clusters&scene=3&settings=sections
What to try (desktop and phone):
wireguard,dns,browser stays,tokenorabout. Each jumps to the window and fades a quiet fill on the row.400: refused inline ("Pick 1 to 30 days. Still using 7 d."), nothing saved; Escape restores. Type336 h: understood as 14 d, and a Reset icon (tooltip "Reset to 7 d") appears. Reset puts the default back.How it is built (read this before judging the layout)
apps/tracer/src/canvas/mock/settings-map/catalog.ts(guesses markedPLACEHOLDER, your numbersOWNER). Windows, breadcrumb, sidebar and ⌘K all read it. Moving a setting is a one-line edit.⌘K → Settings: …entries and?still open them.Evidence (final head, dev-02, headless Chromium)
test/settings-sections.spec.ts), all within ±0.5 px: every row flush with equal 16 px gutters; the windows of a row level (top and bottom) and exactly equal in width; no overlaps; title, help, field and range on one left edge; field and Reset on one centre line; breadcrumb pills on one centre line and centred on the screen (±1 px); the sidebar's nested glyph sits under its parent's name; phone targets ≥ 44 px.tscclean.01–08) and 393×852 @3× (p01–p05). I looked at each at full size; I do not judge them as final.Findings (not fixed, not in scope)
browser signed infinds nothing for "Browser stays signed in for". It applies to every palette row. Words in any order would be friendlier.Questions for the owner (I picked the default and moved on)
Gate for the first version (head
06f46c08e), verbatimscripts/verify faston infraternal-dev-02-std, clean worktree, through build-slot:The
testfailure is not from this branch: 4 of 128 tests failed, allrestart::tests::*, eachexceeded 57.4s; status=signal: 9 (SIGKILL)on a VM with three other gates running (test result: FAILED. 123 passed; 4 failed). This diff changes 0 Rust/Cargo files (21 files, +1261/−11, all TypeScript and CSS). The same four tests, rerun alone on the same build with--test-threads=1:test result: ok. 18 passed; 0 failed. This is the wall-clock dependence tracked in #207. I did not run the gate on an unmodifiedorigin/dev(it would be a second 15-minute Rust build for a diff with no Rust).New instruction from the owner (replaces the table)
The owner's current map (single mapping table, Title Case, no brackets in names):
upcode 10 min, default install mode system or user, default sign-in account, join the mesh automatically) · UpdatesEach window gets a ? in its title pill that opens the matching docs heading as a window in the Docs cluster, beside it (placement still being confirmed: easy to move). Breadcrumb: Settings › Row › Window.
Plan and estimate (from now): about 4 h; I report at 8 h
catalog.tsto this map (still ONE table), with the docs link of each window in the same table (heading id), so moving a setting or a link is one line. 30 min.NOT building: persistence, server API, a docs system (I link into the existing one), changes to the product Settings view.
Ready for review (second version): the owner's map, a "?" per window, a Docs cluster
Try it: http://10.69.69.117:47650/mockups.html (first entry, #304), or directly http://10.69.69.117:47660/?mock=1&proto=clusters&scene=3&settings=sections (deep links:
&at=mesh.keys,&at=machines.new-machines,&at=you.apps,&at=terminal.scrollback,&at=about)Head
74f3eaf3consettings-sections-mock-j92(five atomic commits). Everything is built from ONE table,apps/tracer/src/canvas/mock/settings-map/catalog.ts: the owner's map of 2026-11-02, in order, Title Case. Moving a setting, renaming a window or pointing its "?" at another docs heading is a one-line edit there. Guesses are markedPLACEHOLDER, the owner's numbersOWNER.What to try (desktop and phone):
wireguard,dns,browsers stay,token,about.400in Connection Keys: refused inline;336 his read as 14 d; Reset appears. Machines › New Machines: a segmented choice (Install For, Sign In As) and a switch (Join The Mesh), each with its own Reset. You › Apps: the key list with Revoke (asks first). You › Devices: browsers with Sign Out.Evidence (final head, dev-02, headless Chromium)
tscclean.01–14) and 393×852 @3× (p01–p05). I looked at each; I do not judge them as final.Findings (not fixed)
clusters.css); otherwise "Profile" shows as "Pr…".browsers signed infinds nothing for "Browsers Stay Signed In For". Applies to every palette row.⌘K → Settings: …entries land on the nearest window.Questions for the owner (default picked, moved on)
docs-button.ts) and where the Docs cluster sits (right of Settings, under it on a phone; one functionbuildDocsViewand one argument of the flow host).Finish: head
74f3eaf3cbb625e5156c2c3ff820e54931958013onsettings-sections-mock-j92(baseb0e79b31e,origin/dev)Five atomic commits:
34e6bedebui: a setting row and the rules that refuse a bad value;e4cc06e47ui: a tree leaf may sit under the leaf above it;beb346692canvas: docs pages can open in a view of their own, and be opened by name;a4943b8e9mockup: Settings as rows of windows;74f3eaf3ctest. 25 files, TypeScript and CSS only (0 Rust or Cargo files).Review comment with URL, what to try, evidence, findings and questions: the previous comment on this issue. The preview is served at http://10.69.69.117:47660 (bun test double, PID 4044413 on infraternal-dev-02-std, started by me) and linked from http://10.69.69.117:47650/mockups.html.
scripts/verify faston this head (dev-02, clean worktree, through build-slot), verbatimtestfailed on 10 of 764 server tests (test result: FAILED. 698 passed; 10 failed; 56 ignored): 8 inbootstrap_runtime::remote_backend::tests::*(for exampleThe matching static infraternal binary is unavailable.,Elapsed(())),enrollment::migration_tests::hostname_migration_upgrades_release6_copy_without_changing_canvas_or_checksums(left: 33 right: 32) andremote_http::tests::enrollment_http_is_bound_single_use_and_preserves_token_while_locked.Not from this branch, shown: the same command (
cargo test --workspace --locked -- bootstrap_runtime::remote_backend enrollment::migration_tests remote_http::tests::enrollment_http_is_bound_single_use, same build) on the unmodified baseb0e79b31egivestest result: FAILED. 30 passed; 10 failedwith the same 10 tests, and on this head the same. The diff touches no Rust. (The first version's gate,06f46c08e, failed a different set, fourrestart::tests::*killed after ~57 s under load; they pass alone, 18 passed. #207 tracks that one. Both are the dev baseline, not this work.) Everything else passes, including the static builds.Other checks on this head (dev-02)
tscclean (TSC_EXIT=0), production-flag build ok.test/settings-sections.spec.ts: 2 passed (desktop 1440×900 @2×, phone 393×852 @3×), all alignment within ±0.5 px (details in the review comment).Cleanup
Deleted my Rust
target/(the VM was at 21 GB free, below the 25 GB floor; now 94 GB) and my scratch files. Nothing of mine runs on either VM except the preview server above. Stop it withkill 4044413when the owner has reviewed; to re-serve:bash ~/worktrees/j92-serve.sh(build:INFRATERNAL_CLUSTERS_PREVIEW=1 bun run build.tsin~/worktrees/J92/apps/tracer).How to test (three lines)
wireguard.400in Connection Keys.Owner decision applied: "?" is the first button of each window's action group
Try it: http://10.69.69.117:47650/mockups.html (first entry, #304; one more link, "With a No access card in Console"), or http://10.69.69.117:47660/?mock=1&proto=clusters&scene=3&settings=sections&at=mesh.keys&noaccess=1
Head
21cdaab2094f9b9ffe197549f2bc5df8083fae8consettings-sections-mock-j92(six atomic commits). The in-pill "?" is gone; it is now? ◫ ⊟ ⌸ ✕on a terminal (?, split right, split down, sessions, close),? ✕on an error card and on the add-host dialog, and just?on a Settings window (a card with one action never collapses into "…").Shortcut: the proposed keys are both taken, so I picked the free pair that D222's own rule gives
^_(undo in readline and emacs), and the panel already has Ctrl+Shift+/. Ctrl+Alt is AltGr, so it cannot be a default.?panel under Canvas ("Read about this window — Ctrl Shift Alt /", capture15), and in ⌘K as "Read about this window" with its keys in the hint. The button, the shortcut and the ⌘K row call one function.What it opens
The matching docs heading as a window in the Docs cluster, which sits right of Settings (under it on a phone). Settings windows read their link from the table; examples: a terminal → Multiplexer, the add-host dialog → "Host join token", a No access card → "At a glance". A window with no page yet says so ("There is no page about this yet."). A docs window itself has no "?".
Close-ups (attached):
closeup-<d2|d3|p2|p3>-<settings|terminal|no-access|add-host>-<header|actions>.pngd2 = desktop DPR 2, d3 = desktop DPR 3, p2 and p3 = phone 393×852 at DPR 2 and 3. Plus
15-shortcuts-panel,01-mesh-keys,07-docs-cluster.Alignment, measured (not looked at), at DPR 2 and DPR 3 on desktop and phone, ±0.5 px
For the 22 Settings windows, a terminal, the add-host dialog and a No access card: "?" is the first button; every button is one size on one centre line with equal gaps; every icon sits dead centre in its button (x and y); the group is the title pill's height and on its centre line; every group ends the same distance from its window's edge. The 20 earlier checks (rows flush, gutters, title/help/control/range on one left edge, breadcrumb centre, 44 px targets) still pass.
tscclean.Findings and a question
? ✕(two actions, so within the rule) and a Settings window just?, at the usual small size with a 44 px hit area. Nothing is added beyond two. If the owner wants the phone header untouched, the "?" can stay in ⌘K and the canvas row on phones only (one condition inframe.ts).Finish (second round): head
21cdaab2094f9b9ffe197549f2bc5df8083fae8consettings-sections-mock-j92(baseb0e79b31e,origin/dev)Six atomic commits:
9b52069a1ui: a setting row, and the rules that refuse a bad value;76dff9d93ui: a tree leaf may sit under the leaf above it;f480b88fccanvas: docs pages can open in a view of their own, and be opened by name;6e21b22ffcanvas: "?" is the first button of a window's action group, with a shortcut;d43d22600mockup: Settings as rows of windows;21cdaab20test. 33 files, +1878/−30, TypeScript and CSS only (0 Rust or Cargo files).Review comment (URL, what to try, the key choice and its collisions, measured alignment, findings, captures): the previous comment. Preview: http://10.69.69.117:47660 (PID 4044413 on infraternal-dev-02-std, mine;
kill 4044413when reviewed), linked from http://10.69.69.117:47650/mockups.html.scripts/verify fast, dev-02, clean worktree, through build-slot, on0bcf45321verbatim(The final head
21cdaab20differs from it by one Playwright spec file: 8 lines, the add-host dialog opens with a retry. No Rust.verify fastdoes not run that file.)Why
testfailed, and why it is not this branch. This run: the linker was killed,ld returned 137(out of memory) while linking the examplemesh_revocation_fixture,error: could not compile infraternal-server, with three other jobs' gates running on the same VM ((test: 718s)). No test ran. The previous round's gate (head74f3eaf3c) did run the tests and failed 10 server tests (698 passed; 10 failed), and I showed the same 10 fail identically on the unmodified baseb0e79b31e(30 passed; 10 failedfor the same filtered command,The matching static infraternal binary is unavailable,Elapsed(()),left: 33 right: 32). The first round's gate failed 4restart::tests::*killed by wall-clock timeouts (they pass alone: 18 passed; #207). This diff contains 0 Rust/Cargo files, and 0 between74f3eaf3cand now; so the Rust gate rows are the dev baseline, three different ways. I did not get a greentestrow on any head: please do not read it as green. Everything else in the table passes, including the static builds.Other checks on the final head (dev-02)
tscclean; production-flag build ok.test/settings-sections.spec.ts: 4 passed (desktop, phone, the "?" examples and shortcut, the close-ups at DPR 2 and 3), alignment within ±0.5 px.Cleanup
Deleted my Rust
target/and scratch files from dev-02 (free disk now 36 GB, other jobs' gates are using the rest). No other process of mine is running except the preview server above.How to test (three lines)
Contract note from J101 (#302), for the "?" popover: the docs build now writes quick-facts excerpts into
/docs/index.json. Marker in the Markdown:> [!FACTS]directly under a heading (or under the page title for the page). Index shape:pages[].facts?: stringandpages[].headings[].facts?: string, plain text, at most 320 characters, absent when the page wrote none (preview the pagesummarythen). The same block is also shown on the page as a "Quick facts" panel. Branchdocs-readable-j101.Owner feedback applied: bigger breadcrumb, views menu in place, and "?" now opens a preview
Try it (same URL): http://10.69.69.117:47650/mockups.html (first entry, #304), or http://10.69.69.117:47660/?mock=1&proto=clusters&scene=3&settings=sections&at=mesh.keys&noaccess=1
Head
368136ec0onsettings-sections-mock-j92(11 atomic commits onb0e79b31e; the four new ones are009a758ac,f3d69d986,72ceb042b,368136ec0).1. "The breadcrumbs need to be bigger" — sized like the main top pill
I measured both in the same page before changing anything. Desktop: the breadcrumb pills already had the main pill's height (41.8 px) and icon (17.6 px) and a slightly larger type size (14.85 vs 14.3 px); what made them read smaller was the dimmed ancestor names, tighter padding and gap (13.2 px against 15.4 px, 6.6 against 8.8) and, on a phone, type at 13.5 px against the main pill's 16 px. They now take the main pill's padding, gap, 1 rem icon, weight and tracking (including the mono-font override), the body type size (never below the main pill's: 14.85 px desktop, 16 px phone) and full colour for every name. On a phone the group was also about 27 px left of centre (it hugged the left of its track); it is now on the centre line. Measured at ±0.5 px: pill height, icon size, weight equal to the main pill's; the group's centre = the screen's centre (±1 px) on desktop and phone. Close-ups:
closeup-<d2|d3|p2|p3>-breadcrumb.pngbesidecloseup-…-main-pill.png.2. "When Settings is clicked, it appears on the top left instead of in place" — fixed at the cause
The views list (and the
?shortcuts panel, the floating terminal and the palette) grow out of the top capsule. While the breadcrumb showed, I had hidden the capsule withdisplay: none, so its rectangle was empty and the panel opened at the top left (the same bug put the?shortcuts panel at the left edge in an earlier capture of mine). The capsule now stays in the layout as an invisible ghost with exactly the breadcrumb's rectangle, and what a morph writes on it (its fade, pointer-events, the palette's "covered" mark) is mirrored onto the breadcrumb, so all four panels start where the breadcrumb is and fade it, with no Settings code of its own. Measured on every animation frame of the open (a 900 ms recording): the panel's centre is the breadcrumb's centre and its top is the breadcrumb's top within 0.5 px, for the views list on desktop and phone and for the shortcuts panel on desktop; the breadcrumb fades to 0 while it is open and is fully visible and clickable after. Frames:morph-<d2|d3|p2|p3>-1…3.png(the breadcrumb, 60 ms, 140 ms, 320 ms after pressing Settings).I did not touch the elastic overshoot or the scrolling in the docs window (the video shows them; another job has them).
3. "?" opens a preview, not the page
> [!FACTS]text as it is (first sentence = lead, the next ones = bullets,summaryas the fallback) and propose one optional addition for tables on #302 (comment 74711, with the merge points). Until their build ships, the headings these windows point at get stand-ins in the same shape (mock/settings-map/docs-standin.ts).closeup-<d2|d3|p2|p3>-preview-<settings|terminal|no-access|add-host>.png; whole-screen07-preview.png,p03-preview.png,07b-docs-cluster.png.Tests (dev-02, final tree): 7 Playwright tests pass; unit tests: 10 for the value rules and 24 for the docs excerpt and source, the table and the shortcut keys, 0 failed;
tscclean.Findings and questions
docsview and J91's Docs view share an id and answer the same question; my expand icon'sDocsAdapter.openbecomes "fly to the page's window" there.summary(a lead only) for headings with no quick facts yet; most headings today. Quick facts per heading are what makes it useful, so writing them is the next step for the docs.docs-action.ts.⌘Kphrase match, five windows to a row being cramped for Apps and Devices, the phone-header action count (TASTE row 126).Finish (third round): head
368136ec0d3df88f3e7fa4d6a5c899dfb53e3c0aonsettings-sections-mock-j92(baseb0e79b31e,origin/dev)11 atomic commits, TypeScript and CSS only (0 Rust or Cargo files). This round added
009a758ac(ui: a preview popover and a bottom sheet),f3d69d986(canvas: "?" opens a preview from the docs index),72ceb042b(mockup: the breadcrumb is the main pill's size and what grows out of the top pill grows out of it) and368136ec0(test).Review comment with the results, the root causes and the 41 close-ups: the previous comment on this issue. The contract and merge points for the docs job are on #302 (comment 74711). Preview: http://10.69.69.117:47660 (PID 4044413 on infraternal-dev-02-std, mine;
kill 4044413when reviewed), linked from http://10.69.69.117:47650/mockups.html.scripts/verify fast, infraternal-dev-01-compute01, clean worktree, through build-slot, on this head, verbatimtest result: FAILED. 698 passed; 10 failed; 56 ignored((test: 1077s)): the same 10 server tests as on the unmodified baseb0e79b31e(8 inbootstrap_runtime::remote_backend::tests::*,enrollment::migration_tests::hostname_migration_upgrades_release6_copy_without_changing_canvas_or_checksums,remote_http::tests::enrollment_http_is_bound_single_use_and_preserves_token_while_locked). On the base, the same filtered command gives30 passed; 10 failedwith the same names (shown on this issue in the previous round); this round it fails the same way on x86 (compute01) as it did on arm (dev-02), so it is not machine-specific. This diff changes 0 Rust files. I still did not get a greentestrow on any head; please do not read it as green. Everything else passes, including the static builds.Other checks (dev-02, final tree)
tscclean; production-flag build ok.test/settings-sections.spec.ts: 7 passed (desktop, phone, the "?" examples and shortcut, the action-group close-ups, the preview, the breadcrumb and its morph, the breadcrumb close-ups), within ±0.5 px.Cleanup
Deleted my Rust
target/from compute01 and dev-02 and my scratch files. Nothing of mine runs on either VM except the preview server above.How to test (three lines)
Round 2 (owner: clipped sides, popover that does not follow, narrowed windows) and items 4 to 6: results and 24 close-ups
Try it (same URLs): http://10.69.69.117:47650/mockups.html (entry #304), or http://10.69.69.117:47660/?mock=1&proto=clusters&scene=3&settings=sections&at=mesh.keys
Head
a9fb92a36onsettings-sections-mock-j92(baseb0e79b31e). New commits this round, each one change:8f16db6a6(ui: popover mounted in its window),5a86aad69(mockup: natural widths, pill cap),ecfe45e6a(canvas: a step also stops at the bottom of a tall window),1c84eacec(canvas: a menu opened from a pill is centred on it),2a9519980(mockup: Views button removed),65043925e(mockup: windows as tall as their content),01fcb3529(mockup: Theme is two columns wide), the gesture fix, and the tests. 17 Playwright tests pass on dev-02 (the 7 from before and 10 new),tscclean, unit tests pass (stops 10, settings map 9, docs 23).1. Windows keep their natural width; the canvas scrolls
The desktop view was sized to the screen (each row split into equal parts of it). It is now one grid with a track per column of the longest row, every track the default window width; nothing reads the screen's width. A row longer than the screen is reached by the canvas pan and snap that exist (D159). Measured at 1440 x 900: every window's layout width equals another view's default width (Theme's is two columns, see below), windows of a row are level with equal gaps and a common left edge, none overlaps, the view is wider than the screen.
One thing I had to decide, please look at it: the canvas grid is one scroller only if some window crosses every seam between columns. A row's own windows never cross the seams between themselves, so the first seam could not be crossed by a left-aligned row of natural-width windows (the first column became a scroller of its own; I saw it in the first run: the first window of every row stood still while the rest moved). I gave Theme a default width of two columns (it holds a swatch grid, Background and two sliders), and the last window of each short row crosses the other seams. Rejected, with reasons in the commit: a hidden window spanning everything, a gap in one row, changing D212.
2. No clipping at any side
Cause: the title pill could use the whole header and pushed the action group out ("?" half cut). It now stops short by the group's width. Test at 1440x900, 393x852 and 1024x768: each of the 22 windows is flown into view; every control's box, grown by its focus ring (2 px + 2 px offset, measured from the computed outline after a keyboard focus), is inside its window and inside every clipping box between them (header: all four sides; body: both sides), the window is whole on screen, and the top bar's controls, pills and the MOCKUP tag are whole inside the screen with their rings. All pass within 0.5 px. Close-ups at DPR 2 (DPR 3 on the phone):
edge-2x-1440x900-window-right.png,-window-left,-topbar-right,-topbar-left,-screen, the same for 1024x768 andedge-3x-393x852-*.3. The "?" preview moves with its button
Cause: the popover floated over the screen and was placed once. It is now mounted inside the button's window and positioned in the window's own coordinates, so the camera's pan and zoom and a column's scroll move it in the same frame; no script follows. Test: open the "?" preview, pan the camera 300 px right and 300 px back, 40 frames each way, and a wheel pan; on every frame the offset between popover and button is the same within 0.5 px, the button really moved (> 250 px), and the preview closes once the button has left the screen. Frame strip:
pan-strip-1..4.png.Convention note: the existing details popover closes on any camera movement (
onFrame); the shared popover now follows and closes only when its anchor leaves the screen, as the new TASTE row says. Anything else that closes on camera movement stays as it was; say if you want those changed too.4. Menus from a pill are centred on the pill
Every breadcrumb pill's menu centre equals the pill's centre within 0.5 px at 1440x900 and 393x852 (or the screen's inset when that holds it back, which the test computes), and the grow origin is the pill's centre. The Settings pill's list (views) is centred on the Settings pill, no longer on the whole breadcrumb, and the rest of the breadcrumb fades with it. This touches the shared view list:
toggle(from?), default the top pill. Captures:20-menu-view|row|group.png,p20-menu-*.png(phone).5. The round Views button
Removed in the mockup. I could not reproduce "does nothing": on a desktop it opens the views list (a 340 px panel under the pill), in this mockup and in the plain scene alike, so in the product it is not a button with no action; it duplicates the top pill (and the phone's toolbar row has the same item). I therefore did not touch the product canvas; there is no product-branch commit. If you want the button gone from the product as a duplicate, that is one line in
toolbar/row.ts; say so and I will do it on its own branch.6. Settings rows scroll as a whole
Every Settings window is as tall as its content (heights differ: 176 to 1080 px at 1440 wide), has no scroll area, and no element inside a window has a vertical scroll area or a scrollTop. A wheel notch steps the single grid scroller, so every one of the 22 windows moves by the same offset (measured on every step, down and up, within 0.5 px). Two consequences I handled:
stepStops, pure and unit-tested). The test checks that each window's top and each window's bottom was on screen at some step. This changes product code (layout/stops.ts,columns.ts); for windows that fit, the stops are the same as before.camera/gestures.ts, wheel and two-finger).Captures:
scroll-d2-end.png,scroll-p3-column.png.Findings
20-menu-view.png). I did not touch it; it is the shared list's width.canScrollreads the column, which has no box in a group). Not touched; it is the "scrolling issue" that another job has, as far as I can tell.Finish (round 2 and items 4 to 6)
Head
a9fb92a36onsettings-sections-mock-j92(baseb0e79b31e). TypeScript and CSS only:git diff --stat b0e79b31e HEAD -- '*.rs' 'Cargo.*'is empty. The review comment with the results and 24 close-ups is the previous one on this issue. Preview: http://10.69.69.117:47660 (PID 4044413 on infraternal-dev-02-std, mine;kill 4044413when reviewed), linked from http://10.69.69.117:47650/mockups.html.scripts/verify fast, infraternal-dev-01-compute01, clean worktree, through build-slot, on this head, verbatimThe
testrow is red and I did not get a green one. In this runcargo teststopped at the first failing binary,status_restart::service_states_are_truthful_in_text_and_json("user/server/active: The status of part of this machine's setup is unknown."), after 459 s. That test passes alone on the same head (cargo test -p infraternal --test status_restart: 1 passed). To see the whole picture I ran the workspace with--no-fail-fast: 1752 tests passed and 21 distinct server tests failed (account_events review_revocation_r2 x4, bootstrap_runtime::remote_backend x8, enrollment migration, latest/release_payload staging x4, status/umask/restart tests, remote_http enrollment). The set differs from the 10 I reported on this branch two rounds ago and on the unmodified base, which says these tests are load- and environment-dependent on this VM; none of them touches anything this diff changes (0 Rust files, Rust tree byte-identical to the base). I did not run the base again this time. Please do not read the row as green.Other checks (dev-02, final tree)
tscclean; production-flag build ok.stepStopstest), settings map 9 (grid held as one group for an administrator and a member), docs 23, value rules 10; 0 failed.test/settings-sections.spec.ts: 17 passed (7 before; new: no clipped side at 1440x900, 393x852 and 1024x768; popover follows its button on a pan; menus centred on their pill at 1440 and 393; no Views button; whole-row wheel scrolling; ⌘K scroll to a setting; phone one-finger and two-finger scrolling), within 0.5 px (1 px for nothing).Cleanup
Deleted my Rust
target/and scratch files on compute01 and dev-02; stopped my leftover test processes by PID. Nothing of mine runs on either VM except the preview server above.Decisions I need from you
Round 3: windows start at the layout's size, nothing overlaps, and what I could not reconcile
Same URLs: http://10.69.69.117:47650/mockups.html (entry #304), http://10.69.69.117:47660/?mock=1&proto=clusters&scene=3&settings=sections&at=mesh.keys
Head
9c2762305onsettings-sections-mock-j92, rebased onto origin/dev294042b56(dev's own Docs view is now what the "?" opens; my own Docs view and flow-window plumbing are gone). 22 Playwright tests pass on dev-02,tscclean, unit tests pass (stops 10, settings map and docs 33).What was wrong
The Font-over-Theme overlap was my span hack, not the product: Theme spanned two columns and the windows that spanned were drawn at a fixed width on top of a grid that the drag then changed. All of it is removed.
1. Every window starts at the layout's size
The Settings view is plain columns, as every other view is: a column per component, its windows stacked in it, on a desktop and on a phone. Each column has
defaultWidth(what a terminal window gets from Settings → Window Sizes) and each windowh: 1(one screen). No span, no band, no grid. Test: every Settings window's width equals a terminal window's width (1440x900 and 393x852; and with Window Sizes set to Wide and Full width, and Full width on the phone); its height equals the layout's height unless its content is longer. Captures:01-mesh-keys.png(desktop),p01-mesh-keys.png(phone).2. Scrolling, and the conflict
3. Resizing never draws one window over another
Test (1440x900 with the four edges, 393x852 with the four corner handles that a press and hold shows): each handle of three Settings windows (Theme, Keys, Certificates) is dragged in and out; on every animation frame no two window boxes intersect (the Settings, Docs and Console views are watched; what is drawn of a window counts, not what is scrolled out of its column), and the drags did change the window. Product check: the same drags on three Console terminal windows also pass on this branch. This branch changes none of the resize code (
window-resize.ts,windows/frame.tsresize host,camera/are identical to dev; the diff against dev inlayout/is onlystops.tsandcolumns.ts, below), so I did not need a separate product commit; the overlap came from the mockup. I did not build a second copy of dev to run it there. Capture:narrowed-2x-1440x900.png(Theme narrowed by its right edge: Typing follows, nothing over anything). Skipped on the phone: up to 6 of the 24 handles lie below the screen's bottom edge for a window one screen tall.4. Product changes kept or reverted from round 2
camera/gestures.ts(a step over the empty part of a view): windows fill their columns now. Own revert commit with the reason.layout/stops.ts+columns.ts(stepStops): a step also stops with the bottom of a window taller than the screen in view. It is still needed because a desktop Settings window grows with its content (Typing is 1080 px tall at 1440x900). For windows that fit it gives the same stops as before. Justified in its commit.toolbar/row.ts, its CSS,real/rest.spec.tspresses the top pill,core-screen.spec.tsno longer lists it). The room reserved beside the top pill is two buttons now. The phone toolbar's own "Views" item stays (a different control). Commit3276c5036; the mockup-only removal is reverted.Findings
Finish (round 3)
Head
9c2762305onsettings-sections-mock-j92, rebased onto origin/dev294042b56. TypeScript and CSS only: the diff against dev has no Rust or Cargo file. The review comment with the results and 8 captures (DPR 2: default layout, after a narrowing drag, the edges; phone DPR 3) is the previous one on this issue. Preview: http://10.69.69.117:47660 (PID 4044413 on infraternal-dev-02-std, mine;kill 4044413when reviewed), linked from http://10.69.69.117:47650/mockups.html.scripts/verify fast, infraternal-dev-01-compute01, clean worktree, through build-slot, on this head, verbatimThe
testrow is red; I did not get a green one, and I could not reproduce dev's green. In this runcargo teststopped at the first failing binary,agent_daemon::real_binary_rootless_revocation_after_restart_stops_every_owned_terminal(scripts/test-rootless-revoke-live.py, "restart/descendant oracle failed"). That test passes alone on the same head (cargo test -p infraternal --test agent_daemon: 11 passed). The machine had four other gates running through build-slot at the time (slots 1 to 4 busy, one more queued). With--no-fail-faston the same head: 2050 passed, 12 failed: account_eventsreview_revocation_r2x4,latest/release_payloadprivate-staging x3,lookup_creates_private_staging_under_owner_restrictive_umask,restarted_latest_reclaims_metadata_after_process_stop,pending_channel_writers_preserve_authority_read_capacity,release_manifestsigned identity,faithful_snapshot_preserves_public_mouse_encoder_reports. These are the same families as the last round's 21 (that set also hadbootstrap_runtime::remote_backend, which now passes); they are umask, staging and timing tests and none touches anything this diff changes. Please do not read the row as green.Other checks (dev-02, final tree)
tscclean; production-flag build ok.defaultWidthwide andh: 1, no span, for an administrator and a member, at four screen sizes); 0 failed.test/settings-sections.spec.ts: 22 passed. New this round: layout size (width of a terminal window, height of the layout, equal gaps, nothing over anything), Window Sizes Wide / Full width / phone Full width, the wheel through a column with a window longer than the screen (top and bottom reached), one finger and two fingers on a phone, and the edge drags (four edges at 1440x900, four corners at 393x852, three Settings windows and three terminals, no intersection on any animation frame).Cleanup
Deleted my Rust
target/and scratch files on compute01 and dev-02. Nothing of mine runs on either VM except the preview server above.Needs the owner
Round 4: one row of windows for each component, and the owner's correction
Same URLs: http://10.69.69.117:47650/mockups.html (entry #304), http://10.69.69.117:47660/?mock=1&proto=clusters&scene=3&settings=sections&at=mesh.keys
Head
d242e28f6onsettings-sections-mock-j92, rebased onto origin/dev (c135935fa), cleaned into 15 atomic commits (the add/revert history of earlier rounds is gone; the Views-button removal commit is kept). 22 Playwright tests pass on dev-02 (2 of them flaked once under a parallel run and pass alone),tscclean, unit tests pass (grid and layout 69 including 5 new, settings map and docs 33).What the owner said, and what I built
"Settings - Appearance is one row which scrolls down to ... Access, no per window scrolling. they scroll up and down as groups", then, corrected: "two finger scroll to move vertically. single finger scroll should scroll inside the window." I built exactly that, and it replaces round 3's columns.
group(runtime only, likehalf); adjacent columns with the same name are one run, exactly as if a window spanned them: same DOM, steps, resize and drag. Rule changes: a cell is never covered twice, and in a row group a cell may be empty. Split right keeps the name. A view that declares row groups is arranged when it is built. 5 unit tests ingrid.test.ts. Rejected alternatives are in the commit.stepStops) and its CSS. A long window (Typing) scrolls inside.terminal/multiplexer#offer-to-switch,reference/keys#passkey | recovery-words | keys-last | browsers-stay-signed-in-for | add-link-lasts | connection-keys(Connection Keys now points at the 7-day key). Examples on a terminal, the add-host dialog and a No access card use the new paths too. Preview text comes from the docs' own[!FACTS]; stand-ins stay only for four headings that have none yet (passkey, recovery words, host join token, all keys at a glance).narrowed-2x-1440x900.png(Theme narrowed: Font follows, nothing over anything).Captures (DPR 2 desktop, DPR 3 phone)
01-mesh-keys.png(default layout),strip-d2-1-before / 2-moving / 3-after.png(two rows and the scroll between them: the Appearance row and the Terminal row move as one),rows-d2-next-row.png,narrowed-2x-1440x900.png,p01-mesh-keys.png,strip-p3-1..3.pngandrows-p3-next-row.png(phone: two fingers up).Changes outside the mockup, each justified in its commit
layout/grid.ts,groups.on-demand.ts,model/types.ts,views/world.ts: the row group above.camera/gestures.ts: a two-finger step finds its column over an empty cell (dev's wheel already did; a short row leaves empty cells).ui/anchored-popover.ts: mounted inside its window so it moves with its button, and closes only when a button that was on screen has left it (a first version closed popovers opened for off-screen buttons, which broke dev'sclusters-gridwindow-menu spec; fixed). Merged with dev's new point placement (at).toolbar/viewlist.ts+viewlist.on-demand.ts:toggle(from?)so the views list is centred on the Settings pill (it follows dev's new hook/panel split).toolbar/row.tsand CSS: the round Views button is removed from the product (owner answer a).Other specs, against the dev baseline
clusters-grid.spec.ts: 9 failed on origin/dev and the same 9 fail on this head (none new).core-screen.spec.ts:151also fails on both.sessions-canvasandsidebar-rename-removespecs I ran pass alone on both (three flaked once under load).Findings
rows-d2-next-row.png). Same for terminals; I left it, but it reads as a bug in this view. Say if the breadcrumb should follow the row in view.Finish (round 4)
Head
c88619630onsettings-sections-mock-j92, rebased onto origin/devc135935fa, 16 atomic commits (the Views-button removal commit is kept). TypeScript, CSS and tests only: no Rust or Cargo file. The review comment with the results and 11 captures (DPR 2 desktop, DPR 3 phone) is the previous one on this issue. Preview: http://10.69.69.117:47660 (PID 4044413 on infraternal-dev-02-std, mine;kill 4044413when reviewed), linked from http://10.69.69.117:47650/mockups.html.scripts/verify fast, infraternal-dev-01-compute01, clean worktree, through build-slot, on this head:VERIFY_EXIT=0The first gate run on this branch failed the transfer budget, not Rust: deferred JavaScript was 65,521 B gzip against 61,440 (dev's own 59,759). The breadcrumb and the "?" preview were static imports of the canvas. They are on-demand modules now (commit "canvas: the breadcrumb and the "?" preview load on demand, inside the deferred budget"); this whole branch costs +1,312 B of deferred gzip against dev, 369 B under the cap. J106's note applies: the next canvas feature on dev will trip it again; the ratchet is the orchestrator's.
Other checks (dev-02, final tree)
tscclean; production-flag build ok.test/settings-sections.spec.ts: 22 passed.clusters-grid.spec.ts9 failed on this head and the same 9 on origin/dev;core-screen.spec.ts:151fails on both; the window-menu, sessions-canvas, row-menu, sidebar and appwin specs I ran pass (three flaked once under a parallel run and pass alone, on both).Cleanup
Deleted my Rust
target/and scratch files on compute01 and dev-02 and the baseline worktree; nothing of mine runs there except the preview server above.Needs the owner
J132 start and plan (make the approved Settings rows the product)
Branch
settings-rows-j132, from J92'ssettings-sections-mock-j92(c88619630), rebased cleanly onto origin/dev301a05c3d(16 commits, no conflicts). Worktree~/Developer/Worktrees/infraternal-j132on the control host. Builds and gates go to a VM through build-slot.Finding that needs a decision before the wiring step
The mockup's table (
apps/tracer/src/canvas/mock/settings-map/catalog.ts) lists about 20 settings. On origin/dev only ONE of them has a server setting behind it:server_settings.api_key_lifetime_days(1–365,auth/security_settings.rs), which is "Keys Last". There is no server setting for: connection-key and machine-identity rotation, the certificate renewal grace period, the machine-name suffix, browser sign-in time, add-link and join-code lifetime, install mode, sign-in account, join-the-mesh, renew-early, scrollback lines, or multiplexer offer. Profile, Updates, Connections, Published Services and Licences hold made-up facts. So "wire every row to the real settings" is, for those, new server work (Rust + storage + the rule that enforces the value) in security-sensitive code, not a front-end change.Plan (front end, on demand)
canvas/mock/settings-map/to a product path (canvas/views/settings-rows/), dropsettingsRows/?settings=sectionsfrommock/index.tsandmock/settings.ts. Settings always opens in rows; the productSettingsSourcesupplies the outline. Estimate 1.5 h.layout/grid.tsso a window's width and height are its own. This is the largest layout change; estimate 2 h with grid unit tests.api_key_lifetime_daysthrough the existing security-settings API; the "?" links only to docs pages that exist (checked by a test against the docs index). Estimate 1.5 h.scripts/verify fast, D188 budget lines. Estimate 1.5 h.Total about 9 h for the front end. I stop and report at 18 h.
Not doing unless told
New server settings for the ~19 settings above. I will not show an editable control that saves nothing. Options for the orchestrator: (a) show only settings with a real backing and list the rest as "later" with one plain line; (b) open a server issue per setting and keep the control hidden until it lands; (c) approve the server work in this job and its estimate.
Other notes
DECISIONS.mdon origin/dev (grep finds neither as an entry), so I am taking the two D323 answers from the job brief..on-demand.tsmodules.J132 progress (branch
settings-rows-j132)Owner decision taken in this job: show only backed settings. Layout kept; a setting with no backend has no control, and a window with nothing to show says "Not available yet." in one plain line.
Done on the branch (typecheck clean, 477 canvas unit tests pass on compute01)
canvas/mock/settings-map/tocanvas/settings-rows/. Nosettings=sectionsflag: Settings always opens in rows, in the product (product.ts) and in the mock.SettingsSourcegainsbacking(settingId)anddata(component, group). The table (catalog.ts) holds no invented data any more.api_key_lifetime_days, 1–365, owner only; the write asks for a fresh passkey once and retries, as the device approval does). Backed on the client: Appearance (Theme, Font, Size, Layout), Terminal › Typing (Shortcuts + Toolbar), Terminal › Hosts (the old Hosts panel, which has no other home), You › Profile / Passkeys / Recovery (from the old Account panel), About › Version, About › Licences (AGPL-3.0-only, commercial features separate).docs/user/and checks every page and heading. The docs stand-in text (docs-standin.ts) is removed.Settings with no backend (each needs its own server issue)
connection-keys, machine-identity, renewal-window (Mesh › Keys); name-suffix (Mesh › Names); browser-session (You › Devices; the Devices list has no product source either); add-link, join-code, install-mode, sign-in-account, join-mesh (Machines › New Machines); renew-early (Sharing › Certificates); scrollback-lines (Terminal › Scrollback); multiplexer-offer (Terminal › Multiplexer). Windows with no data source: Machines › Updates, Mesh › Access, Mesh › Connections, Sharing › Published Services. The Mesh › Keys "Machine Authority" fact: the authority lock control is in Terminal › Hosts for now.
Not in D-files
D323 and D188 are not entries in
DECISIONS.mdon origin/dev; I used the two D323 answers from the job brief.Next: Playwright specs on compute01 (running), budgets, screenshots,
scripts/verify fast.J132 progress 2 (head
c869152f1, branchsettings-rows-j132)The two bugs found on 2026-11-04 (specs first, then fixes)
Each has a spec added before the fix (commit
2691071e6), run on that commit: 4 of 4 failed (desktop and phone, both bugs). After the fix commit the same specs pass, apart from two assertions of my own that I corrected (c869152f1).camera/lock.tsrowLeftLimit). It uses the row being flown to; when a scroll or flight rests on a shorter row, the camera comes back inside. Spec:sideways scrolling stops at the end of the row, 1440×900 and 393×852.Nav.windowInViewis the one rule (the camera's stop gives the column, the band nearest the screen's middle gives the row). The breadcrumb reads it, and once the canvas rests an active window that is less than half on screen hands over to it. A change of Window Sizes frames the active window again. Spec:a layout change keeps the active window in view, and scrolling hands the focus on, both sizes.Note: on this branch the Appearance row is Theme, Font, Size, Layout (four windows). Presets is J129's work (#323) and is not on this branch, so the specs use Layout and Theme. The row is shorter than the longest row (You, five), which is the same cause.
Needs a decision from the orchestrator
27 older Playwright tests fail on this branch because they open the old Settings windows (
s-account,s-appearance,s-hosts,s-shortcuts,s-windows...) that the mock no longer builds. Files: account-summary (4), clusters (4: lines 118, 839, 868, 1090; 118 and 1090 may also be the new "?" button on terminals), machine-sections (2), palette-polish (1), settings-edges (4), settings-query-roundtrip (2), settings-rows (6), shortcut-reset (2), sign-out (2). They are not inscripts/verify fast. Converting them to the new window ids is about 3 to 4 h more than my estimate. I have not started it.Gate (
scripts/verify fast) and the light-theme captures are queued on compute01 (position 7).Deferred JS (D188): +6,118 B → +3,233 B gzip, by module
Measured with the production build on compute01, deferred class, gzip: dev
94834e0eb54,299 B → this branch 57,532 B (cap 61,440): +3,233 B. Critical 319,051 (dev 318,146, cap 327,680); largest on-demand chunk 16,220 (cap 20,480). Per-module sizes below are the bundler'sbytesInOutput(identity bytes, from the metafile); gzip is not measurable per module.What is left in the deferred class (identity bytes, branch vs dev)
settings-rows/catalog.tssettings-rows/model.tssettings-rows/source.tsSettingsSourcethe canvas asks for the outline and a window's bodywindows/frame.tssettings-rows/product-source.tssettings-rows/docs-adapter.tscamera/lock.tstoolbar/tree.tsdocs/docs-source.tstoolbar/shortcuts.tsWhat I moved out (each its own commit)
definitions.on-demand.ts) and the ⌘K rows (entries.on-demand.ts)camera/rows.on-demand.ts)windows/resize-rows.on-demand.ts)windows/docs-action.on-demand.ts)locate.on-demand.ts)Two build traps found on the way, both fixed and commented in the commits: a module imported dynamically by the canvas and statically by another on-demand module becomes a re-export chunk with no inputs, which the chunk classes count as critical (+22 KB gzip critical until fixed); and
export type ... fromof an on-demand module kept a chunk edge.What pins the remaining +3.2 KB
Not the 3,000 B goal. 3.2 KB gzip is the structure the canvas needs before any Settings window exists: the table of where things live (3.2 KB identity), the Settings source and its docs adapter (2.3 KB), the sidebar tree and the "?" wiring (about 1.8 KB). Getting under +3,000 would need the sidebar's Settings subtree to build lazily (the tree shows it from the first paint, so it would appear a frame late) or the "?" wiring to wait for the first window; both change what the person sees, so I did not do them. Say if you want either.
J132 progress 3 (head
1ae09ea71, branchsettings-rows-j132)Measured on compute01 (before the last two commits; the final run is queued):
scripts/verify fast's TypeScript half (ts_verify_fast, the same function the gate calls) on168556d68:TS_VERIFY_EXIT=0. D188: critical 319,842 / 327,680 gzip (deva89ebb0ae: 318,892), deferred 57,555 / 61,440 (dev: 54,336, so +3,219; was +6,118), largest on-demand chunk 16,214 / 20,480. The per-module table is in the previous comment.remote_client::testsonce,agent_daemononce).cargo test -p infraternal --test agent_daemonpasses on the same head (11 passed) when it runs alone. No Rust file is changed by this branch. I am re-running the whole gate once more; if a timing test fails again I will say which, and prove it on dev.168556d68(dark and light): 26 of 29 pass. The 3 failures were the own-size resize specs, caused by the resize code being fetched on first pointer contact;a2061d89efetches it at idle for Settings windows.168556d68. Most of the failures were palette words that also matched "Open shell on ..." rows;1ae09ea71uses the palette's exact labels ("Terminal › Typing"). Re-run queued (position about 9). The twosign-out.spec.tsfailures are not mine: they fail identically on unmodified dev (94834e0eb).Fixes found by the new specs, each its own commit: the end of a short row is a stop of its own (
rows.on-demand.ts), measured from layout offsets and ending with the inset the longest row ends with;windowInViewnames a window of the row in view even when the stop's column is empty in that row.J132 finish: head
574037ea5onsettings-rows-j132(the gate ran onca248d9ba; the only change since isapps/tracer/test/palette-polish.spec.ts)The two bugs of 2026-11-04 (captures attached to this comment, DPR 2 desktop 1440×900, DPR 3 phone 393×852, dark and light)
row-end-*: the last window of Appearance rests whole on screen with the inset the longest row ends with; scrolling further stays there.layout-kept-*: after a wider layout the window the person was on is still in view and active.active-follows-*: after scrolling on, the window in view is active and the breadcrumb names it.Each spec was committed before its fix and failed there (4 of 4); both are in
settings-rows-of-windows.spec.tsat both sizes.scripts/verify fastonca248d9ba(compute01, through build-slot):VERIFY_EXIT=0Dev
a89ebb0aefor comparison: critical 318,892, deferred 54,336, largest on-demand 16,218. Deferred is +3,226 B (was +6,118). Earlier gate runs failed inremote_clienttiming tests; dev's own fix for those (#334) is merged in, and with it the Rusttestrow passes.Playwright, production build, 1440×900 and 393×852
settings-rows-of-windows.spec.ts: 29 passed, dark (mocha) and light (latte), twice each on the final head.ac799ea2ato574037ea5), plus the specs that open Settings from elsewhere (account, sign-in rows, palette, shortcuts, hosts, fonts, UI size, version pill, phone gutter), 131 tests onca248d9ba: 121 passed, 6 skipped, 4 failed. Of the 4,palette-polishis fixed since and passes (re-run alone);clusters.spec.ts:161(camera zoom after Ctrl) I did not look into;clusters.spec.ts:1099andshortcut-reset.spec.ts:49are below.Needs the owner or the orchestrator
clusters.spec.ts:1099(phone window header, 44 px touch targets) fails: a phone terminal header now holds "?", "…" and Close, and the "?" and "…" targets overlap. This comes from "?" being the first button on every terminal (J92's design). Options: no "?" in a phone header (it stays in "…" and ⌘K), or a wider spacing. I did not choose.shortcut-reset.spec.ts:49(1440×900): after three keys are rebound the right edge of the key caps moves by 0.5 to 2.8 px (it varies from run to run) where the rule allows 0.5. Shortcuts now share the Terminal › Typing window with the toolbar panel; I did not find the cause.sign-out.spec.ts:144and:309fail the same way on unmodified dev94834e0eb.settings-edges.spec.tsno longer measures the Size window (a single slider; its readout ends at the tick edge by the shared row's CSS); see that commit.J132 finish: head
574037ea5onsettings-rows-j132(the gate ran onca248d9ba; the only change since isapps/tracer/test/palette-polish.spec.ts)The two bugs of 2026-11-04 (captures attached to this comment, DPR 2 desktop 1440×900, DPR 3 phone 393×852, dark and light)
row-end-*: the last window of Appearance rests whole on screen with the inset the longest row ends with; scrolling further stays there.layout-kept-*: after a wider layout the window the person was on is still in view and active.active-follows-*: after scrolling on, the window in view is active and the breadcrumb names it.Each spec was committed before its fix and failed there (4 of 4); both are in
settings-rows-of-windows.spec.tsat both sizes.scripts/verify fastonca248d9ba(compute01, through build-slot):VERIFY_EXIT=0Dev
a89ebb0aefor comparison: critical 318,892, deferred 54,336, largest on-demand 16,218. Deferred is +3,226 B (was +6,118). Earlier gate runs failed inremote_clienttiming tests; dev's own fix for those (#334) is merged in, and with it the Rusttestrow passes.Playwright, production build, 1440×900 and 393×852
settings-rows-of-windows.spec.ts: 29 passed, dark (mocha) and light (latte), twice each on the final head.ac799ea2ato574037ea5), plus the specs that open Settings from elsewhere (account, sign-in rows, palette, shortcuts, hosts, fonts, UI size, version pill, phone gutter), 131 tests onca248d9ba: 121 passed, 6 skipped, 4 failed. Of the 4,palette-polishis fixed since and passes (re-run alone);clusters.spec.ts:161(camera zoom after Ctrl) I did not look into;clusters.spec.ts:1099andshortcut-reset.spec.ts:49are below.Needs the owner or the orchestrator
clusters.spec.ts:1099(phone window header, 44 px touch targets) fails: a phone terminal header now holds "?", "…" and Close, and the "?" and "…" targets overlap. This comes from "?" being the first button on every terminal (J92's design). Options: no "?" in a phone header (it stays in "…" and ⌘K), or a wider spacing. I did not choose.shortcut-reset.spec.ts:49(1440×900): after three keys are rebound the right edge of the key caps moves by 0.5 to 2.8 px (it varies from run to run) where the rule allows 0.5. Shortcuts now share the Terminal › Typing window with the toolbar panel; I did not find the cause.sign-out.spec.ts:144and:309fail the same way on unmodified dev94834e0eb.settings-edges.spec.tsno longer measures the Size window (a single slider; its readout ends at the tick edge by the shared row's CSS); see that commit.J211 start: branch
settings-followups-j211, basea6d0223bf. Plan: (1) phone terminal header without "?" (done, pushed), (2) clusters.spec.ts:161 and (3) shortcut-reset.spec.ts:49: find which side is wrong, then verify quick + fast.J211 progress.
96fe7bc9f, pushed): a terminal's header on a touch device no longer gets "?" (only Close); desktop and non-terminal windows (Settings: "?" alone) unchanged.clusters.spec.ts"window header actions are one pill" passes on a production build (compute01, 1440×900 context + phone).clusters.spec.ts:161— the product is wrong, narrowly. It failed 1 run in 9 (8/8 pass on re-run). The only async step isgestures.tsfetching the free-canvas chunk when the lock turns off (D188): a wheel that lands before it arrives ispreventDefaulted and dropped (canvasWheel:if (free) … else e.preventDefault()). Spec added first (80f17b837, scripts delayed 1.5 s); fix (hold the wheel, play it when the chunk lands) follows.shortcut-reset.spec.ts:49: investigating.J211 progress 2 (branch
settings-followups-j211, headaa80cbe72).clusters.spec.ts:161was the product. New spec80f17b837(scripts delayed 1.5 s so the free-canvas chunk is late) failed there ("Expected < 1, Received 1"); fixd28cf9b51(hold the wheel while the chunk loads, play it when it lands) makes it pass; with the original 161 test, 6/6 (3 repeats each).shortcut-reset.spec.ts:49was the spec. The failing line is not the "caps on one edge" check (that passed every run) but "the edge did not move": it compared the first row's right edge on the page before and after rebinding, and the window was still settling on the canvas. Received 2.8, 7.5 and 78.5 px in three runs.aa80cbe72measures from the window's own left edge. 8/8 pass (4 repeats × 1440×900 and 393×852).verify quick:QUICK_EXIT=0. Firstverify fastonaa80cbe72: every row PASS excepttestFAIL (101):infraternal-plugin-ssh --test install interrupted_upgrade_after_acknowledged_stop_restarts_the_previous_service("Setup is already running on this host"), in code this branch does not touch. Run alone 5 times: 5/5 pass. Re-running the full gate.J211 finish: head
aa80cbe72onsettings-followups-j211(basea6d0223bf, not merged). Four commits:96fe7bc9fphone header,80f17b837+d28cf9b51wheel spec then fix,aa80cbe72shortcut-reset spec.scripts/verify quick:QUICK_EXIT=0.scripts/verify fast(compute01, build-slot), second run; the first failed on a flaky unrelated test, see the previous commentPlaywright (production build, compute01): window-header spec (phone 393×852 touch context) passes; new wheel spec and the original :161 6/6; shortcut-reset 8/8 (1440×900 and 393×852, 4 repeats). Caveat: these specs run in the ink theme only, and I did not capture screenshots (no visual change except the missing "?" in a phone terminal header). Dark/light were not run separately.
Decisions for the orchestrator: (1) with "?" gone from a phone terminal header there is no "…" any more (Close alone never folds), so "?" lives in ⌘K ("Read about this window") only, not in a "…" menu as the task text said; getting it into the canvas row is the D350 build. (2) Not in this branch: D350 is not in DECISIONS.md at this base.