Finding
The kernel screen layer repeatedly redefines the same small UI primitives: keypad-to-character mappings, “keep selected row visible” scroll arithmetic, fixed-capacity ASCII buffers, and compact lap-time formatting. These are not separate screen policies; they are local copies with screen-specific names and, in one case, a canonical helper already exists but is not used.
This issue is an umbrella for the lower-severity intra-kernel UI class. It deliberately does not absorb the broader kernel↔Eidolon convergence tracked by #545; where an Eidolon copy exists, #545 remains the owner of that cross-boundary migration.
Verified against origin/main b2c706b0dd6d63c895b4adc6aa4ecccaf9d9dfab.
Evidence
Numeric-key mapping
crates/thumos/src/screen_dialer.rs:58-74 maps Num0..Num9, Star, and Hash to characters.
crates/thumos/src/screen_contacts.rs:638-653 repeats the same match as key_to_digit_char.
crates/thumos/src/screen_messages.rs:850-867 repeats the numeric/Hash portion and intentionally excludes Star because that screen reserves it for transport selection.
- Additional first-boot/auth input paths carry the same digit mapping with a
u8 output shape. The difference is caller policy/output type, not a reason for every screen to own the key enumeration.
Scroll visibility
crates/thumos/src/screen_privacy.rs:531-538, screen_search.rs:275-282, and screen_settings.rs:119-125 each implement the same formula:
if cursor < scroll_offset {
scroll_offset = cursor;
} else if cursor >= scroll_offset + visible_rows {
scroll_offset = cursor + 1 - visible_rows;
}
- Calendar and threat/list screens contain the same calculation with a differently named row-count constant.
Fixed ASCII formatting buffers
crates/thumos/src/screen_privacy.rs:201-230 defines SizeBuf { data: [u8; 16], len } with new, bounded push, push_str, and as_str.
- The same file defines a second
RetentionBuf at screen_privacy.rs:305-335, differing mainly in capacity.
crates/thumos/src/screen_home.rs:288-317 defines FormatBuf with the same representation and bounded-push behavior.
screen_settings.rs carries another small fixed buffer for IP/signal formatting. These are a const-generic capacity parameter away from one implementation.
Lap-time formatting
crates/thumos/src/heorte_timer.rs:273-291 already exposes pub(crate) fn format_lap_ms(ms) -> [u8; 9] for MM:SS.mmm.
crates/thumos/src/screen_alarm.rs:594-612 repeats the function byte-for-byte as private format_lap_compact instead of calling it.
No open issue owns these intra-kernel helpers. Closed #99 concerned a different UI duplication class (scaled character rendering), and #545 owns capability-layer convergence rather than these screen-local primitives.
Why this matters
Each copy is small, but the screen layer is exactly where behavioral polish accumulates one local fix at a time. A new key variant, safer scroll arithmetic, UTF-8/error policy, formatting overflow rule, or accessibility behavior must currently be discovered and changed across multiple screens.
The current differences are already becoming implicit policy: one mapping excludes Star for a legitimate caller reason, while the rest are exact; buffer conversion failures return "", "?", or "???" depending on which copy a screen happened to use. Those decisions should be explicit at the call site, not accidental properties of cloned structs.
Desired correction
Create a small shared screen-support surface, using narrow helpers rather than a new UI framework:
- one
Key → digit/symbol conversion, with callers filtering reserved symbols explicitly;
- one
keep_selected_visible(selected, offset, visible_rows) helper using checked/saturating arithmetic appropriate to the indices;
- one const-generic fixed-capacity ASCII buffer (or an existing no-allocation formatter) with one overflow/UTF-8 contract; and
- direct reuse of
heorte_timer::format_lap_ms from the alarm screen, or relocation to a neutral formatting module if ownership requires it.
Done when:
Num0..Num9 are enumerated in one kernel helper rather than screen-by-screen;
- every list screen uses one tested scroll-visibility primitive while retaining its own row count;
- one fixed-buffer type replaces the screen-local
SizeBuf/RetentionBuf/FormatBuf/SmallBuf family;
- alarm lap rendering delegates to the existing formatter and the duplicate disappears;
- caller-specific behavior such as Messages reserving
Star remains explicit and tested; and
- a source check or shared test table makes adding another copy visible.
Finding
The kernel screen layer repeatedly redefines the same small UI primitives: keypad-to-character mappings, “keep selected row visible” scroll arithmetic, fixed-capacity ASCII buffers, and compact lap-time formatting. These are not separate screen policies; they are local copies with screen-specific names and, in one case, a canonical helper already exists but is not used.
This issue is an umbrella for the lower-severity intra-kernel UI class. It deliberately does not absorb the broader kernel↔Eidolon convergence tracked by #545; where an Eidolon copy exists, #545 remains the owner of that cross-boundary migration.
Verified against
origin/mainb2c706b0dd6d63c895b4adc6aa4ecccaf9d9dfab.Evidence
Numeric-key mapping
crates/thumos/src/screen_dialer.rs:58-74mapsNum0..Num9,Star, andHashto characters.crates/thumos/src/screen_contacts.rs:638-653repeats the same match askey_to_digit_char.crates/thumos/src/screen_messages.rs:850-867repeats the numeric/Hash portion and intentionally excludesStarbecause that screen reserves it for transport selection.u8output shape. The difference is caller policy/output type, not a reason for every screen to own the key enumeration.Scroll visibility
crates/thumos/src/screen_privacy.rs:531-538,screen_search.rs:275-282, andscreen_settings.rs:119-125each implement the same formula:Fixed ASCII formatting buffers
crates/thumos/src/screen_privacy.rs:201-230definesSizeBuf { data: [u8; 16], len }withnew, boundedpush,push_str, andas_str.RetentionBufatscreen_privacy.rs:305-335, differing mainly in capacity.crates/thumos/src/screen_home.rs:288-317definesFormatBufwith the same representation and bounded-push behavior.screen_settings.rscarries another small fixed buffer for IP/signal formatting. These are a const-generic capacity parameter away from one implementation.Lap-time formatting
crates/thumos/src/heorte_timer.rs:273-291already exposespub(crate) fn format_lap_ms(ms) -> [u8; 9]forMM:SS.mmm.crates/thumos/src/screen_alarm.rs:594-612repeats the function byte-for-byte as privateformat_lap_compactinstead of calling it.No open issue owns these intra-kernel helpers. Closed #99 concerned a different UI duplication class (scaled character rendering), and #545 owns capability-layer convergence rather than these screen-local primitives.
Why this matters
Each copy is small, but the screen layer is exactly where behavioral polish accumulates one local fix at a time. A new key variant, safer scroll arithmetic, UTF-8/error policy, formatting overflow rule, or accessibility behavior must currently be discovered and changed across multiple screens.
The current differences are already becoming implicit policy: one mapping excludes
Starfor a legitimate caller reason, while the rest are exact; buffer conversion failures return"","?", or"???"depending on which copy a screen happened to use. Those decisions should be explicit at the call site, not accidental properties of cloned structs.Desired correction
Create a small shared screen-support surface, using narrow helpers rather than a new UI framework:
Key→ digit/symbol conversion, with callers filtering reserved symbols explicitly;keep_selected_visible(selected, offset, visible_rows)helper using checked/saturating arithmetic appropriate to the indices;heorte_timer::format_lap_msfrom the alarm screen, or relocation to a neutral formatting module if ownership requires it.Done when:
Num0..Num9are enumerated in one kernel helper rather than screen-by-screen;SizeBuf/RetentionBuf/FormatBuf/SmallBuffamily;Starremains explicit and tested; and