Key tray: keep iOS keyboard open; one-shot and sticky (double-tap) modifiers (D129) #53

Open
opened 2026-10-07 07:24:08 +00:00 by kayg · 17 comments
Owner

Owner (2026-10-07), D129: tapping key-tray keys (ctrl, option, esc, tab, arrows) must never dismiss the iOS keyboard. Single-tapping a modifier arms it one-shot; double-tapping locks it (sticky) until it is tapped again; e.g. double-tap ctrl then c c c sends ctrl-c x3. Distinct subtle armed and locked visuals, aria-pressed state, warm tooltip. Tests: touch emulation, keyboard focus retained (document.activeElement stays the terminal input), the byte sequences sent. Real iPhone check by the owner.

Owner (2026-10-07), D129: tapping key-tray keys (ctrl, option, esc, tab, arrows) must never dismiss the iOS keyboard. Single-tapping a modifier arms it one-shot; double-tapping locks it (sticky) until it is tapped again; e.g. double-tap ctrl then c c c sends ctrl-c x3. Distinct subtle armed and locked visuals, aria-pressed state, warm tooltip. Tests: touch emulation, keyboard focus retained (document.activeElement stays the terminal input), the byte sequences sent. Real iPhone check by the owner.
Author
Owner

Start: branch keytray-mods, base SHA cecc7ecd7b. Issue has no prior comments or parent relation in Forgejo view.

Start: branch keytray-mods, base SHA cecc7ecd7bb452229fcf292bebde0917c0568522. Issue has no prior comments or parent relation in Forgejo view.
Author
Owner

Finding: DECISIONS.md ends at D112 (line 486); the D129 contract is recorded in this issue body. I will follow issue #53 and the supplied owner request without editing the owner-only decision file.

Finding: DECISIONS.md ends at D112 (line 486); the D129 contract is recorded in this issue body. I will follow issue #53 and the supplied owner request without editing the owner-only decision file.
Author
Owner

Finding: the pre-change iPhone 15 browser run built the production tracer, then failed because Control has no aria-pressed state (null at keytray-modifiers.spec.ts:54). This confirms the modifier state is not exposed accessibly. The touch-focus loop reached all 13 visible buttons before a test-only strict-locator assertion; that assertion is corrected.

Finding: the pre-change iPhone 15 browser run built the production tracer, then failed because Control has no aria-pressed state (null at keytray-modifiers.spec.ts:54). This confirms the modifier state is not exposed accessibly. The touch-focus loop reached all 13 visible buttons before a test-only strict-locator assertion; that assertion is corrected.
Author
Owner

Finding: iPhone 15 Chromium emulation delivered synthesized click events 491 ms apart for sequential locator.tap calls. The keybar now records modifier pointerdown times (queued to preserve order when clicks are delayed); focused Playwright suite passes 2/2, including exact Control/Option and xterm arrow bytes. Screenshot attachments: keytray-off, keytray-armed, keytray-locked are emitted by test/keytray-modifiers.spec.ts.

Finding: iPhone 15 Chromium emulation delivered synthesized click events 491 ms apart for sequential locator.tap calls. The keybar now records modifier pointerdown times (queued to preserve order when clicks are delayed); focused Playwright suite passes 2/2, including exact Control/Option and xterm arrow bytes. Screenshot attachments: keytray-off, keytray-armed, keytray-locked are emitted by test/keytray-modifiers.spec.ts.
Author
Owner

Correction: DECISIONS.md D112 starts at line 485 and continues to the file end at line 488; D129 remains recorded in issue #53 rather than in DECISIONS.md.

Correction: DECISIONS.md D112 starts at line 485 and continues to the file end at line 488; D129 remains recorded in issue #53 rather than in DECISIONS.md.
Author
Owner

Finding: the first fast-gate run's native mouse probe failed before probing because scripts/verify-vt-native.py found no archive under target/debug/build (stderr: ValueError: max() iterable argument is empty). Cargo artifacts were directed to /home/kayg/.cache/codex-scratch/keytray-mods/target; added ignored target symlinks to that cache and will rerun the gate.

Finding: the first fast-gate run's native mouse probe failed before probing because scripts/verify-vt-native.py found no archive under target/debug/build (stderr: ValueError: max() iterable argument is empty). Cargo artifacts were directed to /home/kayg/.cache/codex-scratch/keytray-mods/target; added ignored target symlinks to that cache and will rerun the gate.
Author
Owner

Step complete: commit 9a912d7104 adds independent terminal modifier states and encodes Ctrl C0 bytes, Alt ESC prefixes, and xterm modifier-arrow sequences. Tracer typecheck/build and focused Playwright checks passed; the suite asserts exact received bytes. Full fast-gate rerun remains after the scratch-path fix.

Step complete: commit 9a912d710452298deeeebf1b2ce5b05fccbc62dc adds independent terminal modifier states and encodes Ctrl C0 bytes, Alt ESC prefixes, and xterm modifier-arrow sequences. Tracer typecheck/build and focused Playwright checks passed; the suite asserts exact received bytes. Full fast-gate rerun remains after the scratch-path fix.
Author
Owner

