Skip to content

ADR-0062: Three-layer keyboard model — navigation on L1, an intact QWERTY on L2

Notion task: GWP-762

The text-entry survey (docs/plans/2026-07-29-text-entry-surface-survey.md) established that no first-party program can accept letters on the physical deck: the character path exists in the emulator, and the only source of letters on the hardware is the ADR-0016 §6 multi-tap machine, reachable from Lisp under OOBE-specific names. Josh selected a QWERTY layer as part of the answer.

Adding one exposed a defect in the committed layout. There is no case modifier anywhere on the board. LT1 is named LSHIFT and is bound MO(L1) (ADR-0031 §3.1 per-key table), a momentary layer switch whose layer carries punctuation. Nothing in L0, L1, or L2 produces an uppercase letter. The gap stayed invisible because no committed layer carried letters: case in literal entry comes from nokia.c’s NokiaCaseMode through the / key (ADR-0022 §7, carried into ADR-0031 §3.3), which lives in the runtime. Moving letters into firmware leaves that mechanism behind.

Two further constraints surfaced with it. ADR-0044 §1 binds L0, L1 (hold LT1), and L2 (the LSHIFT+TERM tri-layer), so no activation was free for a fourth layer. And the ADR-0044 §2 punctuation manifest sits on the right half of the digit base, so no punctuation is reachable from inside a letter layer.

  1. QWERTY is an alternate layer. Never the base, never the default, never the printed primary. The function-block legends stay on the front of the board.
  2. The Ferris Sweep shape does not change.
  3. QWERTY stays real QWERTY. No letter is moved out of its position.
  4. Multi-tap survives. The digits stay on the base, so the ADR-0016 §6 digit-to-letter binding is untouched.
  5. Three layers, printed on custom keycaps: the base large and centred, the second layer in one top corner, the third in the other.
  6. Keep it simple. The deck is a gaming device, and a layer need not be full.

The T-34 layout runs on the same 34-key Ferris. Its lesson is a counting argument: a real QWERTY consumes all 30 main keys, so every layer key and modifier has to live on the four thumbs. Nothing on the letter layer can be anything but a letter, which is what satisfies rule 3.

The consequence is that rule 1 costs nothing. The base layer needs no rearrangement and no verb has to be dropped. The left half already holds thirteen verbs in fifteen slots; the right half already holds the digits and the five punctuation primaries.

Dropping verbs was considered and rejected on cost. Each candidate is referenced across the module specs in lisp-paradigm.md and the per-module bibles: INFO and QUOTE in twenty specs each, APPLY in eighteen, LINK in sixteen, NIL in fourteen, ATOM in thirteen.

A three-layer model in which the base is untouched, the second layer gains navigation beside the punctuation it already carried, and the third layer is an unmodified QWERTY reached from the second.

LayerPrintedReached byLeft halfRight half
L0 BASEcentre, largedefaultthe thirteen verbs, unchangeddigits 1-9, / ; - . ,, ENT
L1 NAV + SYMone top cornerhold LT1ESC TAB, arrows, HOME END PGUP PGDN DEL, abcthe ADR-0044 §2 symbol manifest, unchanged
L2 QWERTYthe other top cornerpress abc on L1qwert asdfg zxcvbyuiop hjkl; nm,./

The unprinted long-tail symbol layer (ADR-0044 §4, LSHIFT+TERM tri-layer) is unchanged and is not one of the three printed layers.

Base thumbs are unchanged from ADR-0031 §3.1: EVAL · LAYER · 0 · TERM. The one change is a name: LT1 stops being called LSHIFT, which it never did, and is called LAYER, which is what MO(L1) does.

Inside L2 the same four thumbs carry:

ThumbIn L2
LT0SHIFT, tapped once: the next letter is uppercase, then it clears
LT1NUM, held: a number row across both halves (§3)
RT0SPACE
RT1abc: leaves L2

No thumb tap on the base is sacrificed, so ADR-0032 §4 is preserved.

L2 carries its own digits rather than borrowing the base map, because the base keeps 0 on the right inner thumb and that thumb is SPACE while letters are live. Held from LT1:

Pinky Ring Middle Index InnerIdx InnerIdx Index Middle Ring Pinky
Top 1 2 3 4 5 6 7 8 9 0
Home ! @ # $ % _ - : ' "
Bottom = + * & ^ ( ) [ ] ?
Left half L00 L01 L02 L03 L04 / L10.. / L20.. (position order matches ADR-0031 §3.1)
Right half R04 R03 R02 R01 R00 / R14.. / R24..

