4runr-os 2.9.46 → 2.9.47

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -144,7 +144,7 @@ fn render_header(f: &mut Frame, area: Rect, state: &AppState) {
144
144
 
145
145
  // Line 1: Brand + version + mode + uptime - Bug 3 fix: Use "4Runr." with dot (matches brand logo)
146
146
  // Use npm package version (2.9.24) - matches package.json
147
- const PACKAGE_VERSION: &str = "2.9.46";
147
+ const PACKAGE_VERSION: &str = "2.9.47";
148
148
  let brand_line = Line::from(vec![
149
149
  Span::styled("4Runr.", Style::default().fg(BRAND_PURPLE).add_modifier(Modifier::BOLD)),
150
150
  Span::styled(" AI AGENT OS", Style::default().fg(BRAND_VIOLET)),
@@ -238,13 +238,14 @@ fn render_options_list(f: &mut Frame, area: Rect, state: &mut AppState) {
238
238
  ("Custom URL", GatewayOption::CustomUrl),
239
239
  ];
240
240
 
241
- // Find selected index
241
+ // Find selected index from canonical source of truth (selected_option)
242
242
  let selected_index = options.iter()
243
243
  .position(|(_, opt)| opt == &state.setup_portal.selected_option)
244
244
  .unwrap_or(0);
245
245
 
246
- // DEBUG: Every frame - exact state used for list (so we can match what's drawn)
247
- eprintln!("[SETUP-PORTAL] LIST selected_index={} selected_option={:?}", selected_index, state.setup_portal.selected_option);
246
+ // CRITICAL: Force ListState to match selected_option every frame.
247
+ // This prevents drift (e.g. from widget internals or multiple render paths).
248
+ state.setup_portal.list_state.select(Some(selected_index));
248
249
 
249
250
  unsafe {
250
251
  if LOG_COUNT % 10 == 1 {
@@ -274,12 +275,6 @@ fn render_options_list(f: &mut Frame, area: Rect, state: &mut AppState) {
274
275
  })
275
276
  .collect();
276
277
 
277
- // CRITICAL: Use the PERSISTED ListState from app state (not a new one each frame)
278
- // This is required for Ratatui's stateful widget to maintain selection across frames
279
- let list_state_selected = state.setup_portal.list_state.selected();
280
- eprintln!("[SETUP-PORTAL] LIST About to render: list_state.selected()={:?} selected_index={} selected_option={:?}",
281
- list_state_selected, selected_index, state.setup_portal.selected_option);
282
-
283
278
  // Use Block to properly contain and clear the area
284
279
  let block = Block::default()
285
280
  .borders(Borders::ALL)
package/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "4runr-os",
3
- "version": "2.9.46",
3
+ "version": "2.9.47",
4
4
  "type": "module",
5
- "description": "4Runr AI Agent OS - Secure terminal interface for AI agents. v2.9.46: Setup Portal navigation fix - persisted ListState so selection matches visual. v2.9.45: Debug logging. v2.9.44: Fill-background fix. ⚠️ Pre-MVP / Development Phase",
5
+ "description": "4Runr AI Agent OS - Secure terminal interface for AI agents. v2.9.47: Setup Portal - sync ListState from selected_option every frame so highlight never drifts. v2.9.46: Persisted ListState. ⚠️ Pre-MVP / Development Phase",
6
6
  "main": "dist/index.js",
7
7
  "bin": {
8
8
  "4runr": "dist/index.js",