From 3a06135dcdb55d66b3ca62018e2351e30a257e7f Mon Sep 17 00:00:00 2001 From: Cameron Date: Thu, 9 Jul 2026 22:45:23 -0700 Subject: [PATCH] Align ACTIONS dial columns MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Pad dial names to a fixed monospace width so bracketed values share one column on the human root menu. Defense: wiki/interface/context-menu.md status dials — dial rows are two columns (name, current value in brackets). Presentation only. Co-authored-by: Cursor --- src/actions.rs | 28 +++++++++++++++++++++++++++- wiki/interface/context-menu.md | 9 +++++---- 2 files changed, 32 insertions(+), 5 deletions(-) diff --git a/src/actions.rs b/src/actions.rs index b77883a..ca9a028 100644 --- a/src/actions.rs +++ b/src/actions.rs @@ -270,6 +270,10 @@ impl DialId { DialId::Drift => "drift", } } + + /// Pad width for the dial-name column so bracketed values line up + /// (monospace ACTIONS chrome). Longest name is `research`. + pub const NAME_WIDTH: usize = 8; } /// One selectable row on the human ACTIONS menu. @@ -442,7 +446,13 @@ impl Sim { let value = self.dial_current_value(actions, dial); rows.push(HumanMenuRow::Dial { id: dial, - label: format!("{} [ {} ]", dial.name(), value), + // Two columns: left-padded dial name, then the value. + label: format!( + "{: = root + .iter() + .filter_map(|r| match r { + HumanMenuRow::Dial { label, .. } => Some(label.find('[').unwrap()), + _ => None, + }) + .collect(); + assert!( + bracket_cols.len() >= 2 && bracket_cols.iter().all(|&c| c == bracket_cols[0]), + "dial values share one column: {bracket_cols:?}" + ); + assert_eq!( + bracket_cols[0], + DialId::NAME_WIDTH + 1, + "value column starts after the padded name" + ); let job = s.human_menu(anchor, Some(DialId::Job)); assert!( diff --git a/wiki/interface/context-menu.md b/wiki/interface/context-menu.md index ffe8b1d..2b70e0f 100644 --- a/wiki/interface/context-menu.md +++ b/wiki/interface/context-menu.md @@ -112,10 +112,11 @@ noise). Cameron adopted **status dials** (2026-07-09): the root answers - **Dial rows.** Mutually exclusive standing choices render as dial rows on the root: machine mode, day-job target (with standing-policy - state), research track, drift/masking policy. Each row shows the dial - name and the **current value in brackets** — e.g. `job [ Meet · auto ]`, - `mode [ day-job ]`. Enter opens a short picker of alternatives; Esc - returns to the root. + state), research track, drift/masking policy. Each row is two + monospace columns — dial name left-padded to a fixed width, then the + **current value in brackets** — so the `[`s line up: + `mode [ day-job ]`, `job [ Meet · auto ]`. Enter opens a + short picker of alternatives; Esc returns to the root. - **Current value is status.** Do not also list the current choice as a disabled "already in this mode" / "already the active…" sibling. The bracketed value is the status. -- 2.51.2