ROOT CAUSE: 3 mismatched names in the empty-context warning path:
1. _handle_generate_send set self.show_empty_context_warning_modal = True
but render_empty_context_modal checks self.show_empty_context_modal.
The modal never opened.
2. _handle_generate_send / _handle_md_only never set
self._pending_generation_action, so the modal's 'Proceed Anyway'
button always saw None and dispatched nothing.
3. After Proceed Anyway, _pending_generation_action was never reset,
so subsequent empty-context calls would dispatch the wrong action.
FIX:
- gui_2.py:494,501: show_empty_context_warning_modal -> show_empty_context_modal
- gui_2.py:494,501: set _pending_generation_action before showing modal
- gui_2.py:5385: reset _pending_generation_action = None after dispatch
Tests: tests/test_gen_send_empty_context.py (5 cases) covers all 4 dispatch
paths (generate/md_only x proceed/skip) plus the happy path with context.
37/37 regression pass. No new ImGui scope errors (2 pre-existing unrelated).
- render_files_and_media now wraps the per-file loop in directory groups
via aggregate.group_files_by_dir + imscope.tree_node_ex (mirrors the
Context Composition visual style at gui_2.py:3114)
- New 'Add Directory' button next to 'Add Files to Inventory':
uses filedialog.askdirectory() + os.walk to bulk-import a folder tree
- Button IDs (i, add_f_{i}, rem_f_{i}) preserve global uniqueness via
file_indices map (regression-safe across the directory wrap)
- Test uses mock button=False, mock filedialog.askopenfilenames/askdirectory
to avoid opening a real Tk dialog during test run
- New module-level render_vendor_state(app) in gui_2.py
- New 'Vendor State' tab in render_operations_hub tab_bar
- Renders 5 stable metrics: provider_model, context_window, cache, quota, last_error
- Each row: Metric label | Value | State (colored ok/warn/error/info)
- Tooltips via imgui.set_tooltip on the value cell
ImGui scope linter: render_vendor_state OK. Pre-existing 2 errors at lines
2684 and 4994 unrelated to this commit.
- AppController.__init__: public vendor_quota: Dict[str,Any], last_error: Optional[Dict[str,str]], token_tracker: Dict[str,Any]
- set_vendor_quota(provider, remaining_pct, reset_at): public API for ai_client quota paths
- clear_last_error(): reset hook
- _refresh_api_metrics: read vendor_quota and error from payload, populate state
ai_client per-provider quota wire-up deferred to a future track (per-provider
signals differ; this commit establishes the state shape and read path).
ROOT CAUSE: gui_2.py:1675 re-instantiated LogRegistry() which opens the TOML
but never called .load_registry() so the table stayed empty.
FIX: in-place load_registry() on the existing instance — preserves in-memory
state (any pending update_session_metadata call) and matches the user's intent
of 'refresh from disk'.