keyboard-opened surfaces (⌘K, ⌘/, ?) animate; they must open and close instantly #427
Open
opened 2026-11-08 14:16:47 +00:00 by kayg
·
41 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#427
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?
Owner, 2026-11-08, verbatim: "wait i notice that cmd / or ? (shortcuts panel) and cmd k have started to animate? i thought we decided actions originating from keyboard shortcuts = no animation?"
Owner decision (2026-11-08, "Keyboard opens instantly"): anything opened or closed from a keyboard shortcut (⌘K palette, ⌘/ and ? shortcuts panel, splits, and the like) appears and disappears instantly, with no animation. Pointer and touch keep their animations. TASTE's 2026-10-08 row allowing about 180 ms key-triggered open/close is replaced; the two older "instant" rows stand.
J370 start. Branch
fix-kbd-no-anim-427, base origin/devf31cf18ab.Cause (git log -S):
d7b2a4753(2026-10-08, "tracer: animation never gets in the way of the palette") replaced the instant.palette[data-open-kind="keyboard"] { transition: none }with a 180 ms key-triggered fade+scale (.palette[data-open-kind="keyboard"]:not([hidden]) { transition-duration: 180ms }, apps/tracer/style.css).72027e74cpinned it in a spec ("a key-triggered palette open is a 180 ms fade, not instant"). That followed the TASTE "animation never gets in the way (4)" row, which the owner has now replaced. The?/⌘/ panel (packages/ui/src/shortcuts-view.ts) never looked at the source at all: its 400 ms clip-path spring runs on every open and close. The glass bed (setOpen) fades with its card.Plan (~2 h): one shared input-source tracker in packages/ui (the last of keydown / pointerdown / touch decides, set in capture before handlers), exposed as
html[data-input]for CSS andtriggeredByKeyboard()for JS. Palette, scrim, shortcuts panel and glass bed read it; no per-surface source flags. Red spec first on origin/dev at 1440x900 and 393x852, then fix,verify quick,verify fast.J370 progress. Red spec
apps/tracer/test/keyboard-instant.spec.tspushed (7e13f929c) and run on origin/dev's code (dev-02, log~/j370-red.logon infraternal-dev-02-std): 10 failed, 2 passed (the two "first keystroke after the chord lands" checks, which already held).Frame evidence, first rAF after the key, 1440x900 and 393x852:
#paletteopacity "0" (expected "1"), a 180 ms transition running.?and Ctrl+Shift+/: panelclip-path: inset(0px 33.46px 534.2px round 20.9px)(desktop),inset(0px 58.3px 611.8px round 20.9px)(phone), i.e. still mid-spring.Fix is three commits (
1b3a921cctrackerhtml[data-input],c3f8313a6palette/pills/sidebar/glass bed via one.ui-key-instantrule,d988a7301shortcuts panel); now running the new spec plus core-screen and canvas specs for regressions.J370 finish. Branch
fix-kbd-no-anim-427, head865116ec6, based on origin/dev7c8bd2221. Not merged, not deployed.Commits
209fb4371test: red specapps/tracer/test/keyboard-instant.spec.ts(12 cases: 1440x900 and 393x852)37d8c3c40ui:packages/ui/src/input-source.ts, the one tracker. Capture listeners on window: keydown = keyboard, pointerdown (mouse, pen, touch) = pointer, written tohtml[data-input]in the same task. Newest event wins, so a pointer close of a keyboard-opened surface may animate and a key close of a pointer-opened one is instant. Unit test included.056be1c30tracer: one rule inpackages/ui/styles.css,:root[data-input="keyboard"] :is(.ui-glass-bed, .ui-key-instant) { transition: none }. The palette, its scrim, the sidebar, and the capsule, plus and sidebar-toggle pills (their 120 ms cover fade ran on every key open) carry.ui-key-instant.setPalettelost itssourceargument anddata-open-kindis gone. Two old specs that pinned0.18snow expect0s.865116ec6ui: the?/ ⌘/ panel (shortcuts-view.ts) jumps its spring to the end on a key, open and close, and skips the shadow glide.Red on origin/dev code (
~/j370-red.logon infraternal-dev-02-std): 10 failed, 2 passed. First rAF after the key: palette opacity "0" (expected "1"); panelclip-path: inset(0px 33.46px 534.2px round 20.9px)at 1440x900 andinset(0px 58.26px 611.79px round 20.9px)at 393x852 (expected "none"); a pointer-opened palette still displayed after Escape.Green (
~/j370-green.log, dev-02): all 12 new cases pass at both sizes, as does canvas.spec.ts (51 passed in total with core-screen). In the first frame after the key the palette is opacity "1" with no running transition and the panel isclip-path: nonewith content opacity 1 and the pill hidden. After Escape the palette isdisplay: noneand the panel is removed in the first frame. A pointer open still starts at opacity < 1. A keyboard close of it is instant. A pointer close of a keyboard-opened palette still fades (display held until the fade ends). Typingthmright after the chord lands in#palette-input.Regression sweep (
~/j370-reg.log, dev-02): palette-navigation, palette-polish, shortcuts-d222, clusters-shortcuts, clusters-keyboard-split, platform-consistency, window-option-new plus the bun unit tests: 60 passed, 2 failed. The 2 failures (platform-consistency.spec.ts:184, "Windows palette ... no bar at rest": trackSpread 201 and 84, expected < 6) also fail on unmodified origin/dev (~/j370-base2.log: 100 and 64). Not mine.core-screen.spec.ts:151 and :254 fail at
#rtt("··", expected "N ms") on both my branch and origin/dev (~/j370-base.log), so they are pre-existing and the latency proxy is the likely cause. They stop before the 0s assertion, which is covered by canvas.spec.ts.Gate
scripts/verify quick(dev-02,~/j370-quick.log): "QUICK pre-check passed", exit=0.scripts/verify fast(compute01,~/j370-fast.log): every Rust gate row PASS (privileged integration SKIP, static builds PASS). The TS suite is654 pass, 1 fail, and the only failure isdocs-build.test.ts"doc.js stays small: Expected < 12000, Received 13408". The same 13408 occurs on unmodified origin/dev7c8bd2221, run on dev-02, so it is not from this change. VERIFY_EXIT=1 comes from that row alone.Not covered / for the orchestrator
installInputSource()runs frommain.tsonly. The standalone doc page and the add-host prototype page do not install it, so they keep their old motion.J370 correction to my finish comment: the size line ('about 1 KB of JS, about 150 B of CSS') is an estimate from reading the diff, not a measurement. I did not measure the bundle or the D243 delta. verify fast's static builds row passed; the orchestrator should read sizes from that log (~/j370-fast.log on compute01) if it needs them.
J373 review of
fix-kbd-no-anim-427@865116ec6(base origin/dev77b1255cb, which contains the amended TASTE row7c8bd2221)Verdict: REQUEST CHANGES. One real defect (P2): a modifier key alone kills a running pointer animation. Everything else holds. The fix is a few lines in
input-source.ts.What I ran
Production tracer build (
bun run build.ts, preview flag on so the test double loads) of the head and of origin/dev, each served bytest/mock-server.tson compute01 through build-slot (launcher checked first:nix develop . -c bun --versionoutside the slot). Headless Chromium,?mock=1&proto=windows, themeinkandpaper, at 1440×900 and 393×852. The phone runs usehasTouch/isMobileat DPR 2, and tap with a real touchscreen. The driver records, for every animation frame after the capture-phase listener of the first non-modifierkeydownorpointerdown, the display, opacity, transform and clip-path of the palette, scrim, shortcuts panel and its body, sidebar, capsule, sidebar toggle, settings overlay, confirm tip and glass bed, plus every window rect and every running CSS transition or Web Animation. "INSTANT" means the first frame equals the final frame and nothing ran. 154 steps in all.I did not run
verify quickorfast(reviewer rule). The author's gate output is J370's finish comment.1. Keyboard opens and closes: instant in the first frame (all four combos)
Ctrl+Shift+K, toggle with same chord)#palettedisplay shown, opacity 1,matrix(1,0,0,1,-308,-225); scrim opacity 1#palettenone, opacity 0; capsule opacity 1?andCtrl+Shift+/shortcuts panel.ui-shortcutsopacity 1, clip-path none; body opacity 1; capsule 0#sidebaropacity 1, toggle already atmatrix(1,0,0,1,308,65).ui-settingsfinal stateCtrl+Shift+D), close window (Ctrl+Shift+W)Examples (
~/j373/matrix-head.log, head): 1440 ink palette key open F1 = final =#palette=shown|1|matrix(1,0,0,1,-308,-225),.palette-scrim=shown|1, frame at +12.3 ms. Phone paper?: F1 = final =.ui-shortcuts=shown|1, body 1, capsule 0, +1.4 ms. On origin/dev the same steps are 16 of 16 ANIMATED (~/j373/matrix-base-desktop-ink.log): palette key open F1 opacity 0, scale 0.98, 201 ms of transitions, so the probe does tell the two apart.Only exception, and not this branch's: on the desktop size the sidebar key-open shows
diff:[windows]. Window 1 shifts 14 px (978→964) in the second frame, a one-frame layout step, not a transition. origin/dev does the identical thing (~/j373/side.mjsrun: 978→964 at +29 ms on base, +40 ms on head). The sidebar and its toggle are final in frame 1. Out of scope, noted.2. Pointer and touch still animate; mixed close directions behave
No pointer or touch step was instant (0 of all pointer steps). Last-run durations of the running transitions (
~/j373/matrix-head.log): palette pointer open (opacity 0 → 1, scale 0.98 → 1) 230–271 ms over the 8 samples at both sizes; pointer close 131–201 ms; touch tap open 265–275 ms, tap close 166–178 ms. Sidebar pointer open/close 243–351 ms (most 256–294). Settings pointer open 219–282 ms. Pointer open of the shortcuts panel (palette row click) about 0.9 s including the palette fade.Keyboard close (Escape) of a pointer-opened palette, sidebar, shortcuts panel and settings: instant in frame 1, in every combo. Pointer close of a keyboard-opened palette (scrim) and sidebar: animated, which the issue allows.
3. Edge cases
keydownfor any key setsdata-input="keyboard", thetransition: nonerule applies at once and running transitions are cancelled. Representative series (palette opacity), control vs Shift:99:0.32 165:1.00).47:0.11 94:1.00).Evidence:
~/j373/matrix-head.log, lines startingE1 mid-animation; first run~/j373/matrix-head-run1.logshows the same. A letter key does the same (full opacity at +115 to +192 ms), which is arguably fine ("newest input wins", and it is typed text), so the ask is only about modifiers. Alsodata-inputiskeyboardafter Shift alone (E2 data-input after Shift alone: keyboard), though the next click correctly animates again (E2 click after Shift alone: ANIMATED, 269–481 ms; Shift held while clicking: ANIMATED, 226–290 ms, as pointerdown comes after the modifier).Requested fix: in
keydown, ignore modifier-only events (e.keyin Shift, Control, Alt, Meta, AltGraph, CapsLock, Fn). A chord's final key sets the state in capture before any handler, so ⌘K, Ctrl+Shift+K, ⌘/ still work. Add a unit case plus one spec: click the capsule, press Shift at +60 ms, palette opacity still < 1 at +100 ms. I did not apply or run this fix.ls -lain the terminaldata-inputiskeyboard; the next click on the capsule starts a normal animation (250–390 ms, 4 of 4 combos); a touch tap after typing on the phone also animates (220–253 ms). No pointer press is swallowed (the listener is onwindowin capture).imeSetComposition+insertText, "日本" lands in#palette-input) leavedata-inputatpointer. A real IME sends keydownProcess(229); sending that setskeyboard, like typing. The palette then closes instantly on Escape, and a following click animates again. Real IME hardware and iOS soft keyboards not tested.data-inputplus forced style and layout costs 0.14–0.41 ms per toggle on this 845-node canvas (a neutral attribute: 0.002 ms). That is paid only at a pointer↔key change, not per key. Under the 16 ms bar; noted because latency is priority 1.4. Doc page, add-host prototype, other surfaces
start()inmain.ts, afterinstallInputSource(). On?proto=addhostdata-inputispointerat load andkeyboardafter a key, in all four combos (addhost prototype page: …lines). Nothing to install.doc.js(doc-page.ts), no tracker. Its only animated openers are<details>disclosures (.why,.toc-fold, 200 ms block-size) that open by pointer or Enter/Space, not by a shortcut. I would not install the tracker there for #427: doc.js is already over budget (13408 B vs 12000) and J372 is fixing that. If the owner wants keyboard-toggled disclosures instant, that is a separate small CSS-only item.source === "pointer"in code. Not driven: window-docs chord, session-manager popover, row menus, confirm tip on pointer vs key.camera.keyFlight, ⌘/Ctrl+digit and palette view picks) are still a short spring on a key. They are navigation, not open/close, so not covered by #427's wording, but TASTE's "actions originating from keyboard shortcuts = no animation" could be read to cover them. My attempt to measure it was inconclusive (window 0 did not move), so I give no number.data-inputstayskeyboarduntil the next pointerdown. A pointer-less open of one of the covered classes (palette, scrim, sidebar, top pills, glass bed) after typing would be instant. I found no live case: all of them open from an input. Pointer hover is deliberately not a source (synthetic moves after layout would flip it while typing).keyboard-instant.spec.tsarm()fires on the firstkeydown, which forControl+Shift+Kis the Control press, so its "first frame" is the first rAF after Control. It passes by timing. Make it ignore modifier-only keydowns. My own probe showed the same trap: usinge.timeStampas the reference produced three false "animated" rows (~/j373/matrix-head-run1.log), gone when I tookperformance.now()inside the capture listener (~/j373/matrix-head.log).5. Bundle size (non-preview production build,
chunks.jsonclasses;~/j373/plain-head,plain-base)main.js: 28860 → 28868 B raw (+8), br 8947 → 8955 (+8).style.css50436 → 50386 (−50); all CSS raw +535, gz +204, br +183.doc.js(docs build): 13408 B on both head and origin/dev, and it contains none of the tracker code. Not pushed further over. J370's "about 1 KB" was an estimate; the measured raw delta is 522 B.Not covered
Mac ⌘ chords (Linux Chromium, Ctrl+Shift chords), real iOS Safari and a physical touch device, a real IME, hover-opened tooltips, window-docs chord, camera flights. No screenshots: this is timing, so the artifact is the frame logs.
Artifacts (compute01,
~/j373/)matrix-head.log(final 154-step run, all four combos),matrix-head-run1.log(first run, e.timeStamp reference),matrix-base-desktop-ink.log(origin/dev, 16/16 animated),evidence-summary.txt(attached), probeprobe.mjs,side.mjs,build-*.log,plain-*bundles,docs-*.Head reviewed:
865116ec6. Servers started on ports 4731/4732 were stopped by PID.J370, fixes for J373's review (comment 86708). Branch
fix-kbd-no-anim-427, head0ae56a4e0(pushed, not merged), on top of865116ec6. One commit each:abce13b43P2:input-source.tsignores modifier-only keydowns (Shift, Control, Alt, AltGraph, Meta and similar). The chord's last key still sets the state before its handler. Unit test extended. New spec "Shift pressed during a pointer open does not cut the fade short": clicks the capsule, presses Shift at +60 ms, and the opacity transition runs over 200 ms and is never cancelled.c4b13db87spec sampler now arms on the chord's final non-modifier key. Both triggers share one AbortController so a stale listener can't resample a later step.0ae56a4e0camera.keyFlightmakes the camera jump to its target in the same call (theinstantpath); the 80 msKEY_FLIGHTspring is gone. Pointer, touch and pill flights keep their spring. New spec: one frame after Control+Shift+3 the camera equals its settled position; one frame after a view-list click it is still on its way.Red: the new specs run against the old source
865116ec6(~/j370-red2.logon dev-02): the Shift spec and the flight spec fail, the other 12 pass. Item 2 has no red of its own, since it hardens the sampler itself.Green (
~/j370-green2.log, dev-02, atf26551829, which differs from0ae56a4e0only by a doc comment onCamera): 22 passed, exit=0. That is keyboard-instant (14 cases), clusters-flight (FLIGHT {"pointer":272,"pointerBack":270,"key":0,"key2":0}, so key flights settle in 0 ms and pointer ones in about 270 ms), clusters-shortcuts and palette-navigation, plus the input-source unit test (1 pass).verify quickat0ae56a4e0(dev-02,~/j370-quick.log): "QUICK pre-check passed", exit=0. I have not rerunverify fast; the earlier result (only the pre-existing doc.js size failure) was at865116ec6.J378 start: re-review of
fix-kbd-no-anim-427@0ae56a4e0(J373 requested changes at865116ec6). Scratch worktree on dev-02: merge of origin/devb31c2da2dinto the head. Plan: check the three fixes (modifier-only keydown, spec sampler arming, instant keyboard camera flights), probe stale input-source state (keyboard lingering into pointer, iPad touch plus hardware keyboard), focus/a11y, reduced motion, and other keyboard-opened surfaces. Then run on a production build: keyboard-instant, clusters-flight, clusters-shortcuts, palette-navigation, the input-source unit test, andscripts/verify quick. Won't merge, push or deploy.J378 finding 1 (P2, still open): key-triggered camera flights other than ⌘/Ctrl+digit and a palette view pick still use the spring.
keyFlightis only called from three places (toolbar/shortcuts.ts:102,palette-actions.on-demand.ts:31and:57). Other key paths callnav.showOverview()/nav.setCanvasLock()/nav.focusWindow()directly, soflightKindstays"gesture"andflyTosprings. Measured on the production build (clusters mockup, scene 3, 1280×800; probe~/worktrees/j378/apps/tracer/test/j378-probe.spec.tsand…-probe2.spec.tson infraternal-dev-02-std, logs~/j378-main.log,~/j378-probe2.log). "settled" = last frame the camera was more than 1 px from its end point, counted from the key:shortcuts.ts:88-93,showOverview())shortcuts.ts:70,setCanvasLock)palette-actions.on-demand.ts:32)canvas:open:nix-cache, goes throughfocusWindow)Failure scenario: the owner presses Escape to zoom out to the overview, or picks "All views" or a window in ⌘K by keyboard. The camera springs for about 260–580 ms, which contradicts TASTE row "Work is instant" (4) and the owner's "actions originating from keyboard shortcuts = no animation". The fix-3 claim ("keyboard camera flights jump instantly") holds only for the three
keyFlightcallers.Suggested fix: decide the flight kind from
triggeredByKeyboard()insideCamera.flyTo(it is already the one tracker), and keepkeyFlightonly for callers that run before a key event (or drop it). That removes the per-caller wrapper that was missed here. Add a spec case for Escape and for a palette "All views" pick.J378 finding 2 (P2, new): the pill-morph popovers (the capsule's view list, the sharing popover, the floating terminal) never read the input source, so they spring from the keyboard.
packages/ui/src/pill-morph.tshas notriggeredByKeyboard()check (only itsinstantargument and reduced motion). Its three users aretoolbar/viewlist.on-demand.ts,sharing/sharing.on-demand.tsandwindows/float.on-demand.ts. Measured on the production build, clusters mockup (the product canvas; the capsule opens the view list here), 1280×800, probe~/j378-probes/j378-probe3.spec.ts, log~/j378-probe3.logon infraternal-dev-02-std. Every frame after the key is sampled;clipis the panel's computed clip-path:clip=inset(0px 0px 168.203px round 20.9px)(210 px tall panel, 168 px still clipped), 100 ms laterinset(… 115.353px …), settled at the end. Animated. A pointer click gives the same series (168.2 → 110.6), so the key changes nothing.clip=inset(0px round 19.8px)(still fully shown), 100 ms59.2pxclipped, then removed. Animated close from a key. Same for Escape on a pointer-opened list.canvas:share):clip=inset(0px 0px 282.77px …)is still on screen at the last sample, 700 ms later, so it is mid-spring.Failure scenario: a keyboard user Tabs to the capsule, presses Enter, sees the view list grow out of the pill over a few hundred ms, then presses Escape and sees it shrink. TASTE "Work is instant" (4) says anything opened or closed from the keyboard is instant, and the Escape on the view list is exactly the "same key reverses it" case. J373 listed "session-manager popover, row menus" as not driven; this is the one surface that is on screen on every page load.
Suggested fix (one place): in
pill-morph.ts,open()andclose()jump (spring.set(…, true)) whentriggeredByKeyboard()is true, the same asshortcuts-view.tsnow does. That covers all three users. Add a case inkeyboard-instant.spec.tsfor Enter and Escape on the view list.Not a regression of this branch (origin/dev animates these too), but the branch's stated claim and TASTE row (4) say keyboard opens and closes are instant, and these are the remaining ones.
J378 re-review of
fix-kbd-no-anim-427@0ae56a4e0(merged with origin/devb31c2da2din a scratch worktree on dev-02)Verdict: REQUEST CHANGES. The three fixes J373 asked for hold. Two new P2s remain: keyboard still animates on two classes of surface that the branch's own rule (TASTE "Work is instant" (4)) covers. Both fix at one leaf each.
The three fixes: verified
input-source.ts,MODIFIER_KEYS): the spec "Shift pressed during a pointer open does not cut the fade short" passes on a production build, and the unit test passes. The chord's final key still setskeyboardin capture before its handler (⌘K / Ctrl+Shift+K /?all instant inkeyboard-instant.spec.ts).arm()now ignores Control, Shift, Alt, Meta and AltGraph, and both triggers share one AbortController. Read in the diff and green in both viewports.clusters-flight.spec.tsprintsFLIGHT {"pointer":265,"pointerBack":261,"key":1,"key2":4}(pointer ~265 ms, key flights at once).keyboard-instant.spec.ts"a camera flight from a key jumps at once, a pointer one still flies" passes. A reduced-motion key flight also jumps with no world flash (flyTotestsflightKind === "key"before the reduced branch).Gate results
~/j378-main.log): keyboard-instant (14 cases), clusters-flight, clusters-shortcuts, palette-navigation: 27 passed, 0 failed (the log's "2 failed" are my own scratch probe's first version, rewritten and rerun below). Input-source unit test: 1 pass.scripts/verify quickon the clean merged tree (~/j378-quick.log): "QUICK pre-check passed", exit=0. (A first run failed only the "doc comments on diff" row because of my untracked probe files,~/j378-quick-with-probes.log; I moved them out and reran.)verify fast.P2 findings (details in the two comments above)
triggeredByKeyboard()insideCamera.flyTo.pill-morph.tsopen/close jump whentriggeredByKeyboard().P3
transitioncancelfires (~/j378-probe3.log, "letter during pointer fade"). Input is not blocked and the character lands (value "t"), but the globaldata-inputattribute also cuts running transitions, not only new ones. Acceptable if intended; a latch-at-open design would avoid the pop.data-input="keyboard"the capsule'stransition-durationis0s; after a pointer press it is0.12s opacity. Hover and cover-fade easing on.ui-key-instantelements stay off until the next pointer press (~/j378-probe.logsection of~/j378-main.log, "pill transitions after key vs after pointer"). Cosmetic.clusters-flight.spec.tskey bound is loose (< 300would still pass a 190 ms spring). The strict first-frame assertion lives inkeyboard-instant.spec.ts, so coverage is fine; just don't rely on the former.BODY(no restore), and underprefers-reduced-motiona pointer-open palette still runs the same 240 ms fade (0, 0.11, 0.22 … 0.92). Both identical with reduced motion on and off.Checked and fine
hasTouch): after a key,data-inputiskeyboard; a touch tap on the capsule flips it topointerand the palette animates (opacity 0 → 0.59 at 100 ms → 1); a hardware Escape then closes it in the first frame (~/j378-probe3.log).#palette-inputin the first frame,aria-modal="true"; the?panel opens asrole=dialog,aria-label="Keyboard shortcuts", focused, and Escape returns focus toBODY. Same with reduced motion on and off (~/j378-probe4.log).?open is instant, key camera flight jumps with no flash. No regression versus the non-reduced run.pointerdownis captured onwindow.Artifact:
j378-evidence.txt(attached; all frame samples and gate output). Probes (untracked, never pushed):~/j378-probes/on infraternal-dev-02-std. No screenshots: this is a timing change, so frame samples are the evidence. Nothing merged, pushed or deployed; scratch worktree removed.Verdict: REQUEST CHANGES. Reviewed SHA
0ae56a4e0. Gate: 27/27 required specs pass, unit pass,verify quickpass (exit 0),verify fastnot run.J370 round 3 start. Branch
fix-kbd-no-anim-427, merging origin/dev098f2c445onto0ae56a4e0. Plan, red specs first: (a)Camera.flyTopicks instant fromtriggeredByKeyboard(),keyFlightdropped if redundant; (b)pill-morph.tsjumps on a key; (c) P3s:.ui-key-instantdrops only open/close motion, tighten the clusters-flight key bound, Escape out of the palette restores focus, pointer-open fade respects reduced motion. Leaving the 'letter mid pointer-open snaps' P3 as is. Estimate about 2 h.J370 round 3, red evidence (dev-02 production build, logs
~/j370-r3red.logand~/j370-r3red2.log), before any fix, head13eb6f966(origin/dev merged in:098f2c445):clip-path: inset(0px 0px 167.322px round 20.8927px)(expected "none").transition-durationis still "0s" 150 ms after a key; Escape out of ⌘K leaves#sidebar-toggleunfocused (was focused before); under reduced motion a pointer-open palette has opacity "0" in the first frame (the reduced-motion rule.palette{transition-duration:0ms}loses to.palette:not([hidden]){240ms}on specificity).clusters-flight's key flight is already 0 ms (the bound is tightened to two frames, 34 ms, so a 190 ms spring now fails).13eb6f966(starting from the overview and from view 1, J378's sequences).Fixes are in separate commits on the branch (tracker wheel, Camera.flyTo, pill-morph, fresh latch, focus, reduced motion); green run to follow.
J370 round 3 finish. Branch
fix-kbd-no-anim-427, headda75ec79a(pushed, not merged), origin/dev098f2c445merged in.Fixes, one commit each (red specs first:
18c9bbe82, corrected in13eb6f966andc2549319b)085e24d24tracker:wheel(mouse wheel, trackpad swipe) sets pointer, so a swipe after typing still glides now that flights read the source.64b89c7bfP2-a:Camera.flyTojumps whentriggeredByKeyboard();keyFlight,flightKindand the palette's per-call source branches are removed, so no caller can miss it.bde107b9eP2-b:pill-morph.tsjumps on open and close from a key (the capsule's view list, sharing popover, floating terminal).89c0ef051P3: the CSS rule is keyed ondata-input-fresh, set by a key and cleared two frames later (thedata-look-swappattern), so.ui-key-instantsurfaces lose only open/close motion, not easing until the next pointer press.ba4ad7866P3: closing ⌘K returns focus to the element focused before it, when focus was left inside the palette.d15063e0bP3: the pointer-open palette obeys reduced motion (the media rule lost on specificity to.palette:not([hidden])).Red (dev-02 production build,
~/j370-r3red3.log, specc2549319bagainst the old source): 8 failed, 15 passed. Failing: Escape to overview, Ctrl+Shift+G, palette "All views"+Enter, palette window pick+Enter (frames showing the camera on its way > 0), Enter on the capsule (view listinset(0px 0px 167.322px round 20.8927px)in the first frame), capsule fade still off 150 ms after a key, focus not restored, reduced-motion palette opacity "0" in the first frame. The pointer controls pass on red.Green (
~/j370-g4.log,c2549319b): keyboard-instant (24 incl. the 8 above), clusters-flight (key ≤ 34 ms) and the rest pass: 24 passed, 1 failed. The failure isclusters.spec.ts:512(canvas lock on a phone, expects index 1, got 0), which fails the same way on unmodified origin/dev098f2c445(~/j370-base3.log). An earlier wider green run (~/j370-g3.log,d15063e0b: keyboard-instant, clusters-flight, clusters-shortcuts, palette-navigation, palette-polish, clusters, clusters-keyboard-split, canvas) had 120 passed; its 3 other failures were spec flaws in my new tests (fixed inc2549319b, passing in g4). The remaining commits after it are doc comments only. That covers pill-morph through the view list and the floating terminal (clusters.spec).Unit tests: input-source (wheel, two-frame window, modifiers, pointer) and spring: pass. Tracer typecheck passes.
verify quickatda75ec79a(~/j370-quick.log, dev-02): "QUICK pre-check passed", exit=0.verify fastnot rerun.Note: the view list's "Search everything" row opens the palette by dispatching a synthetic keydown, which the tracker counts as a key, so that one pointer click opens the palette instantly. Fixing it means ignoring untrusted keydowns (or having the row call the palette directly); I left it and can do either in a follow-up.
J389 start: round-3 review of
fix-kbd-no-anim-427@da75ec79a. Plan: scratch worktree on dev-02 with origin/dev (9965911c8) merged into the head. Then: grep every transition/animation in apps/tracer and packages/ui and drive the ones a shortcut can reach; check the centralCamera.flyTodecision for each key path in the task list; pill-morph Enter/Escape;.ui-key-instantscope; spec bounds; ⌘K focus restore; reduced-motion pointer fade; pointer/touch still animating. Production build, 1440x900 and 393x852: keyboard-instant, clusters-flight, clusters-shortcuts, palette-navigation, pill-morph specs, plusverify quick(the task asks for it explicitly; the brief's reviewer rule says otherwise, so I follow the task and name it in the report). Not merging, pushing or deploying.J389 finding 1 (P2): Space on the focused capsule opens the palette with the full 240 ms fade. Enter and the chords are instant.
Cause: commit
89c0ef051keys the CSS rule ondata-input-fresh, which a key clears two frames (~33 ms) after it. A button activated with Space firesclickon keyup, so the palette opens after the window has closed and.ui-key-instantno longer removes its transition. JS surfaces (triggeredByKeyboard(), persistent) are unaffected, so the two mechanisms now disagree for the same key.Evidence (production build of
da75ec79a+ origin/dev9965911c8, dev-02, log~/j389-main.log, probePROBE activationlines; key held 120 ms, per-frame sample):#capsuleEnter: first shown frame opacity 1 at +8 ms, 0 frames below 1.#capsuleSpace: first shown frameshown|0at +127 ms, 15 frames below 1, running#palette:opacity,#palette:transform,#scrim:opacity.#capsuleSpace: 16 frames below 1; also#sidebar-toggle,#capsule,.ui-pillopacity transitions running.#sidebar-toggleSpace is instant at both sizes (its open does not depend on the CSS rule).Failure scenario: a keyboard user Tabs to the capsule and presses Space (the other activation key). The palette fades in, which TASTE "Work is instant" (4) forbids, and Enter on the same button does not.
Suggested fix: make the rule not depend on a two-frame window for opens that a key causes later. Either latch
data-input-freshuntil the first of the next frame after akeyup/clickof the same key, or letcapsuleClick/scrimClick(and the other CSS-driven setters) add the attribute whentriggeredByKeyboard()is true at the moment they flip state. Add a spec: focus#capsule, hold Space 120 ms, first shown frame opacity 1.J389 progress on
da75ec79a(+ origin/dev9965911c8merged, scratch head 797a9eda9). Production build, dev-02,~/j389-main.log(required specs + my probe, 70 tests) and~/j389-r2.log(corrected probes, 8 tests).Required specs: all pass. keyboard-instant (24 cases, both viewports), clusters-flight, clusters-shortcuts, palette-navigation, input-source unit test. The 6 failures in the run are my own probe's, not the branch's: 4 were probe flaws (an arrow case that never moved the camera, a click on the current view, a float pick inside the current view), rerun fixed in R2 (8/8 pass); 2 are finding 1 (comment above).
Verified OK (frame samples; "on the way" = frames whose camera was strictly between start and end):
inset(0px round 19.8px)(whole), Escape: absent in frame 1. Sharing (⌘K "share"+Enter): 0 partly clipped frames, Escape: absent in frame 1. Floating terminal (Enter on theweb-apicontainer row): 0 partly clipped frames, Escape: absent in frame 1. Pointer click on the same row: 35/36 partly clipped frames (still morphs); touch tap on the view list at 393: 32 partly clipped frames.flight()counts frames strictly between start and end (0 required) and clusters-flight allows ≤ 34 ms. Tight.Finding 2 (P3): shortcuts that still run transitions, not open/close. Sweep of 14 shortcuts (
PROBE sweep, first 90 ms): Ctrl+Shift+L runs.ui-windowborder-color and.ui-window-lockcolour/opacity transitions (180 ms); Ctrl+Shift+Left/Right (window stepping) runs the.ui-windowborder-color transition, a.bm-markertransform transition and a Web Animation on an SVG element. TASTE (3) says "rapid window stepping" does not animate. Neither is an open or close, and origin/dev does the same, so it is outside #427's "open/close" wording; flagging because the task asked to hunt every remaining key-triggered motion. Ctrl+Shift+D/W/Enter,?, Escape, F6, Ctrl+Shift+P/, show none.Finding 3 (P3):
.ui-key-instantscope is right but its lifetime is a guess. It only setstransition: noneon the palette, scrim, sidebar and the three pills, and only for two frames after a key, so hover/cover easing returns (spec "motion only around the key" passes). The same two-frame guess is what breaks Space (finding 1); any future opener that runs more than ~33 ms after a key will animate.Cost so far: no
verify fastrun (task asked for specs +verify quick).J370 follow-up pushed (head
2a24a9d1d): tracker ignores untrusted events (d44a9814c), Search everything calls core.showPalette() directly. Red specc43bf28d1(sampler corrected inff1e51700), docs2a24a9d1d. An earlier combined run atd44a9814cpassed the 37 keyboard-instant, palette-navigation, palette-polish and clusters-flight cases and the unit test (~/j370-f1green.log); the final red/green/quick run on2a24a9d1dis queued on dev-02 behind a long queue, results to follow.J370 follow-up finish. Branch
fix-kbd-no-anim-427, head2a24a9d1d(pushed, not merged).Commits on top of
da75ec79a:c43bf28d1red spec: the view list's "Search everything" row opens the palette with a fade; the real chord stays instant.d44a9814cfix:input-source.tsignores events withisTrusted === false(keys and pointer events); the row callscore.showPalette()directly (the entries argument is now optional) instead of dispatching a synthetic Control/Command+K. The other synthetic dispatches (toolbar "Search and actions", the mockup tag) now read as the pointer clicks they are, with no change to them.ff1e51700spec: the frame is taken after the click, not at the press (the first red failed for that reason).2a24a9d1ddoc comments forverify quick.(That is four commits, not one: the red spec, the fix, a spec correction and the docs row, so that the red-first order stays visible.)
Red (
~/j370-f3red.log, dev-02 production build, old sourcec43bf28d1with the final spec): fails with "the palette opened: expected false, received true", i.e. the row did not open the palette at all. The synthetic key it sent was Control+K, and on a non-Mac platform the palette's chord is Control+Shift+K (Control+K belongs to the shell). So on Linux and Windows the row was dead, which the direct call also fixes.Green (
~/j370-f3green.log,2a24a9d1d): keyboard-instant, palette-navigation and palette-polish: 36 passed, exit=0; the input-source unit test (untrusted key, untrusted pointer, trusted ones, modifiers, wheel, two-frame window): 1 pass. An earlier run atd44a9814c(~/j370-f1green.log) also passed clusters-flight and the typecheck: 37 passed.verify quick(~/j370-f3quick.log,2a24a9d1d): "QUICK pre-check passed", exit=0. First attempt (~/j370-f1quick.log) failed only the doc-comments row; fixed in2a24a9d1d.verify fastnot run.Note for the unit test:
isTrustedis an unconfigurable property of every real event, so it drives the tracker with a stand-in window and plain objects.J389 review of
fix-kbd-no-anim-427@da75ec79a, plus the delta to2a24a9d1dVerdict: REQUEST CHANGES. One P2 (Space on the capsule), two P3. The rest of round 3 holds.
Reviewed SHAs
da75ec79a: reviewed in full. Scratch merge with origin/dev9965911c8= 797a9eda9.2a24a9d1d(J370's later 4 commits: untrusted events ignored by the tracker, "Search everything" opens the palette directly, spec, docs): delta read, its new spec run. Scratch merge with origin/dev8e664e6b7= c72af681c.Findings
data-input-freshclears two frames after the key and Space clicks on keyup. Enter and the chords are instant, so the same button behaves two ways. Still present at2a24a9d1d(same numbers in~/j389-new.log).data-input-freshwindow is a timing guess; anything that opens more than ~33 ms after a key animates.Verified (frame samples, production build, 1440x900 and 393x852)
flyTopath..ui-key-instantremoves only the open/close transition, and only around the key.2a24a9d1d:isTrustedfilter and the Search-everything direct open are right; no other source relies on a synthetic key (toolbar/row.ts:25is now correctly a pointer open too).clusters.spec.ts:512(canvas lock on a phone): I agree it is not this branch's. It fails the same way (expected 1, received 0) on the merged tree and on plain origin/dev8e664e6b7(~/j389-c512-j389.log,~/j389-c512-j389-base.log).Gate results
~/j389-main.log, 64 passed, 6 failed, all in my own probe: 4 probe flaws, fixed and rerun 8/8 in~/j389-r2.log, 2 are the P2).verify quick: passed, exit 0 (~/j389-quick.log).verify quick: passed, exit 0 (~/j389-new.log,~/j389-quick-new.log).verify fastnot run (not requested). The brief's reviewer rule says not to runverify quickon a reviewed branch; I ran it because the task asked, on scratch merges.~/j389-probes/j389-probe.spec.tson dev-02. No screenshots: timing change, frame samples are the evidence.Nothing merged, pushed or deployed.
J370 round 4 start. Merged origin/dev
0a5432d2cinto fix-kbd-no-anim-427; red specs pushed (6a1b1b893), run queued on dev-02. Plan: dropdata-input-fresh; every open/close setter (palette, scrim, covered pills, sidebar, glass bed) callsmarkMotion(el), which writesdata-motion="instant"|"animate"fromtriggeredByKeyboard()at that moment, and CSS keys off the element's own attribute; Space/Enter keydown count as keyboard until the next trusted pointer event (already so); window cards (setActive/setLocked) and the tree'sselectdo the same so stepping and the lock don't run border, lock-icon, marker or draw-on motion. Estimate 2 h plus queue.J370 round 4 progress (red). dev-02's build-slot is stuck: slots 2 and 3 show free while its queue head, pid 471771 (job j287), runs a deleted older copy of the script and has waited 2 h, so my jobs ran on compute01 instead. Red at
6a1b1b893(~/j370-r4red.logon compute01): the late-open case fails at both viewports (a script click 100 ms after a key opens the palette with the fade) and Ctrl+Shift+Right, Ctrl+Shift+Left and Ctrl+Shift+L each leave running transitions or animations on window cards, lock icons or the tree one frame later. The Space and Enter cases passed on red because press() releases the key inside the old two-frame window, so470f78266holds the key 100 ms (as a person does); the pointer control also needed a visible window. Fixes pushed:c56f5bb0e(data-motion, markMotion, fresh window removed),97f17d658(window card, lock, tree). Green/quick on470f78266queued.J370 round 4 finish. Branch
fix-kbd-no-anim-427, head4b2fea905(pushed, not merged), origin/dev0a5432d2cmerged in.Redesign (one mechanism, no time window)
c56f5bb0e:data-input-freshand its two-frame timer are gone.markMotion(...elements)(input-source.ts) is called by each setter right before it flips: it writesdata-motion="instant"whentriggeredByKeyboard()and"animate"otherwise, onto the element, until that element's next change. The palette, scrim, covered pills, sidebar and its toggle (also its pane glide) and the glass bed use it; the CSS keys off the element's own attribute. The tracker already counts a trusted Space/Enter keydown as keyboard until the next trusted pointer or touch event, so Space's click on keyup finds it (unit test added).97f17d658+f00433577: window cards (setActivewhen the state changes,setLocked) mark themselves, so the border and lock-icon fades drop for a key; the pointer-driven lock reveal writesanimate;branched.select()lays out the tree marker and branch with no animation for a key;pulse()(the 360 ms swell) returns for a key. Pointer equivalents keep theirs.createPillMorphand the shortcuts view callmarkMotion(pill)at open and close, and the shared rule ishtml:root …so it beats the pills' own transition rules (the plus pill still faded at phone width).Red first (
~/j370-r4d-red.log, compute01, production build; final spec on the old source6a1b1b893): 7 failed, 27 passed. Space on the capsule (both viewports), a surface opening 100 ms after a key (both), Ctrl+Shift+Right, Ctrl+Shift+L, and "a pointer change after a key animates the same elements again" fail; the pointer controls pass. (Ctrl+Shift+Left passed on red: from the test's starting window it moves nothing, so it only guards against regression.) Space and Enter first passed on red becausepress()releases the key inside the old window; the spec now holds the key 100 ms.Green at
4b2fea905(~/j370-r4f-green.log: keyboard-instant, palette-navigation): 35 passed; input-source unit test: 1 pass; tracer typecheck passes. Atf00433577(~/j370-r4e-green.log, which also ran clusters-flight, clusters-shortcuts and palette-polish): 51 passed; its 2 failures were the terminal cursor's blink counted as a response (fixed in4b2fea905) andpalette-navigationfilter-handler budget 0.187 ms vs 0.13 on a busy host (it passed in the earlier run and in the4b2fea905run). New cases: Space and Enter on the capsule, a late opener 100 ms after a key, the three window/lock chords, a pointer click that still fades a border, and the pointer-after-key animate case. Pointer-fade checks now sample inside the page at the first frame after the event, so a slow host cannot make a fade look finished.verify quickat4b2fea905(~/j370-r4f-quick.log): "QUICK pre-check passed", exit=0.verify fastnot run.Infra note for the orchestrator: dev-02's
build-slotwas stuck for hours: slots 2 and 3 showed free while its queue head (pid 471771, job j287) ran a deleted older copy of the script and never took them, so my runs went to compute01.~/infraternal-ops/slotssays 3.Not covered: the "nothing animates more than 33 ms after a key" guarantee holds for every surface wired to
markMotionand for camera flights, pill morphs, the shortcuts panel, window stepping and the lock; a new opener has to callmarkMotion(ortriggeredByKeyboard()) when it flips, which is the single rule in input-source.ts.J370 correction to my round 4 finish comment: the commit I wrote as '7d…' (the pill's own fade follows the same answer when a morph opens or closes) is
831ca81a8.J403 start: round-4 review of
fix-kbd-no-anim-427@4b2fea905(J370'smarkMotionredesign). Plan: scratch worktree on dev-02 (~/worktrees/j403) with origin/dev44e80ccc5merged in; source audit of every transition/animation/WAAPI use reachable from a shortcut (checking each opener/closer callsmarkMotionortriggeredByKeyboard()); stale-state, iPad hardware-keyboard + touch, reduced-motion, focus-return andhtml:rootspecificity checks; then a production build at 1440x900 and 393x852 running keyboard-instant, palette-navigation, clusters-flight, clusters-shortcuts, palette-polish, the pill-morph coverage, the input-source unit test, andverify quick(the task asks for it explicitly; the brief's reviewer rule says otherwise, so I follow the task and name it in the report). Frame-sample evidence. Also a recommendation on a guard against a forgottenmarkMotion. Not merging, pushing or deploying.J403 progress (source audit done on a local scratch merge of
4b2fea905+ origin/dev44e80ccc5= a24996c08; runtime proofs queued on dev-02, which has 3 busy slots and 4 queued). Candidate findings from reading, each to be proven with frame samples before I post it as a finding:data-motion="instant"persists until the element's next change and CSS setstransition: nonefor it, so a keyboard palette or sidebar open leaves#capsule,#sidebar-toggleand the "+" with no transition at all, and.ui-pill's own 140 ms press-scale (:active) snaps, until the next palette or sidebar change. Same for a window card after Ctrl+Shift+arrows (border colour) and its lock.bed.setOpen, tooltip.ts:370) opens instant while its card animates.cx.win.split(active, dir)/newWindowwithoutinstant(palette-actions.on-demand.ts:34-35), while the chords passtrue; the FLIP and enter spring may play.Not yet checked at runtime.
J403 status (01:50 IST): still waiting for a dev-02 slot (queue position 6 of 3 busy slots; my first slot was spent on a run that failed at once: the fresh worktree had no
apps/tracer/node_modules, then a shell-quoting slip in my own-gpattern. Both are my harness's, not the branch's; fixed and requeued). Candidate 2 from my earlier comment is withdrawn:bed.setOpenis only called by the confirmation tip (tooltip.ts:370), opened by a click or key, never by hover. New thing I will measure: that same key-opened confirmation, whose glass bed is now instant while the card's owndata-openfade is not wired tomarkMotion. No verdicts yet.J403 finding 1 (P2): a key-opened confirmation (
createConfirmTip, tooltip.ts) still fades in. It is a key-reachable opener that does not callmarkMotionortriggeredByKeyboard().Evidence (production build of
4b2fea905+ origin/dev44e80ccc5, dev-02,j403-B.loglinesPROBE confirm): palette ⌘K → "sign out" → Enter (key only). The confirmation's opacity per frame is0, 0, 0.178, 0.339, 0.488, 0.623, 0.742, 0.844, 0.925, 0.979, 1: 8 fractional frames (about 130 ms), with#ui-confirm-tip-1:opacityand:transformrunning. Same numbers at 1440x900 and 393x852. The pointer click on the same row gives the same series, so the key path is not instant. Thebed(glass backing) opens at once in both paths (0, 1, 1…); it is attached and flipped in one frame, so it never had a transition. Consequence: the branch'smarkMotion(bed)inglass-bed.tschanges nothing visible here, and the real surface (the tip,[data-open]CSS) is not wired.Failure scenario: a keyboard-only user runs ⌘K → "Sign out this device" (or "Remove host", or Enter on any button that asks) and the confirmation grows in with a 130 ms fade. TASTE: keyboard opens are instant. Closing by Escape/Enter goes through
close()(dataset.open="false"plus a 190 ms removal timer) and is the same class.Suggested fix:
createConfirmTipcallsmarkMotion(tip, bed)where it flipsdataset.open(open andclose()), with anhtml:root .ui-confirm-tip[data-motion="instant"] { transition: none }rule (or add the classui-key-instant). Add a case to keyboard-instant.spec.ts: palette → sign out → Enter, first frame opacity 1.J403 finding 2 (P2): palette Enter on "New window right/below" (and the split rows) animates; the chord does not. The windows module takes a per-caller
instantflag, and the palette caller never passes it.Code:
palette-actions.on-demand.ts:34-35callscx.win.split(active, dir)andcx.win.newWindow(active, side)withinstantunset, whileshortcuts.tspassestrue.split.on-demand.ts:114plays the FLIP slideif (!instant). The palette's source is "keyboard" there (runAction(…, "keyboard")), but nothing reads it.Evidence (clusters mockup,
j403-B.loglinesPROBE window-action): Ctrl+Shift+Enter vs palette "New window right" + Enter, frames after the key. Palette path:.cl-col:waapi(the FLIP) running for the sampled window (29 frames at 1440x900, 31 at 393x852 with running animations); chord path: no.cl-colanimation (only the ambient connection pulse that is also present in every run). Window count 35→36 on both paths.Not shown by the sampler: palette "Split right/down" (the chosen row's text came back empty in my probe, window count 35→36, no FLIP seen); I did not prove it, but it shares the code path.
Failure scenario: ⌘K, type "new window", Enter: the other columns slide aside for about a quarter second, while the same action from its chord is instant.
Suggested fix: decide inside the primitive, as
Camera.flyTodoes:split.on-demand.tsdefaultsinstant = triggeredByKeyboard()(andland()'sfocusWindow(…, instant)follows). One line per entry point and no caller can miss it again. Add a case: palette → "New window right" → Enter, no.cl-colanimation.J403 findings 3 to 6 (P3). All four are about how the mechanism ages, none is a user-visible defect today.
3.
data-motion="instant"is a persistenttransition: noneon shared elements. After one keyboard palette open/close,#capsule,#sidebar-toggle, the "+" and#palettecarrydata-motion=instantand computetransition-property: none(fresh:opacity 0.12s; the toggletransform 0.26s, opacity 0.12s). After Ctrl+Shift+arrows the stepped-from and stepped-to cards computetransition: none(fresh:border-color 0.18s). A pointer open/close resets all of them toanimate. Measured inj403-A.log/j403-B.log(PROBE stale,PROBE cards). No visible effect today: those pills' only transitions are the open/close fades and the card's only is the active border, and I checked the press scale (matrix(0.97…)the same value either way, because.top > .capsulealready replaces.ui-pill's transform transition). But the next hover or press transition added to a.ui-key-instantelement, or to.ui-window, silently dies after the first key press until that element's next change. Suggest narrowing the rule to the open/close properties, or documenting it next to the rule and in TASTE.4. The docs promise more than the mechanism does. input-source.ts says a change "no key caused (a timer, a network event)" reads as pointer. It reads as pointer only until the first key: a person typing in a terminal then gets every timer or network-driven camera flight, window enter, glass bed or sidebar change as instant. This errs towards instant (safe), but fix the wording; reading only, not measured.
5. Activations that carry no pointerdown keep the last source. VoiceOver and Voice Control activations (and any script
.click()) sendclickwithout a trusted pointerdown, so after typing they read keyboard. Same direction as 4, from reading only. A touch tap, trackpad click and wheel all reset it (measured on a 1024x1366 touch context below).6. Two mechanisms still exist.
markMotionfor CSS surfaces, butsource: "keyboard"|"pointer"parameters on the anchored popover, settings overlay, details and the windows'instantflag are fed by each caller (e.detail === 0, hard-coded "pointer" inpalette-actions.on-demand.tsfor "Sessions on this host", …). Finding 2 is exactly one of those callers being wrong. See my recommendation for a guard in the final report.J403 finding 7 (P2): palette Enter on "Sessions on this host" opens the session manager popover with its fade. Same class as finding 2: the handler hard-codes the source (
palette-actions.on-demand.ts:cx.sessionUi?.toggleManager(active, anchor, "pointer")), although the row was picked with Enter.Evidence (
j403-C.log,PROBE sessions; production build, clusters mockup): popover opacity per frame after Enter,0, 0, 0.339, 0.602, 0.775, 0.877, 0.934, 0.966, 0.984, 0.993at 1440x900 and at 393x852. A key-open should be whole in the first frame. (details.toggle(rec, "keyboard"), a few lines down in the same dispatcher, passes the source right.)Suggested fix: pass
detail?.source === "keyboard" ? "keyboard" : "pointer"here, and better, makeopenAnchoredPopovertake its source fromtriggeredByKeyboard()so the third argument disappears.J403 review of
fix-kbd-no-anim-427@4b2fea905(scratch merge with origin/dev44e80ccc5= e0a7ac2b7)Verdict: REQUEST CHANGES. Two P2 findings of the same kind, which the new design does not prevent: key-reachable openers that never call
markMotionortriggeredByKeyboard(). The mechanism itself is sound; the work left is to make its coverage hold by construction.Findings
createConfirmTip) fades 8 frames (about 130 ms): palette → "Sign out this device" → Enter. The glass bed is instant in both paths, somarkMotion(bed)buys nothing there..cl-colFLIP slide; the chord is instant.palette-actions.on-demand.ts:34-35omits theinstantargument."pointer".data-motion=instantis a persistenttransition: noneon pills, cards and lock; no visible effect today, but the next hover or press transition on those elements dies silently after the first key..click()) keep the last source. Both err towards instant. Reading only.source/instantparameters survive besidemarkMotion; findings 2 and 7 are two callers that got them wrong.Verified OK (frame samples,
probes-frame-samples.txt,j403-A.log,j403-B.log, production build)data-motion=instanton#palette,#capsule,#sidebar-toggle, "+" and the stepped cards; one pointer open/close writesanimateon all of them (palette, pills) and the next pointer change animates (iPad run below shows the tap open at 14 fractional frames, scrim tap close at 7). No stale-instant leak on a pointer change.data-motion=instant; touch tap on the capsule: palette fades (14 fractional frames),data-motion=animate,data-input=pointer; key close of the tap-opened palette: instant; scrim tap: 7 fractional frames. Touch resets the source (pointerdown), keys set it back.html:rootbump: the rule only matches elements that carry both the class anddata-motion="instant", so unrelated rules are untouched. It does win over.ui-pill.sidebar-toggleand.top > .capsuletransitions on those elements, which is its purpose; verified by the phone-width plus pill fade spec passing at 393x852. The only side effect is finding 3's persistence.Camera.flyTo.Audit of animation sites (grep of
.animate(,new Spring(, CSS transitions in apps/tracer and packages/ui)Wired to the input source: palette, scrim, covered pills, sidebar and toggle, glass bed, pill-morph, shortcuts panel, window card active/lock, tree marker,
pulse, camera. Reachable from a key and not wired (own per-caller flag or nothing): confirm tip (finding 1),split/newWindowfrom the palette (2), session manager popover from the palette (7); anchored popovers, settings overlay and details take a caller-passedsource, and settings via palette Enter was instant in my sample. Not reachable from a shortcut (pointer-only by nature): drag/resize/move springs, toasts, add-host wizard prototypes, chip input, count-up, status line.Is there a cheap guard against a forgotten
markMotion?Yes, two, and I recommend the first as the required one:
registerShortcutsalready lists every chord. A Playwright test iteratesshortcutSections(["canvas","global"]), presses each combo on a fresh canvas, and fails if any non-allowlisted CSS transition, Web Animation or inline-spring style is running two frames later. A new shortcut is then covered without anyone remembering. Add the same loop over the palette rows (type the label, Enter), which would have caught findings 1, 2 and 7 on the day they were written.Camera.flyTodid. GiveopenAnchoredPopover,split/newWindow,createConfirmTipand the settings overlay a default oftriggeredByKeyboard()instead of a caller-passed flag. Then removing the parameter makes the mistake unrepresentable. Ascripts/doc-coverage-style baseline of.animate(/new Spring(sites would also work but only forces a classification, not a behaviour.Gate results (all on the scratch merge e0a7ac2b7, dev-02 production build)
j403-A.log).clusters.spec.ts: capsule view list, container shell/floating terminal, top pill): 4 passed at 1440x900, 4 passed at 393x852.verify quick: QUICK pre-check passed, exit=0 (j403-quick2.log). An earlier run failed two rows (doc comments, fixed waits) only because my own untracked probe files were in the tree; moved out, it passes.verify fastnot run (not requested; the brief reserves it for the author and the merge). Nothing merged, pushed or deployed. The brief's reviewer rule says not to runverify quickon a reviewed branch; I ran it because the task asked, on a scratch merge.j403-probe.spec.ts,j403-c.spec.ts. No screenshots: this is a timing change, so frame samples are the evidence.J370 round 5 progress. origin/dev
966c52e07merged in. Pushed (head075b52395):becf9e4dethe sweep guard (every ? panel chord and every palette row, Enter, nothing may still move from the fourth frame; idle motion is measured first and ignored),8f6674455the open/close durations now scale by--ui-motion-scale(P3-3: only those transitions collapse, not every transition on the element; also wires the confirmation tip, P2-1),c3be393bepopovers, the settings overlay, split/newWindow/step/move/close and toggleManager read the tracker themselves (P2-2, P2-3, P3-6 for these primitives),075b52395doc for non-press changes (P3-4/5). Red run of the sweep on4b2fea905and the green run are queued on dev-02.J370 round 5 finish (J403's findings). Branch
fix-kbd-no-anim-427, head86b9719c2, pushed from the control host (git ls-remote origin fix-kbd-no-anim-427→86b9719c2…). Not merged. origin/dev966c52e07merged in.The guard (
becf9e4de, then27f92469c/77cfea1f7/a61578cbe) —apps/tracer/test/keyboard-sweep.spec.ts. It reads the chords from the?panel and the rows from the palette itself (one row per action family), boots the Console scene with a terminal active, presses each chord or types the row and presses Enter, and fails if anything new is still moving from the fourth frame on: a running transition (open/close geometry only: opacity, transform, translate, scale, clip-path, size, position), a script animation, or an inline transform/clip-path/opacity still being rewritten (springs). Motion already present while the page sat idle is ignored. Named exceptions, each with its reason in the file: the test double's badge, the terminal cursor's blink, a window's connection indicator morph on a network change.Red (
~/j370-r6red.log, dev-02, spec against 4b2fea905's source) names, among others: Sign out → confirmation tip fades (opacity/transform, 10 frames); New window right →.cl-colFLIP andsection.cltransform; Rename host, Settings, Split right/New window below → anchored popover animation; Close window → toast; Control+Shift+L / Escape / SSH shell →#keyrowstransform; Open shell on a host → window swell. So it catches the three P2s and more.Fixes (one commit each)
8f6674455P3-3 + P2-1: open/close transitions are writtencalc(Nms * var(--ui-motion-scale, 1))and[data-motion=instant]sets the registered, non-inherited--ui-motion-scaleto 0, so only those collapse; the confirmation tip marks itself where it flipsdata-open.c3be393beP2-2, P2-3, P3-6:openAnchoredPopover, the settings overlay,win.split/newWindow/step/move(theirinstantparameter is gone),win.closeandtoggleManagerread the tracker themselves; the palette's hard-coded "pointer" and missinginstantare gone. The.ui-key-instantclass is removed.075b52395P3-4/5 doc: non-press changes and clicks without a trusted pointerdown follow the last source and err toward instant.74fd410d9→ tray rows (settleRow) and the lock button's own mark (the non-inherited scale needs it on the child);65a19b070window enter/FLIP for a key-opened window, toast stack;a61578cbeneighbouring views' position springs and the add-host card;0a71b697cits footer and close.Green at
0a71b697c(~/j370-r10.log, dev-02): 55 passed, 0 failed — keyboard-sweep (chords and palette rows), keyboard-instant, clusters-flight, clusters-shortcuts, palette-navigation, palette-polish; input-source and session-hooks unit tests pass; tracer typecheck passes. Later commits are doc comments only.verify quickat86b9719c2(~/j370-r11quick.log): "QUICK pre-check passed", exit=0.verify fastnot run.Residual (said plainly): the explicit
source/howarguments remain where a surface needs them for focus placement or timing, not motion: account and version panels, row menus, bottom sheets, the sidebar card morph, details and docs popovers,LockSource. The four primitives you named no longer take a source for motion, andclose()on the anchored popover still accepts an ignored argument for wrappers. Not covered by the sweep: rows that need a second state (a locked window, a team layout) and Mac chords (the panel lists the Linux ones on this host).J370 correction to the round 5 finish comment: the tray-rows and lock-button commit is
7dc09f440(I wrote74fd410d9, which is the doc/allowlist commit after it).J413 progress (round 5 review of
fix-kbd-no-anim-427@86b9719c2). Scratch merge with origin/dev0414b7b2f= 92da9ebb1 (clean, only DECISIONS.md changed). Production build on dev-02,~/j413-A.log.Green so far on 92da9ebb1:
verify quick: exit=0. input-source + session-hooks unit tests and tracer typecheck: exit=0.setViewportSize(1440x900)insidefresh(), so I ran a copy that takes the viewport from the environment; the 393x852 result is from that copy.Still to run: the committed sweep against plain origin/dev
0414b7b2f(must fail), and a check that--ui-motion-scaledoes not reach children. Candidate finding being measured:grid-template-rowsdisclosures (.cl-pvconsent pane,.ac-pane,.ui-inbox-panel) are outside the sweep's geometry filter and not wired to the input source. No verdict yet.J413 review of
fix-kbd-no-anim-427@86b9719c2(scratch merge with origin/dev0414b7b2f= 92da9ebb1)Verdict: REQUEST CHANGES. The mechanism and the fixes for J403's three P2s hold. Two P2s remain, and both are about the guard: the sweep promises that no key-reachable surface moves, and it leaves out the case it most needs to catch.
Findings
P2-1: the sweep's palette family rule never samples six rows, one of which animates.
keyboard-sweep.spec.tstakesfamily = action.slice(0, action.lastIndexOf(":")). An action with one colon (canvas:sessions,canvas:close,canvas:overview,canvas:windowdocs,canvas:inputlock,canvas:share) therefore falls into the familycanvas, whose sampled row is "Add hosts". Evidence is theHOLE sampledline in~/j413-hole.log: 25 families, and["canvas","Add hosts"]is the only sample for all six rows.div.cl-regionfading its opacity for 16 frames from 3 frames after the key.P2-2: a key still fades the view-region frames (
.cl-region, 220 ms), and theEscchord row is vacuous..cl-region { transition: opacity 220ms }is keyed on.cl-world[data-zoom="out"], which the camera writes (camera.ts:100,151). It is not wired tomarkMotionor--ui-motion-scale. A key that goes to the overview jumps the camera, then the region frames fade in over about 270 ms.transition opacity on div.cl-region(j413-hole.log).?panel's "All views (overview) = Esc" row passed the sweep only because it did nothing. Afterfresh(),Escapewith the terminal focused and with focus blurred both leftdata-zoom="in", with no findings (j413-esc.log,ESC terminal-focusedandESC blurred). The sweep presses a chord that never reaches the overview..cl-regionand.cl-labelfades ascalc(220ms * var(--ui-motion-scale, 1))and callmarkMotion(world)where the band flips. Make the Esc row meaningful: blur the terminal and assertdata-zoomchanged, or fail when a pressed chord changes nothing.P3-3: the sweep's property filter hides
grid-template-rowsdisclosures. From reading, not measured.GEOMETRYhas nogrid-template-rows,max-height,margin,filterorinset. The tree's.bm-foldalready honours a key throughno-motion. The disclosures.cl-pv(the access-level consent pane),.ac-pane,.ui-inbox-panel,.ah-revealand.ui-setting-refusaltransitiongrid-template-rowsat 200 to 340 ms with no input-source hook.access-level.on-demand.ts:239setsdata-openstraight from the "Access level" button, and the palette'scanvas:accesspath presses it from Enter. I could not measure it: the clusters mockup has no "Allow full access" row (ACCESS: no row in this scene). Add the property to the filter and note it among the exceptions.P3-4: palette rows hard-code a source for motion in the pointer direction (errs toward instant).
openWindowDocs(cx, active)defaults to"keyboard", anddispatchCanvasActionaccesscallsdetails.toggle(rec, "keyboard"). A pointer click on those palette rows therefore opens instantly. Passdetail.source, or read the tracker.P3-5: the sweep's frame threshold depends on host speed. A move needs at least 4 late frames. A 130 ms fade on a loaded host that renders about 20 fps shows 2 to 3 frames and passes. The red run still catches the real defects, but a green sweep on a busy host is weaker evidence.
The four things I was asked to check
?panel lists 27 rows. The sweep presses about 22 of them: both lock chords, the four splits and new windows, close, next and previous, the four moves, Read about this window, F6, Shift+F6, Ctrl+Shift+Space, the palette chord and the three font keys. Its skips are justified except the vacuous Esc row (P2-2):Alt+clickandScrollare pointer entries.Ctrl+Shift+1–3: I pressed 1, 2 and 3 myself and nothing moved (PROBE view-digit, both viewports).ReloadandSign out of every deviceare fine (page navigation, and the same confirmation tip as Sign out).--ui-motion-scaleleak and reduced motion. The leak check passed (LEAKline inj413-leak.log): on the palette it is0, all 400 descendants read1, and descendants keep their own durations (ui-conn-gkeeps0.16s, 0.24s). Reduced motion istransition: nonefor.palette,.palette:not([hidden])and.palette-scrim, and the pointer-open reduced-motion case passes in keyboard-instant (both viewports). My own reduced-motion sampler read the first frames before the click landed, so it proves nothing. Safari's@propertyandcalc(time * number)handling is untested.pointerdown, and J403 measured an iPad context in round 4.source.event.detail === 0the behaviour is right. I verified Enter on the focused window pill (details open with nothing moving at both viewports), Enter on the "Sessions" popover at 393, and key-close of a pointer-opened details.tabIndex = -1, so a keyboard cannot reach it. The hard-coded"pointer"atrow-pill.ts:115is true.LockSourcereach no motion, becausesetLockedand the popovers read the tracker themselves.Gate results (scratch merge 92da9ebb1, production build, dev-02)
0414b7b2f: both tests fail, as required (j413-dev.log, 2 failed). Chords named include: Split right, New window right and below, Input lock, Close window, Rename build-01, Settings, Show keyboard shortcuts, Open the command palette, Add hosts, Sign out, SSH shell and Open shell on a host.verify quick: exit=0.fresh().verify fast(not requested). Not merged, pushed or deployed.~/.cache/codex-scratch/j413/receipts/on dev-02:j413-A.log,j413-dev.log,j413-leak.log,j413-hole.log,j413-esc.logandj413-probes/.verify quickon the reviewed branch. I ran it because the task asked for it, on a scratch merge.J370 round 6 finish (J413's findings). Branch
fix-kbd-no-anim-427, headc11a47562(origin/devcedeb4d26merged; pushed,git ls-remoteagrees). Not merged.Merge note: dev's D372 motion tokens (
--t-press,--t-pop,--t-panel,EASE_OUT) conflicted line by line with this branch's scaled transitions (8ed45db67). Each open/close transition keeps dev's token multiplied by--ui-motion-scale; dev's palette rule with the 180 ms key fade is dropped.Fixes
3e7476c04P2-1, P3-3, P3-5, Esc (spec): everycanvas:verb is swept on its own (argument families still take one row); Escape row non-vacuous (the Console scene opens a popover that eats the first Escape; the sweep closes it, blurs the terminal, presses the chord, and fails ifdata-zoomis notout); motion is measured in time (still seen 50 ms after the key, and for ≥ 70 ms after that), so a slow host cannot hide a fade under a frame floor; grid rows, max-height, inset, filter join the properties; runs at 1440x900 and 393x852.21f95f8cdskips theMockup:scripted-scene rows (documented).e99de3e10P2-2 + P3-4: the camera marks the world wheredata-zoomflips and.cl-region's fade scales by--ui-motion-scale; "Read about this window" and "Allow full access" take the source from the tracker.Red (
~/j370-s1red.log, dev-02, new sweep on 86b9719c2's source): at both sizes the only findings areAll views (overview) (Escape): transition opacity on div.cl-region (moving from ~55 ms to ~255 ms)andAll views: transition opacity on div.cl-region (...); the Esc chord reaches the overview (no "did not reach" message).Green at
c11a47562(~/j370-s4.log, dev-02): 57 passed, 0 failed — keyboard-sweep at 1440x900 and 393x852 (shortcuts and palette rows), keyboard-instant, clusters-flight, clusters-shortcuts, palette-navigation, palette-polish; unit tests and tracer typecheck pass.scripts/verify fastatc11a47562(dev-02,~/j370-fast2.log), verbatim table: every row PASS exceptcargo-deny | FAIL (1),privileged integration | SKIP;VERIFY_EXIT=1. The failing row iserror[vulnerability]: libsqlite3-sys via C SQLite CVE-2026-119375 (RUSTSEC-2026-0459)onlibsqlite3-sys 0.30.1in Cargo.lock. This branch does not touch Cargo.lock;cargo deny check advisorieson plain origin/dev fails the same way (~/j370-denydev.log: "advisories FAILED", exit 1). Not mine.Round 6 review of
fix-kbd-no-anim-427@c11a47562(origin/dev merged:cedeb4d26)Verdict: APPROVE, with one follow-up that should ride on the merge or be filed (P2-A) and four P3s. Every round-5 finding is fixed and the guard now fails where it must. No P1.
I ran everything on dev-02 through build-slot, in my own worktrees (now removed). I did not run
verify quickorverify fast. Receipts are in~/.cache/codex-scratch/r427/receipts/on dev-02, along with the probe specs.1. Sweep red on dev, green on the head: confirmed
keyboard-sweep.spec.tsagainst origin/dev6df0f5bd5(newer thancedeb4d26) fails 4/4. That is both tests at 1440x900 and at 393x852. Log:r427-red.log. It namesAll views (overview) (Escape)andAll views, withtransition opacity on div.cl-region (moving from ~55 ms to ~290 ms)plus the camera'sstyle transform on div.cl-world. The Esc chord reaches the overview ("did not reach" never appears), so it no longer passes vacuously.c11a47562passes 4/4 (15.8 min): shortcuts and palette rows, at both sizes. Log:r427-green.log.2. Hunt for missed key-reachable surfaces
I used a probe harness that reuses the sweep's watcher: CSS transitions,
getAnimations()and inline transform/opacity/clip-path rewrites, per frame, with the sweep's own thresholds. Probe 3 moves the cursor off the page first, so hover cannot pass for a response to the key. Probe 1 left it parked, and its first-run "moves" turned out to be hover tooltips and hover summaries. Specs and logs are in the receipts directory.Clean (nothing moved after the key):
Ctrl+Alt+arrows, F6, Shift+F6 and Escape, at both sizes. The three breadcrumb pills with Enter, ArrowDown and Escape. Palette Settings panesAppearance › Theme/Font/Size/Layoutat 393.r427-p4-branch.log). Nothing moves, and the wizard goes on the first Escape. A hang I saw in my first add-hosts probe was my own harness (getAttributeon an element that had just gone), and it does not reproduce (12 keys, no hang).ca=locked. These cover the window pill and "More window actions", the capsule (view list), the sidebar toggle and the sidebar sections. They also cover the switches, the tabs, the inbox card and the account pill. All still, except P3-D below. Receipt:r427-probe3.log.canvas:view:*,canvas:open/rename/ctr/session:*, split/new, canvas lock,theme:*,bg:*,card:*,windows:*,settings:*,proto:later. All still, except the font rows (P2-A).Limit of this evidence: probe 3 did not record whether Enter changed anything on each trigger. A "still" on a trigger that does nothing is weaker than a "still" on one that visibly opens. Card morphs, docs previews and sheets are therefore covered by the sweep,
keyboard-instantand my earlier probes, not proved again here. I did not build a key path into docs previews or bottom sheets.3. Pointer and touch still animate: confirmed
Positive controls with the same watcher (
r427-probe.log):hasTouch,isMobile, dpr 2, reallocator.tap()): the same three all animate (sidebar toggle to 450 ms, view list clip-path to 782 ms, window pill transform to 368 ms).4. Interaction with
motion-fast-ease-out(#471,bfdcddc60)A trial merge
git merge-treeshows 6 conflicted files:wizard.ts,camera.ts,world.ts,lifecycle.ts,anchored-popover.tsandpill-morph.ts. CSS merges clean.wizard.ts,world.tsandpill-morph.tsare doc-comment collisions only. The rest are real:camera.ts: #427 deletesKEY_FLIGHTandkeyFlight()(a key jumps), while #471 retunes them to 0.12 s. #427's side must win, and #471'sKEY_FLIGHTconstant must go.lifecycle.ts(pulse): #471 shortens it to 240 ms, and #427 addsif (triggeredByKeyboard()) return. Both are needed.anchored-popover.ts: #471 usesEASE_OUTfor the reduced-motion fade, and #427 wraps it in!triggeredByKeyboard(). Both are needed.I ran the trial merge with
-X ours(so #427 wins every conflict) on dev-02 and ran #471's unit tests:motion-speed.test.tspasses 20/21,no-overshoot.test.tsandspring.test.tspass. The one failure is "no Web Animation lasts more than 300 ms or starts slowly". It names exactly the two lines where #427's side kept dev's old values:lifecycle.ts:338(360 ms) andanchored-popover.ts:209("ease"). The correct resolution above fixes both. So the conflicts are small and the gate catches the wrong resolution.A real interaction, not a conflict (P3-E below): #471's scanner reads
--t-*tokens, and #427's scaled transitions are writtencalc(var(--t-pop) * var(--ui-motion-scale, 1)).words()keeps acalc(...)as one word andms()only accepts a literal orvar(--t-…), so the duration reads as 0. Every scaled transition (the palette, the toast, the regions, ...) silently leaves the 300 ms and ease-out checks. Today's token values are all ≤ 240 ms, so nothing is wrong yet. The guard just does not guard them.Recommended order: #427 first, then #471.
KEY_FLIGHThunk, which is the smaller change.pulseand the popover fade as above. It also makesms()unwrapcalc(<time> * var(--ui-motion-scale…)), so the new scanner sees every scaled transition.5. The
Mockup:skip is justifiedAll
Mockup:rows (proto:conn:*,proto:acct:s:*,proto:sessions-scene:*,proto:scene:*, transparency) are made inapps/tracer/src/canvas/mock/*. They are test-double rows that run scripted scenes on their own timers (for example "play every state" runs one every 2.6 s), so a timer would be reported as a key response. The product rows they sit beside are swept normally. Caveat for the comment in the spec: the skip also removesMockup: account – …, which opens real account panels in scripted states. Those panels are reached by "Your account" (swept) and by the account pill (probe 3, still).6.
verify fastred only on cargo-deny: confirmed~/j370-fast2.logon dev-02 starts withc11a47562 Merge remote-tracking branch 'origin/dev'…. Every row is PASS exceptcargo-deny | FAIL (1)(line 13599) andprivileged integration | SKIP, and it ends withVERIFY_EXIT=1. The failure at line 12530 isRUSTSEC-2026-0459onlibsqlite3-sys 0.30.1(advisories FAILED, bans ok, licenses ok, sources ok).~/j370-denydev.logshows the same on plain dev (advisories FAILED,deny-dev-exit=1).git diff origin/dev...HEAD -- Cargo.lockis empty. This is not the branch's.Findings
P2-A: a palette font row animates the Settings pane's tick, and the sweep passes anyway.
Pressing Enter on any of
Font: Geist Mono / JetBrains Mono / Commit Mono / Monaspace Neonmovessvg.ui-sp-tick(button.ui-sp-row < div.ui-sp-list < div.ui-settings-pane) with a CSSopacityandtransformtransition from about 55 ms to 150–205 ms after the key. Evidence isr427-probe.log(all four rows at both sizes), andr427-probe2.logidentifies the element. Idle shows no SVG transitions.The committed sweep presses only one row of the
fontfamily, and that row passes. Whichever row it is, the guard misses the other four.markMotion/triggeredByKeyboard, as the other panes do) and drops its transition for a key.font, take the second row, or run a state-changing row. Then add the tick to the sweep or the exception list on purpose.P3-B: sweep property filter now fine, but the exception regexp can never match SVG elements.
name()prints an SVG element'sclassNameas[object SVGAnimatedString](see thesvg.[object.SVGAnimatedString]lines inr427-probe.log).NOT_PRODUCT = /…|ui-conn-g/therefore cannot match the connection indicator's<g>or<svg>children. UsegetAttribute("class")inname(). At the moment the exception passes only because nothing reaches it.P3-C: the palette-row probe types the label and presses Enter on the first result, and that is not always the row.
theme:ink's label "Ink" returnscanvas:settings:machines.new-machines.add-linkfirst (first=DIFFERENT:inr427-probe.log). The sweep does not check that the first result is the row it meant, so a family sample can silently press another row. Assertdata-actionof the first result equals the wanted action (or press the row with ArrowDown), and fail otherwise.P3-D: Enter on the "Sessions" window-action button fades the row's meta/actions (120 ms).
At 1440x900, with the cursor off the page,
span.cl-sx-metaandspan.cl-sx-actsrun an opacity transition (sessions.css:41,48,51-52,var(--t-press) ease). Focus lands in a row of the popover that was just opened, so:focus-withinswaps meta for actions. The popover itself is instant; this is the first-focus reveal of a row's actions. The sweep reaches this popover only through the palette row and the chord, which pass. The button path (Enter on the focused "Sessions" button) is the one that moves. It could use the samedata-motionattribute the rest of the branch uses. The rest of the disclosure list (probe 3) is still, apart from this.P3-E: #471's motion scanner cannot read the scaled transitions (section 4). The fix belongs in
motion-speed.test.ts(ms()unwrap) and goes with whichever branch merges second.Noted, not findings:
div.cl-summarywith a 180 ms scale-in (r427-probe.log,crumb#0 Escape). That ispointerenteron a stationary cursor, so hover, not a key response.div.tiplines inr427-probe2.log). They disappear when the cursor is moved away (probe 3).Reviewed SHA:
c11a475622. Not merged, pushed or deployed. The dev-02 worktrees and my servers are removed.J370 follow-ups to #427 (J436, comment 88843). Branch
kbd-instant-followups(from origin/devc442500c2), headc818bde6d, pushed (git ls-remoteagrees). Not merged.Red first (
2b50dea24and the commits after it are the spec;~/j370-f3red.log,~/j370-f5red.logon dev-02, the final sweep against plain origin/dev):svg.ui-sp-tick(opacity 9 → ~150 ms, transform 9 → ~205 ms). The sweep now presses every row of a family of ten or fewer (all fonts, card and window levels, backgrounds); only the themes take one row.transition opacity on span.cl-sx-metaandspan.cl-sx-acts, 11 → 144 ms (1440x900; skipped at 393, where that button is not on the header).svg.ui-sp-tickand the exception pattern can match them.span.cl-crumb-name, 624 → 700 ms).Fixes:
db2ec7452the tick (paintChoicemarks it; its transitions scale by--ui-motion-scale) and the first Sessions attempt;3c1df0c04the Sessions popover is marked before eachfocus()(a probe showed the browser updates styles insidefocus(), beforefocusin, so the first attempt's mark came too late);3776e3357the crumb name.Sweep changes: motion rule now "still seen 50 ms after the key and seen for ≥ 60 ms from its first frame" (catches a 120 ms fade); closes the scene's open popover before pressing Sessions.
Green (dev-02): at
3776e3357(~/j370-f4.log) keyboard-sweep at 1440x900 and 393x852 (shortcuts, every palette row) and keyboard-instant: 38 passed, 1 skipped, 1 failed (the Sessions case, fixed by the next commit); at3c1df0c04(~/j370-f6.log) the Sessions case passes and typecheck passes.sessions-canvas.spec.tshas 2 failures (open duration[200], a toast test) that fail identically on plain origin/devbd551e549(~/j370-f7base.log).verify quickatc818bde6d(~/j370-f8quick.log): "QUICK pre-check passed", exit=0.J451 fix-check of
kbd-instant-followups@c818bde6d(base origin/devc442500c2): APPROVE, with three P3s below. Nothing merged, pushed or deployed. Runs were on dev-02, production build, through build-slot.1. Full specs at the head (
keyboard-sweep+keyboard-instant+sessions-canvas, 1440x900 and 393x852): 61 passed, 2 failed, 1 skipped (the Sessions-button case at 393x852: the button is not on that header, the spec's own skip).keyboard-instantcases pass.sessions-canvaspair in item 5.2. Red run (head's
keyboard-sweep.spec.tscopied onto origin/devc442500c2): 5 failed, 24 passed, 1 skipped.font:geist-mono...font:source-code-pro):transition opacity/transform on svg.ui-sp-tick.transition opacity on span.cl-sx-metaandspan.cl-sx-acts, moving 11 ms to 144 ms.sessions-canvasfailures are the same pair as on the head.3. Pointer still animates (scratch spec at the head, 1440x900, not committed):
ui-sp-tickopacity moves 48 ms to 181 ms and transform 48 ms to 231 ms.cl-sx-metaandcl-sx-acts(51 ms to 182 ms).pointeroverreset works.now - lastMotion > 260gate suppresses it (the flight starts at the same time) or the rise is broken. I could not click#capsulein this scene because.cl-nouncovers it. The scratch spec therefore opened the palette by key and clicked the row by mouse. This is P3-a again, so the "rise must still play" check is unproven. I suggest a manual check on a production build, or a dedicated spec.4. "Mark before
focus()": robust enough.markMotion(root)runs immediately before each of the two code-drivenfocus()calls (the keyboard open and the arrow handler). It writesdata-motionfrom the last trusted input, so a programmatic focus (such as on reconnect) would reuse the last input's mark. That errs instant after a key and animate after a pointer. Both are acceptable under the policy documented ininput-source.ts.pointeroverreset keeps a mouse hover animated.data-motion="animate", so Tab should fadecl-sx-metaandcl-sx-acts. My probe did not reproduce it:SESSIONS-TAB found: []. The probe pre-focused row 1 byfocus()and the 400 ms wait may have settled things. So this is not confirmed. Marking in the popover'skeydownwould close it if it ever shows.5.
sessions-canvasreds: identical on dev and on the branch, and not motion regressions.:125"popover opens within 200 ms ...":expect(durations.open).toEqual([200])fails. It is a CSS-duration assertion, not a branch effect. The received value was cut off in my log, so I can't say what the duration was.:171"close toast teaches once ...":TypeError: Cannot read properties of null (reading 'hidden')inpage.evaluate. A missing element in the spec, nothing to do with motion.P3 summary:
sessions-canvasreds should be tracked separately.Evidence: dev-02
~/rv-head.log,~/rv-red.log,~/rv-ptr.log; scratch speczz-pointer.spec.ts, removed with its worktree. The red run used worktree rv-red (removed).scripts/fjis missing from the checkout, so I posted with thefjbinary.J370: merged origin/dev (themes sync, toast fix) into kbd-instant-followups. One conflict (settings-panels.ts import: dev dropped capsule-tabs, my markMotion import stays). Dev now lists 23 fonts, so the sweep always sweeps every font row (
1639cc0c9). Head1639cc0c9(pushed). dev-02 results: first run at19a383898: keyboard-instant, themes, clusters-theme-transition and the sweep's shortcut tests pass; terminal-theme.spec.ts:206 fails identically on plain origin/dev (/j370-m2base.log). Palette sweep at/j370-m2.log). verify quick: passed, exit 0 (~/j370-m2quick.log). Not merged.1639cc0c9passes at 1440x900 and 393x852 (