Step complete: c783f67 implements the core-screen modifier/focus state and calm armed/locked styles (140 ms ease-out). Tracer typecheck and production build passed; the iPhone 15 focused suite passed 2/2, including all 13 tray-button focus checks and F6 keyboard access.

Step complete: c783f67 implements the core-screen modifier/focus state and calm armed/locked styles (140 ms ease-out). Tracer typecheck and production build passed; the iPhone 15 focused suite passed 2/2, including all 13 tray-button focus checks and F6 keyboard access.
Author
Owner

Step complete: f9946b2d45 adds the opt-in byte recorder and iPhone 15 tests. Focused suite passed 2/2; screenshots for off (75,167 bytes), armed (77,713 bytes), and locked (78,429 bytes) were captured from the production build. Full Playwright suite is running on TRACER_TEST_PORT=4611; screenshots will be attached to this issue.

Step complete: f9946b2d450529e6a9508df28a443be4ebb37227 adds the opt-in byte recorder and iPhone 15 tests. Focused suite passed 2/2; screenshots for off (75,167 bytes), armed (77,713 bytes), and locked (78,429 bytes) were captured from the production build. Full Playwright suite is running on TRACER_TEST_PORT=4611; screenshots will be attached to this issue.
Author
Owner

Finding: first full Playwright run finished 33/34. The only failure is test/motion-audit.spec.ts:477: the auth setup checkbox's pointerTickMidOffset was 0 after its 50 ms sample (expected >0); this is separate from the key tray. Both new iPhone modifier tests passed. Isolating the motion test now.

Finding: first full Playwright run finished 33/34. The only failure is test/motion-audit.spec.ts:477: the auth setup checkbox's pointerTickMidOffset was 0 after its 50 ms sample (expected >0); this is separate from the key tray. Both new iPhone modifier tests passed. Isolating the motion test now.
Author
Owner

Finding: isolated motion-audit rerun also failed in unrelated auth setup behavior, at test/motion-audit.spec.ts:400: #copy-recovery did not reach data-done within 520 ms (timed out after 5 s); its failure differed from the first run's checkbox sample. The audit applies 4x CPU throttling. Key-tray tests remain green; I will rerun the full suite after the repository gate.

Finding: isolated motion-audit rerun also failed in unrelated auth setup behavior, at test/motion-audit.spec.ts:400: #copy-recovery did not reach data-done within 520 ms (timed out after 5 s); its failure differed from the first run's checkbox sample. The audit applies 4x CPU throttling. Key-tray tests remain green; I will rerun the full suite after the repository gate.
Author
Owner

Finding: cache-backed fast-gate workspace tests passed 70, failed 1, and ignored 6 in 155.80 s. The unrelated server test auth::tests::review3_tests::review3_backend_reply_has_a_deadline failed at crates/infraternal-server/src/auth/tests.rs:1505 with 'server closed websocket unexpectedly'; this branch has no Rust changes. cargo-deny and static builds are still running.

Finding: cache-backed fast-gate workspace tests passed 70, failed 1, and ignored 6 in 155.80 s. The unrelated server test auth::tests::review3_tests::review3_backend_reply_has_a_deadline failed at crates/infraternal-server/src/auth/tests.rs:1505 with 'server closed websocket unexpectedly'; this branch has no Rust changes. cargo-deny and static builds are still running.
Author
Owner

Follow-up: the isolated auth::tests::review3_tests::review3_backend_reply_has_a_deadline test passed 1/1 in 60.60 s. It logged 'failure at 60005ms; late success ignored; next Ping succeeds'; the earlier workspace failure appears load-sensitive. Starting one final fast-gate run with the warm cache.

Follow-up: the isolated auth::tests::review3_tests::review3_backend_reply_has_a_deadline test passed 1/1 in 60.60 s. It logged 'failure at 60005ms; late success ignored; next Ping succeeds'; the earlier workspace failure appears load-sensitive. Starting one final fast-gate run with the warm cache.
Author
Owner

Gate step complete at head f9946b2d45. Final cache-backed 'nix shell ... scripts/verify fast' exited 0. Verbatim summary:\n+---------------------------+--------------+\n| Rust gate | Result |\n+---------------------------+--------------+\n| fmt | PASS |\n| VT native fmt | PASS |\n| clippy | PASS |\n| test | PASS |\n| cargo-deny | PASS |\n| static builds | PASS |\n+---------------------------+--------------+\n\nTypeScript protocol gate: 7 pass, 0 fail, 34390 expect() calls; stream differential: 134 streams, 11439 schedules, zero divergences. Workspace tests: server 71 passed/6 ignored, shim 61 passed/12 ignored. Static binaries: x86_64 16,120,912 B; aarch64 13,539,528 B; PT_INTERP absent for both.

