Skip to content

ADR-0034: Aesthetic Mode Mechanism — AMBER / WHITE / GREEN (phosphor schemes)

The KN-86 primary display is monochrome amber. The color is locked (CLAUDE.md Display / Color rows). On a monochrome panel, “theme” cannot mean “palette swap” — but the mechanism the inspiration corpus argues for (a named, cyclable, persisted setting whose choice the runtime is built around) transfers anyway. On a monochrome device the variable knob is glyph treatment, scanline/ghost overlay strength, and CIPHER-LINE animation profile — not color.

Three forcing functions:

  1. Synthesis §3 item 2 is unresolved. The synthesis names “aesthetic-mode mechanism — named, cyclable, persisted in nosh-config.toml. AMBER (default) / AMBER / CIPHER roster” as a P1 promote-to-spec item, and §6 item 6 carries it as Gameplay Design + Platform Engineering sprint work. Until this ADR lands, the roster is a brief and not a spec; the picker contract is a sketch and not a contract; and the cart-readability question (can (get-aesthetic-mode) answer from cart Lisp?) is open.
  2. nosh-config.toml is already the de-facto config substrate (docs/device/hardware/build-specification.md for the ambient-glitch system; ADR-0011 / system-image release infrastructure for runtime config). Several runtime features already persist there. Aesthetic mode either joins them or grows a new persistence surface — choice forced now, because the SYS-tab picker depends on knowing where the setting lives.
  3. Two sibling ADRs (ADR-0033 reveal primitive, ADR-0035 trackpoint cart-FFI) amend ADR-0005’s Tier 1 catalog in the same sprint. Adding (get-aesthetic-mode) independently keeps each amendment surgical; the rebase belongs to PM at merge time, not to this ADR’s scope.
  • Monochrome amber is locked. This ADR does not propose a palette change. AMBER’s color values (#E6A020 on #000000) remain the CLAUDE.md canonical defaults.
  • AMBER is the v0.1-shippable default. AMBER and CIPHER are part of the roster the runtime must accept, but the synthesis is explicit that v0.1 ships AMBER only (docs/influences/synthesis.md §3 item 2 caveat per inspiration/index.md §“What should ship in v0.1” #1). This ADR locks the roster the architecture supports; the enablement of AMBER and CIPHER as user-selectable can ship behind a config-only toggle in v0.1 and surface on the SYS picker in v0.x.
  • Universal Deck State is reserved for cartridge-agnostic operator identity (handle / credits / reputation / cartridge history / phase chain / cipher seed) — see docs/software/runtime/deck-state.md. Aesthetic preference is not an operator-identity field; it is a device-configuration field. Persisting it in UDS would conflate two different concerns and force the 64-byte SRAM record to absorb a settings field every future settings PR would want to follow.
  • Spec Hygiene Rule 6. CIPHER renders on CIPHER-LINE only (except for the Null cart’s sanctioned main-grid escape). Aesthetic mode adjusts CIPHER-LINE’s animation profile; it does not relocate CIPHER glyphs to the main grid.
  • Determinism. The cipher-voice-style-guide §2.1 invariant 5 (“identical deck states + identical event streams produce identical CIPHER output”) must survive aesthetic-mode changes. The mode controls rendering, not the LFSR seed or vocabulary sampling.
  • Cart grammar cannot define new aesthetic modes. Cipher-voice-style-guide §2.2 already bounds cart contributions to vocabulary, productions, mode-weight biases, and style deltas. Aesthetic modes are a runtime concern — letting cart grammar register new ones would mean a cart could ship its own glyph treatment / overlay strength, violating the “one generator, one meta-grammar” invariant and breaking cross-cart visual continuity.

The KN-86 ships a named, cyclable, persisted aesthetic-mode mechanism with a runtime-locked three-entry roster: AMBER (default), AMBER (warmer), CIPHER (desaturated for reading). The mode is persisted in nosh-config.toml (not in Universal Deck State). The mode is readable from cart Lisp via a single new Tier 1 FFI primitive (get-aesthetic-mode) → symbol. The picker UI lands on the Bare Deck Terminal SYS tab. Cart grammar contributions cannot define new aesthetic modes.

Concrete commitments:

⚠ ROSTER REPLACED BY 2026-06-13 AMENDMENT (ADR-0036). The current canonical roster is :amber (default, #E6A020) / :white (#F0F0F0) / :green (#33F033) — three phosphor schemes on a 1024×600 native framebuffer. The :amber / :amber / :cipher table below is design history and must not be implemented as written. See the Amendment Log entry “2026-06-13 — Roster replaced: AMBER (default) / WHITE / GREEN” for the live roster, FFI return values, and migration rules.

The following table is design history (pre-ADR-0036) — retained for the record, not a live contract:

Mode symbolRoleReference imagev0.1 ship status
:amberCanonical default. #E6A020 on #000000. The factory default; the marketing identity; the inspiration corpus’s anchor mode.os-models-3.pngSelectable + default.
:amberWarmer. Same amber pixel element, more saturated red-orange shift; subjectively warmer, slightly higher contrast.os-models-1.pngSelectable in v0.1 (config-only toggle acceptable until SYS picker ships).
:cipherDesaturated for reading. Mid-luma amber, lower-saturation, calmer overlay profile. For sustained reading sessions (Null cartridge passages, long debriefs, REPL work).(no direct still — described in inspiration/index.md §“Color story and aesthetic-mode direction”)Selectable in v0.1 (config-only toggle acceptable until SYS picker ships).

The roster is runtime-locked. No fourth entry without an amendment to this ADR. The mode registry in the runtime is a fixed enum, not a plugin surface; carts and config files cannot register new symbols. (Sister ADRs for v2+ aesthetic mode additions — should there be a hypothetical :phosphor mode someday — are the path; cart grammar is not.)

2. Persistence — nosh-config.toml, not Universal Deck State

Section titled “2. Persistence — nosh-config.toml, not Universal Deck State”

The current mode persists in nosh-config.toml at the path /home/shared/nosh-config.toml (the existing ambient-glitch-config home per docs/device/hardware/build-specification.md) under a new top-level table:

[aesthetic]
mode = "amber" # one of: "amber" | "white" | "green" (per 2026-06-13 amendment / ADR-0036)

Default if the file or the key is missing: "amber" (per the 2026-06-13 amendment — was "amber"). Invalid value (typo, unknown symbol, case mismatch): the runtime falls back to "amber" and logs a one-line warning to the firmware-status row of the boot log. Reads happen at boot (cached in SystemState); writes happen on picker-confirm and on first-boot creation. Legacy persisted values migrate per the Amendment Log entry “2026-06-13 — Roster replaced”: "amber""amber", "cipher""amber" (lossy).

Why nosh-config.toml over Universal Deck State:

  • UDS is operator-identity, not device-configuration. UDS persists handle, credits, reputation, cartridge history bitfield, phase chain, lambda macros, quote slots, cipher seed (see docs/software/runtime/deck-state.md and the Bare Deck STATUS-tab layout in bare-deck-terminal.md §“FOUNDATION: UNIVERSAL DECK STATE”). The whole structure is 64 bytes, every byte accounted for. Aesthetic preference is a device-level setting that belongs alongside contrast, volume, backlight — the SYS tab’s existing fields, all of which are already persisted as settings rather than as identity. The principle: if it should survive a factory reset and follow the operator across devices, it goes in UDS; if it should be reset by a factory reset and stay with the device, it goes in nosh-config.toml. Aesthetic preference is the second kind.
  • Human-editable and shareable. Per the inspiration corpus convergence (audium.md, rs-pug.md, nfl-challenge.md), text formats trump binary blobs for settings the operator might reasonably want to grep, diff, sync, or share. nosh-config.toml already carries this character; UDS does not.
  • Settings drift over time. Future v0.x SYS-tab additions (keybinding remaps per aethertune.md, boot animation speed/once_per_session/disable per bootstra386.md, carousel idle interval per features-matrix item 33) all belong in nosh-config.toml. Locking aesthetic mode there now sets the precedent and keeps UDS narrow.
  • Mode cycle is a SYS-tab action, not a global hotkey in v0.1. The synthesis L2 doctrine (“a single key to cycle modes, rendered as the first thing the operator sees”) is honored on the SYS tab — EVAL on the aesthetic-mode row cycles :amber → :white → :green → :amber (per the 2026-06-13 amendment; was :amber → :amber → :cipher → :amber). A global hotkey (e.g., a SHIFT-chord) is deferred until the v0.1 layout has been operated for a sprint; live cycling outside SYS risks accidental triggers during cart work.
  • Picker contract is specified in bare-deck-terminal.md §“TAB 4: SYS” as the AESTHETIC section (this ADR amends that doc in the same PR). See §4 below for the row layout and interaction contract.
  • Confirm-on-cycle, not save-button. Modeled on PulseDeck / NetWatch / AetherTune cycling pattern, not on the os-models-4.png save row pattern. The OS Models picker is the visual reference for a full-editor surface (foreground/background hex entry, multi-field commit); the AESTHETIC row is a single-axis cycler, so the simpler PulseDeck cycle pattern is the right fit. Each EVAL press commits the new mode to nosh-config.toml immediately; the display redraws with the new mode’s rendering deltas applied in-place. No separate “save.”

These are the dimensions the runtime varies per mode. Concrete values where possible; bring-up parameters named where not.

⚠ INVALIDATED BY ADR-0027 (2026-06-12) — OPEN QUESTION FOR JOSH. This sub-section was written against ADR-0014’s 12×24-cell model and its F1 native-12×24 glyph table. ADR-0027 retired ADR-0014 (ratified 2026-06-07): under the 128×75 canon the cell is native 8×8 Press Start 2P, rendered 1:1 with no 12×24 cell, no 1×/2× scaling, and no font_12x24 table. The “AMBER renders scaled-and-padded vs CIPHER uses the native 12×24 cut” distinction therefore no longer exists — all three modes render the same native 8×8 glyph. The glyph-treatment axis of aesthetic mode is gone.

What remains as a viable per-mode rendering axis under 128×75: the CIPHER-LINE cadence delta (§4.2, unaffected) and the scanline / ghost overlay floor (§4.3, unaffected), and possibly an amber-hue warmth shift (a phosphor-tint delta within the locked monochrome-amber envelope) — but hue-warmth is not yet specified and is not a re-spec the architect is making unilaterally.

Open question for Josh: with glyph cell-size fixed at native 8×8, what should AMBER / AMBER / CIPHER actually control? The candidate axes are (a) CIPHER-LINE typewriter cadence + blink, (b) scanline/ghost overlay floor, and (c) an as-yet-unspecified amber-hue warmth/saturation shift. The table below is retained as design history only and must not be implemented as written. This sub-section requires Josh’s confirmation before the mode semantics are re-spec’d.

The following table is design history (pre-ADR-0027) — retained for the record, not a live contract:

Toggled between the two glyph paths sanctioned by the now-retired ADR-0014:

ModeGlyph path (pre-ADR-0027, invalidated)Source
:amberPress Start 2P 8×8 source, rendered 1× horizontal / 2× vertical with 2 px H / 4 px V padding inside the 12×24 cell (ADR-0014 §Decision item 4).v0.1 default.
:amberPress Start 2P 8×8 source, same scaled-and-padded path as AMBER.Glyph treatment unchanged from AMBER; the warm shift is delivered via the overlay profile (§4.3), not via the glyph cut.
:cipherNative 12×24 glyph table per ADR-0014 F1 (the runtime-flagged --font-12x24 path, generated by tools/gen_font_12x24.py, source kn86-emulator/src/font_12x24.c).Trades the 8×16 visible glyph + padding for a true 12×24 per-glyph cut with 2-pixel descenders for q/p/y/g/j. Reads denser and calmer at the same panel size — the right glyph treatment for sustained reading.

Implementation (pre-ADR-0027, invalidated): a new display.c function display_set_glyph_table(GlyphTable) selected between the two glyph tables. Under ADR-0027 there is a single native 8×8 glyph table and no per-mode glyph-table selection; the display_set_glyph_table plan and the KN86_FONT_12X24 flag are retired with ADR-0014.

The CIPHER-LINE typewriter render (ADR-0015 §Decision, “Deliberate” timing class) varies cadence per mode:

ModeTypewriter cadence (chars/sec)Cursor blink period (ms)Notes
:amber18 cps500 msv0.1 baseline. The cadence cipher-voice.md §6 was tuned against.
:amber22 cps400 msFaster, slightly more urgent — pairs with the warmer rendering.
:cipher14 cps700 msCalmer, slower — pairs with the sustained-reading rendering.

The cadence values above are v0.1 commitments based on the cipher-voice §6 timing class definitions. The cursor blink period values are bring-up-benchmark TBD: the values shown are the architect’s starting point but will be calibrated against the SSD1322 panel during prototype bring-up; if the calibration moves them more than ±50 ms, this ADR’s table is amended in the same PR that fixes the values.

These are the only CIPHER-LINE timing values that ride on aesthetic mode. The 4-row layout (Row 1 status / Row 2 current / Row 3 echo / Row 4 contextual), the 32-char-per-row hard cap, the echo-cycle semantics (silent ticks do not push), and the determinism invariant are all unchanged across all three modes.

The ambient CRT-glitch overlay (ADR-0023’s nOSh ambient CRT-glitch system) carries an intensity floor set by aesthetic mode. The operator’s existing Off / Low / Medium / High setting (persisted at /home/shared/nosh-config.toml) acts as a ceiling; the per-mode floor sets a lower bound the user setting cannot go below.

ModeOverlay floorEffective overlay scale
:amber (default)LowUser setting clamped from below to Low. If the user has overlay = Off, AMBER mode applies a Low overlay anyway — the warm rendering target needs the slight phosphor bleed to read correctly. (Carries the floor formerly mapped to the old :amber value; new default per ADR-0036 cascade.)
:whiteOffUser setting honored exactly (Off ≤ Low ≤ Medium ≤ High). WHITE phosphor reads cleanly without overlay assist; starting value pending on-glass tuning.
:greenOffUser setting honored exactly. GREEN phosphor (P1-style) reads cleanly without overlay assist; starting value pending on-glass tuning.

(Floor table re-spec’d 2026-06-13 per ADR-0036 cascade [Open Question 3 resolved by Josh]: roster changed from AMBER/AMBER/CIPHER → AMBER/WHITE/GREEN; the old AMBER’s Low floor migrates forward to the new AMBER default. The old :amber and :cipher floors are retired with their symbols.)

This is the runtime’s first multi-knob composition: aesthetic mode contributes a floor, user setting contributes a ceiling, accelerometer events contribute the active intensity within those bounds (ADR-0023 §“firmware-internal nOSh ambient CRT-glitch system”). The composition rule is effective = max(mode_floor, min(user_setting, accel_active)).

Pixel-level overlay rendering values (alpha mix per intensity step, scanline period in lines, ghost trail length in frames) are bring-up-benchmark TBD — the existing overlay implementation in the ambient-glitch system supplies the rendering values; this ADR adds the per-mode floor knob without redefining the overlay’s own pixel math. If the overlay implementation grows mode-aware knobs beyond the floor, this ADR is amended.

5. Cart-readability — yes, via (get-aesthetic-mode) → symbol

Section titled “5. Cart-readability — yes, via (get-aesthetic-mode) → symbol”

Cartridges can read the current aesthetic mode via a single new Tier 1 FFI primitive:

(get-aesthetic-mode) → :amber | :white | :green ; per 2026-06-13 amendment (was :amber | :amber | :cipher)

The primitive is read-only. Carts cannot change the mode (only the operator via the SYS picker, or the device boot path from nosh-config.toml). The primitive is cheap (one SystemState struct field read; no syscall, no file I/O). It returns one of the three roster symbols; the runtime guarantees no other symbol can be returned (default fallback on invalid config is :amber, per §2 as amended).

Why read-only and cart-readable: Carts that compose visuals against the deck’s aesthetic (a logo cart that wants thicker strokes in CIPHER mode, a stat-sheet cart that wants tighter glyph spacing in CIPHER mode, a cart that wants to bias its own CIPHER bias-weights against the active rendering profile) can theme to operator preference without forcing the operator to set anything per-cart. This is the same justification PulseDeck / NetWatch / AetherTune carry for exposing their theme as queryable state. The primitive is cheap enough that there’s no architectural cost to making it always-available rather than gating it.

What carts can do with it: read it during cart-init or during a redraw; branch on the symbol to pick a sprite variant, a stroke width, a spacing constant, or a bias weight. What they cannot do: write it (no set-aesthetic-mode primitive in any tier), register a callback for changes (mode changes during a cart session are rare; carts re-read on next redraw), or define new modes (cipher-voice-style-guide §3 merge rule).

This adds one row to ADR-0005’s Tier 1 catalog (Deck State Access subsection), bringing the primitive count from 57 → 58. ADR-0005 is amended in the same PR.

6. Cart grammar cannot define new aesthetic modes

Section titled “6. Cart grammar cannot define new aesthetic modes”

The cipher-voice-style-guide §3 (vocabulary rules) is amended to forbid cart grammar from contributing aesthetic-mode definitions. Carts may bias the existing CIPHER style parameters (terseness / certainty / temporal-blur per beat, within the ±64 clamp in §2.2), but they cannot:

  • Register a new aesthetic-mode symbol.
  • Override the rendering-delta values of an existing mode.
  • Conditionally activate a mode (no cart-driven mode swap; only the operator can change modes via the SYS picker).

The merge-gate lint tool (§9.3 of the style guide) gains a new check (Check 17 in the next implementation pass): rejects any cart grammar block that references aesthetic-mode symbols outside the read-only (get-aesthetic-mode) primitive. This keeps the runtime as the single authority on aesthetic mode and prevents cross-cart drift in glyph treatment / overlay strength.


⚠ ROSTER REPLACED BY 2026-06-13 AMENDMENT (ADR-0036). §Consequences below references the original :amber / :amber / :cipher roster. The live roster is :amber / :white / :green with :amber as the default fallback and enum AestheticMode { MODE_AMBER, MODE_WHITE, MODE_GREEN }. See the Amendment Log entry “2026-06-13 — Roster replaced: AMBER (default) / WHITE / GREEN” for the authoritative values; the immediate-effects list below is design history.

  • nosh-config.toml gains an [aesthetic] table. Runtime reads it at boot, falls back to :amber on missing-or-invalid (per 2026-06-13 amendment; was :amber).
  • SystemState gains an aesthetic_mode field (enum AestheticMode { MODE_AMBER, MODE_WHITE, MODE_GREEN } per 2026-06-13 amendment; original draft was MODE_AMBER, MODE_AMBER, MODE_CIPHER). (The derived glyph_table enum originally planned here is invalidated by ADR-0027 — no per-mode glyph table exists under 128×75 native 8×8; see §4.1 flag.)
  • Bare Deck Terminal SYS tab gains an AESTHETIC section with a single-row cycler (see bare-deck-terminal.md amendment in this PR).
  • CIPHER-LINE driver gains a mode-aware cadence table (chars/sec + cursor blink period). The §4.2 values are wired as constants for v0.1; bring-up may calibrate.
  • ADR-0023’s overlay system gains a mode-aware floor in the user-setting compose function. Default is Off floor for AMBER and CIPHER, Low floor for AMBER.
  • ADR-0005 Tier 1 catalog gains one row for (get-aesthetic-mode). Primitive count 57 → 58.
  • Cipher-voice-style-guide §3 gains a merge rule forbidding cart grammar from defining aesthetic modes. The lint tool gains Check 17 in the next implementation pass.
  • Global mode-cycle hotkey — deferred. SYS-tab picker is the v0.1 surface.
  • Mode-change live preview from outside the SYS tab — out of scope. Mode changes happen on SYS-tab EVAL; the screen redraws with the new mode immediately, but there is no “hover to preview” UX.
  • Per-cart mode overrides — explicitly forbidden (§6). Carts read mode; they do not set it.
  • Additional roster entries — none planned. A v2 mode (e.g., a :phosphor green-CRT mode) would require a sister ADR amending §1’s locked roster and adding a column to §4’s rendering-delta tables.
  • Animated transitions between modes — out of scope. v0.1 is a hard cut. If a fade or wipe is desired, it lands as a separate spec.
  • REPL mode introspection — Tier 3 read-only primitives (REPL only) inherit from Tier 1; (get-aesthetic-mode) is available in the REPL by virtue of being Tier 1. No separate REPL surface needed.
  • nosh-config.toml schema versioning — out of scope for this ADR. The [aesthetic] table is additive; older runtimes that don’t know the table will ignore it. When the schema grows enough to need a version, that’s a separate spec.
  • Bring-up may move the §4.2 CIPHER-LINE cadence values. The chars/sec and blink-period values are the architect’s starting point. If the calibration on the actual SSD1322 panel moves them more than ±50 ms (blink) or ±2 cps (cadence), this ADR’s table is amended in the same PR that fixes the values. The risk is small (the values are conservative) but the trigger condition is named.
  • (get-aesthetic-mode) invites cart authors to over-theme. A cart that branches every render on aesthetic mode is doing too much. The expected use is a single-axis bias at cart-init; the lint tool cannot detect “overuse” but PR review can flag it. Mitigation: the cart-authoring docs (screen-design-rules.md, ui-patterns.md) should add a note in a follow-on pass: “aesthetic mode is read at init or during redraw, not on every cell.”
  • :cipher mode glyph treatment depends on the F1 native 12×24 table. INVALIDATED BY ADR-0027 (see §4.1 flag + Amendment Log). Under the 128×75 canon there is no 12×24 table and no per-mode glyph path; :cipher no longer derives any distinction from a glyph cut. The original risk (F1 regression dropping CIPHER back to AMBER glyph treatment) is moot. CIPHER remains distinguishable from AMBER only via the CIPHER-LINE cadence (§4.2) and overlay-floor (§4.3) knobs — and the still-open hue-warmth question pending Josh’s confirmation. Original risk text preserved for design history: “ADR-0014 F1 is shipped (the runtime flag is operative); the table itself exists at kn86-emulator/src/font_12x24.c. If F1 regresses, :cipher mode falls back to the AMBER glyph treatment + a one-line warning.”
  • AMBER’s Low overlay floor over a user-set Off may surprise operators. The user setting is a ceiling but AMBER raises the floor; if the user has set overlay = Off explicitly and switches to AMBER, the overlay turns on. This is documented behavior (§4.3 explicit) and is the design intent (warm mode needs the bleed), but warrants a one-line note in the SYS-tab picker UI (“AMBER mode applies a Low overlay regardless of user setting”).

This ADR’s PR carries the following doc updates as a hard requirement (per CLAUDE.md Spec Hygiene Rule 3):

  • docs/adr/ADR-0034-aesthetic-mode-mechanism.md — this file (new).
  • docs/adr/README.md — add ADR-0034 row to the index (newest-first; this ADR sits above ADR-0032).
  • docs/adr/ADR-0005-ffi-surface.md — Tier 1 “Deck State Access” subsection gains one row for (get-aesthetic-mode). Header line gains an **Amends:** clause for this ADR; primitive-count caption rises 57 → 58 where referenced. (Surgical; single row insertion.)
  • docs/software/runtime/bare-deck-terminal.md — SYS tab section gains an AESTHETIC subsection (single-row cycler) per §3 / §4 of this ADR. The §“GLOBAL KEY BEHAVIOR (BARE DECK)” key table is not changed (EVAL already does context-dependent confirm).
  • docs/software/runtime/cipher-voice-style-guide.md — §3 “Vocabulary rules” gains a new §3.5 “Aesthetic-mode immutability” forbidding cart grammar from defining new aesthetic modes; §9.3 merge-gate check table notes Check 17 as a deferred implementation item for the lint tool.
  • Spec Hygiene Rule 3 grep sweeprg -i "aesthetic|amber|amber" docs/ is clean of stale or contradicting aesthetic-mode claims. (AMBER appears in the display Color row spec and in marketing copy referring to the device’s visual identity; those are correct uses unrelated to the mode mechanism and remain unchanged.)

Future implementation items tracked outside this ADR:

  • kn86-emulator/src/types.h adds enum AestheticMode and the aesthetic_mode SystemState field.
  • kn86-emulator/src/display.c adds display_set_glyph_table() and the mode-aware glyph-table selection. Invalidated by ADR-0027 — no per-mode glyph-table selection under 128×75 native 8×8 (see §4.1 flag). This item is dropped pending the §4.1 open-question resolution.
  • kn86-emulator/src/oled.c adds the mode-aware cadence table for the CIPHER-LINE typewriter render.
  • kn86-emulator/src/nosh.c adds the (get-aesthetic-mode) Lisp binding (per ADR-0005 Tier 1 amendment).
  • tools/cipher-grammar-lint/ gains Check 17 (cart grammar may not reference aesthetic-mode symbols).
  • Notion task B2 (this work) → Review on PR open.

2026-06-12 — Reconciled to the 128×75 canon; §4.1 glyph-treatment delta INVALIDATED (ADR-0027)

Section titled “2026-06-12 — Reconciled to the 128×75 canon; §4.1 glyph-treatment delta INVALIDATED (ADR-0027)”

What changed. This ADR was drafted against ADR-0014’s display model (12×24 logical cell, F1 native-12×24 glyph table). ADR-0027 was ratified 2026-06-07 (the same day this ADR was accepted) and retired ADR-0014: the canonical grid is now 128 columns × 75 rows with native 8×8 Press Start 2P cells rendered 1:1 — no 12×24 cell, no 1×/2× scaling, no font_12x24 table.

Coordinate reconciliation (safe, mechanical): this ADR carries no main-grid row/column coordinates in its decision surface (the picker lives on the Bare Deck SYS tab, addressed by that doc’s own layout), so there were no Row 24 / rows 1–23 / 0–79 numeric refs to patch here. The display-model references that were present are reconciled: the §“Related” ADR-0014 link is annotated as superseded by ADR-0027.

Semantic invalidation — §4.1 glyph treatment (FLAGGED, NOT re-spec’d): the §4.1 per-mode glyph-treatment delta tied AMBER/AMBER to the scaled-and-padded 8×8-in-12×24 path and CIPHER to the native 12×24 cut (ADR-0014 F1). Under ADR-0027 that entire axis is gone — all three modes render the same native 8×8 glyph; there is no second glyph table to toggle. §4.1 is now marked INVALIDATED in place, the table is retained as design history only, and the display_set_glyph_table() / glyph_table enum implementation items are dropped. The CIPHER-LINE cadence axis (§4.2) and the scanline/ghost overlay-floor axis (§4.3) are unaffected and remain live.

Open question raised for Josh (NOT resolved here): with glyph cell-size fixed at native 8×8, what should AMBER / AMBER / CIPHER control? Candidate axes: (a) CIPHER-LINE typewriter cadence + blink (§4.2, already live); (b) scanline/ghost overlay floor (§4.3, already live); (c) an as-yet-unspecified amber-hue warmth / saturation shift within the locked monochrome-amber envelope. Axis (c) is a candidate only — it is not specified and the architect is not re-spec’ing the mode semantics unilaterally. The roster (§1), persistence (§2), SYS-tab picker (§3), cart-readability primitive (§5), and cart-grammar immutability (§6) are all unaffected by this and stand as written. Josh’s confirmation is required before §4.1 mode semantics are re-spec’d.

Implementation note. Emulator code reconciles to 128×75 at the nOSh re-flow (tracked deviation, per CLAUDE.md Spec Hygiene); the per-mode glyph-table work is dropped at that re-flow rather than reconciled.

Authority trail. ADR-0027 §“Decision” item 3 (128×75 grid), §“Context” + §“Constraints” (native 8×8 Press Start 2P, no 12×24 cell, ADR-0014 retired); CLAUDE.md Canonical Hardware Specification (updated 2026-06-07).


2026-06-13 — Roster replaced: AMBER (default) / WHITE / GREEN; §4.1 open question CLOSED (ADR-0036)

Section titled “2026-06-13 — Roster replaced: AMBER (default) / WHITE / GREEN; §4.1 open question CLOSED (ADR-0036)”

What changed. ADR-0036 (KN-86 native framebuffer renderer, 2026-06-13) supersedes ADR-0027’s display layer and locks integer-scaled rendering at arbitrary phosphor colors as the canonical display mechanism. On-glass against the deckline prototype 2026-06-13, Josh selected AMBER #E6A020 as the canonical default foreground (the prior #E6A020 read too yellow on the Elecrow panel) and WHITE #F0F0F0 + GREEN #33F033 as the two selectable phosphor alternates. The aesthetic-mode roster is replaced accordingly:

Was (drafted 2026-06-07)Now (per ADR-0036)
AMBER (default)AMBER (default)
AMBERWHITE (on black; P4-style)
CIPHER (desaturated-for-reading)GREEN (on black; P1-style)

§4.1 open question — CLOSED. The 2026-06-12 amendment flagged the AMBER/AMBER/CIPHER glyph-treatment delta as invalidated by ADR-0027 (native 8×8 left no glyph-cut axis to toggle) and listed three candidate axes for what aesthetic mode should control under 128×75 — including “amber-hue warmth / saturation shift” as candidate (c). The on-glass session of 2026-06-13 resolved the question: aesthetic modes control foreground phosphor color, which is candidate (c) generalized from “warmth shift within amber” to “selectable phosphor scheme.” The CIPHER-LINE cadence axis (§4.2) and the scanline/ghost overlay-floor axis (§4.3) remain live and unaffected. §4.1 is now a phosphor-color axis (not a glyph-treatment axis); the table semantics in §4.1 are re-pointed accordingly.

FFI return values. (get-aesthetic-mode) returns one of :amber / :white / :green. The previous values :amber / :amber / :cipher are retired — there are no carts that depend on the old symbols (the primitive shipped only with this ADR’s reveal-era amendment and has not been used by carts yet, per the cart catalog). ADR-0005’s Tier 1 catalog gets an Amendment Log entry per ADR-0036’s cascade noting the return-value rename.

Persistence. nosh-config.toml [aesthetic].mode continues to be the persistence target (§2 unchanged); the accepted string values are "amber" / "white" / "green". Missing / invalid → default "amber". The migration from any legacy "amber" / "cipher" values is: "amber""amber", "cipher""amber" (lossy; CIPHER’s desaturated-for-reading semantic is not preserved — the operator can re-select WHITE or GREEN if they want the phosphor change CIPHER was approximating).

Picker UI. The SYS-tab picker contract (§3) is preserved; the cycle list updates from AMBER → AMBER → CIPHER → AMBER to AMBER → WHITE → GREEN → AMBER. The picker label updates accordingly. The TERM-key cycle, the persistence-on-change behavior, and the live re-render semantics are all unchanged.

Cart-readability. (get-aesthetic-mode) remains Tier 1, cart-callable, cheap (single SystemState field read). Carts can read the active phosphor to bias rendering (e.g. a sprite that has a “lighter strokes for WHITE” variant), but cannot mutate.

Provenance. Decided 2026-06-13 on-glass against the deckline prototype. Test utility at /home/kn86/fb_restest.py; python3 ~/fb_restest.py colors renders the four-way comparison (AMBER / WHITE / GREEN / amber). The WHITE and GREEN exact hexes (#F0F0F0 and #33F033) are starting values pending further on-glass tuning; AMBER #E6A020 is locked.

Authority trail. ADR-0036 §“Decision” item 7 (phosphor color is selectable) + §“Consequences” companion amendments + §“Validation reference” (on-glass session 2026-06-13). CLAUDE.md Canonical Hardware Specification Color row update lands in the same cascade.


End of ADR-0034.