Read left to right the left half runs pinky to inner index and the right half inner index to pinky, which is the ADR-0031 §3.1 diagram convention. 1 is therefore the left pinky and 0 the right pinky, so the row reads as an ordinary number row across the board.

abc is live on L1 only. Every main key in L2 is a letter, so a toggle placed on one would take a letter’s position, which is the rule-3 violation this model exists to avoid. Leaving L2 is therefore a thumb (RT1) rather than the key that entered it.

Every activation is scoped to the layers it appears on. A held layer key releases on release regardless of which layer it selected.

Three legends per cap: the base centred and large, L1 in one top corner, L2 in the other. Two positions (L20, L21) are blank on the base and carry only corner legends. v0.1 ships blank caps (ADR-0018), so this governs the eventual print manifest rather than the current build.

The function block and its legends (ADR-0022 §1, audited by ADR-0044 §5), the digit cluster and the ADR-0016 §6 digit-to-letter binding, the ADR-0044 §2 SHIFT manifest, the ADR-0044 §4 tri-layer, the four locked thumb taps, and both v2 spare positions. Zero new physical keys.

Option A: QWERTY on the base, the function block on a layer (rejected)

Section titled “Option A: QWERTY on the base, the function block on a layer (rejected)”

Measured cheapest on every target (a capital in six presses against seven) and cost no keys and no spares, because letters on the base need no mode.

Rejected on rule 1. The function-block legends are the deck’s face. It also removes the digit cluster’s base home, which retires the ADR-0016 §6 binding and leaves multi-tap nothing to run on.

Option B: two co-equal bases, DECK and TYPE, toggled (rejected)

Section titled “Option B: two co-equal bases, DECK and TYPE, toggled (rejected)”

Rejected on rule 1 for the same reason, and it carried six layers against three.

Option C: a latched guest layer spending both v2 spares (rejected)

Section titled “Option C: a latched guest layer spending both v2 spares (rejected)”

Put the toggle and a dedicated Shift on L20 and L21. Rejected on rule 3: those positions are z and x in QWERTY, so a letter had to move. Superseded by the accepted model, which costs one fewer key and moves no letter.

Option D: a momentary layer held on a thumb (rejected)

Section titled “Option D: a momentary layer held on a thumb (rejected)”

No latched state to be wrong about, but the right thumb is pinned for every letter and a capital needs a second held key. Costs more presses than the accepted model for the same result.

Option E: home-row modifiers for Shift (rejected)

Section titled “Option E: home-row modifiers for Shift (rejected)”

The standard answer on a 34-key board and free in keys. Rejected because it reintroduces a tap-hold timing term, in firmware, where ctest cannot reach it. That is the dependency the dwell-commit multi-tap variant was rejected for, relocated somewhere harder to test.

  • Reaching QWERTY is two steps (hold LAYER, press abc) rather than one. That is the price of spending no base key, and it suits a layer entered per field rather than per word.
  • A toggled layer is a state the hands cannot feel. Pressing CAR with letters live types f. Row 0 has to carry the indicator, which makes it a ui/ component requirement rather than a keymap one.
  • Navigation is new territory. The L1 left half was passthrough; binding it costs nothing that existed and adds a surface with no precedent on this deck.
  • Two entry paths coexist. Multi-tap runs in the runtime and needs no firmware, so it is the path that works before the keymap retarget lands. Whether it stays afterwards is deferred.

Every first-party program gains a real path to letters on hardware. Short strings (hostnames, paths, filter text) stop being the deck’s worst interaction. The SHIFT keycap finally describes something.

Three printed layers is more legend than two. The Row 0 layer indicator becomes a shipping requirement rather than a nicety.

The L1 left half is bound to navigation on the argument that a deck needs cursor movement. A gaming device may want game verbs there instead; the binding is cheap to change because nothing was there before.

Documentation Updates (per Spec Hygiene Rule 3)

Section titled “Documentation Updates (per Spec Hygiene Rule 3)”
ItemOwnerBlocking
QMK keymap retarget: the Sweep LAYOUT_split_3x5_2 map, three layers, the abc scope, the one-shot ShiftPlatform Engineeringeverything below
Row 0 layer indicator componentUIshipping the toggle honestly
Runtime: accept letters from the keyboard on the device without the spurious-character path (survey §2)C Engineerletters on hardware
  1. What the L1 left half should carry. Navigation is the placeholder; game verbs are the alternative.
  2. Whether multi-tap stays once the letter layer ships.
  3. Whether the two v2 spares get used at all now that neither the toggle nor Shift needs one.