Gate step complete at head f9946b2d450529e6a9508df28a443be4ebb37227. Final cache-backed 'nix shell ... scripts/verify fast' exited 0. Verbatim summary:\n+---------------------------+--------------+\n| Rust gate | Result |\n+---------------------------+--------------+\n| fmt | PASS |\n| VT native fmt | PASS |\n| clippy | PASS |\n| test | PASS |\n| cargo-deny | PASS |\n| static builds | PASS |\n+---------------------------+--------------+\n\nTypeScript protocol gate: 7 pass, 0 fail, 34390 expect() calls; stream differential: 134 streams, 11439 schedules, zero divergences. Workspace tests: server 71 passed/6 ignored, shim 61 passed/12 ignored. Static binaries: x86_64 16,120,912 B; aarch64 13,539,528 B; PT_INTERP absent for both.
Author
Owner

Production-build screenshots from the iPhone 15 Playwright run:\n\nKey tray off\n\nKey tray armed\n\nKey tray locked

Production-build screenshots from the iPhone 15 Playwright run:\n\n![Key tray off](https://git.kayg.org/attachments/d7da7360-7be3-4b13-8b9b-8d34a8ee231e)\n\n![Key tray armed](https://git.kayg.org/attachments/072eec16-3549-45ef-bf06-436d5671a1c9)\n\n![Key tray locked](https://git.kayg.org/attachments/c3221203-08fd-4e6a-b3d1-5cc3285c07fe)
Author
Owner

Correction: these block-separated embeds display the production-build screenshots from the iPhone 15 Playwright run.

Key tray off

Key tray armed

Key tray locked

Correction: these block-separated embeds display the production-build screenshots from the iPhone 15 Playwright run. ![Key tray off](https://git.kayg.org/attachments/d7da7360-7be3-4b13-8b9b-8d34a8ee231e) ![Key tray armed](https://git.kayg.org/attachments/072eec16-3549-45ef-bf06-436d5671a1c9) ![Key tray locked](https://git.kayg.org/attachments/c3221203-08fd-4e6a-b3d1-5cc3285c07fe)
Author
Owner

Finish: head SHA f9946b2d45.

The requested fast gate exited 0:
env CARGO_TARGET_DIR=/home/kayg/.cache/codex-scratch/keytray-mods/target nix shell nixpkgs#binutils nixpkgs#file nixpkgs#gnumake nixpkgs#perl nixpkgs#zig_0_15 -c scripts/verify fast

Rust summary, verbatim:

+---------------------------+--------------+
| Rust gate                 | Result       |
+---------------------------+--------------+
| fmt                       | PASS         |
| VT native fmt             | PASS         |
| clippy                    | PASS         |
| test                      | PASS         |
| cargo-deny                | PASS         |
| static builds             | PASS         |
+---------------------------+--------------+

TypeScript protocol output, verbatim:

 7 pass
 0 fail
 34390 expect() calls
Ran 7 tests across 2 files. [2.61s]

Workspace scale results: server 71 passed/6 ignored; shim 61 passed/12 ignored. Static binaries: x86_64 16,120,912 bytes and aarch64 13,539,528 bytes; PT_INTERP absent for both.

Full Playwright command TRACER_TEST_PORT=4611 bun x playwright test ended:

  1 failed
    test/motion-audit.spec.ts:39:1 › measure deployed motion at 4x CPU and capture production screens
  33 passed (3.4m)

The sole failure was the auth setup motion audit: #copy-recovery had no data-done after 520 ms and the assertion timed out after 5 s. Both key-tray tests passed. The 500-key probe measured p99 16.20 ms overall and p99 0.20 ms from onData to encode.

The off, armed, and locked production-build screenshots are embedded in the preceding issue comment. A real iPhone check remains owner-side as specified in the issue.

Finish: head SHA f9946b2d450529e6a9508df28a443be4ebb37227. The requested fast gate exited 0: `env CARGO_TARGET_DIR=/home/kayg/.cache/codex-scratch/keytray-mods/target nix shell nixpkgs#binutils nixpkgs#file nixpkgs#gnumake nixpkgs#perl nixpkgs#zig_0_15 -c scripts/verify fast` Rust summary, verbatim: ```text +---------------------------+--------------+ | Rust gate | Result | +---------------------------+--------------+ | fmt | PASS | | VT native fmt | PASS | | clippy | PASS | | test | PASS | | cargo-deny | PASS | | static builds | PASS | +---------------------------+--------------+ ``` TypeScript protocol output, verbatim: ```text 7 pass 0 fail 34390 expect() calls Ran 7 tests across 2 files. [2.61s] ``` Workspace scale results: server 71 passed/6 ignored; shim 61 passed/12 ignored. Static binaries: x86_64 16,120,912 bytes and aarch64 13,539,528 bytes; PT_INTERP absent for both. Full Playwright command `TRACER_TEST_PORT=4611 bun x playwright test` ended: ```text 1 failed test/motion-audit.spec.ts:39:1 › measure deployed motion at 4x CPU and capture production screens 33 passed (3.4m) ``` The sole failure was the auth setup motion audit: `#copy-recovery` had no `data-done` after 520 ms and the assertion timed out after 5 s. Both key-tray tests passed. The 500-key probe measured p99 16.20 ms overall and p99 0.20 ms from onData to encode. The off, armed, and locked production-build screenshots are embedded in the preceding issue comment. A real iPhone check remains owner-side as specified in the issue.
Sign in to join this conversation.
No labels
launch-qa
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
kayg/infraternal#53
No description provided.