tui: F5 thalamus screen, fix HashMap ordering, Screen enum

- Add Thalamus variant to Screen enum (F5)
- Fix HashMap iteration ordering causing flickering in F4/F5
  screens by using BTreeMap in supervisor and sorting plan_counts
- Update screen legend: F1=interact F2=conscious F3=subconscious
  F4=unconscious F5=thalamus
- Add dirty bit field to App (prep for event-driven rendering)

Co-Authored-By: Proof of Concept <poc@bcachefs.org>
This commit is contained in:
Kent Overstreet 2026-04-03 18:38:49 -04:00
parent 604f442215
commit db42bf6243
2 changed files with 10 additions and 3 deletions

View file

@ -21,7 +21,7 @@ mod subconscious_screen;
mod unconscious_screen; mod unconscious_screen;
mod thalamus_screen; mod thalamus_screen;
pub(crate) const SCREEN_LEGEND: &str = " F1=interact F2=conscious F3=subconscious F4=unconscious "; pub(crate) const SCREEN_LEGEND: &str = " F1=interact F2=conscious F3=subconscious F4=unconscious F5=thalamus ";
/// Subconscious agents — interact with conscious context /// Subconscious agents — interact with conscious context
pub(crate) const SUBCONSCIOUS_AGENTS: &[&str] = &["surface-observe", "journal", "reflect"]; pub(crate) const SUBCONSCIOUS_AGENTS: &[&str] = &["surface-observe", "journal", "reflect"];
/// Unconscious agents — background consolidation /// Unconscious agents — background consolidation
@ -380,6 +380,8 @@ pub(crate) enum Screen {
Subconscious, Subconscious,
/// F4 — memory daemon status /// F4 — memory daemon status
Unconscious, Unconscious,
/// F5 — thalamus: channels, presence, attention routing
Thalamus,
} }
/// Actions triggered by hotkeys, consumed by the main loop. /// Actions triggered by hotkeys, consumed by the main loop.
@ -577,6 +579,7 @@ impl App {
KeyCode::F(2) => { self.set_screen(Screen::Conscious); return; } KeyCode::F(2) => { self.set_screen(Screen::Conscious); return; }
KeyCode::F(3) => { self.set_screen(Screen::Subconscious); return; } KeyCode::F(3) => { self.set_screen(Screen::Subconscious); return; }
KeyCode::F(4) => { self.set_screen(Screen::Unconscious); return; } KeyCode::F(4) => { self.set_screen(Screen::Unconscious); return; }
KeyCode::F(5) => { self.set_screen(Screen::Thalamus); return; }
_ => {} _ => {}
} }
@ -677,7 +680,7 @@ impl App {
_ => {} _ => {}
} }
} }
Screen::Unconscious => { Screen::Unconscious | Screen::Thalamus => {
match key.code { match key.code {
KeyCode::PageUp => { self.debug_scroll = self.debug_scroll.saturating_sub(10); return; } KeyCode::PageUp => { self.debug_scroll = self.debug_scroll.saturating_sub(10); return; }
KeyCode::PageDown => { self.debug_scroll += 10; return; } KeyCode::PageDown => { self.debug_scroll += 10; return; }
@ -815,6 +818,7 @@ impl App {
Screen::Conscious => { self.draw_debug(frame, size); return; } Screen::Conscious => { self.draw_debug(frame, size); return; }
Screen::Subconscious => { self.draw_agents(frame, size); return; } Screen::Subconscious => { self.draw_agents(frame, size); return; }
Screen::Unconscious => { self.draw_unconscious(frame, size); return; } Screen::Unconscious => { self.draw_unconscious(frame, size); return; }
Screen::Thalamus => { self.draw_thalamus(frame, size); return; }
Screen::Interact => {} Screen::Interact => {}
} }

View file

@ -134,8 +134,11 @@ impl App {
// Plan summary // Plan summary
let plan_total: usize = gh.plan_counts.values().sum::<usize>() + 1; let plan_total: usize = gh.plan_counts.values().sum::<usize>() + 1;
let plan_summary: Vec<String> = gh.plan_counts.iter() let mut plan_items: Vec<_> = gh.plan_counts.iter()
.filter(|(_, c)| **c > 0) .filter(|(_, c)| **c > 0)
.collect();
plan_items.sort_by(|a, b| a.0.cmp(b.0));
let plan_summary: Vec<String> = plan_items.iter()
.map(|(a, c)| format!("{}{}", &a[..1], c)) .map(|(a, c)| format!("{}{}", &a[..1], c))
.collect(); .collect();
let plan_line = Line::from(vec![ let plan_line = Line::from(vec![