perf(entropy): Fix nested imports in hot paths

Hoisted imports from inside frequently-called functions to module level:

app_controller.py:
- Added traceback and inspect at module level
- Removed 3 nested traceback imports from exception handlers

gui_2.py:
- Added traceback at module level
- Removed nested traceback import from _gui_func exception handler
- Kept uvicorn lazy-loaded (only for --headless mode)

multi_agent_conductor.py:
- Removed unused 'import sys' from run()
- Removed redundant nested imports (already at module level)

Also adds audit scripts and entropy findings documentation.
This commit is contained in:
2026-05-06 20:18:30 -04:00
parent 54afbb9365
commit 2b5185a78f
8 changed files with 598 additions and 57 deletions
@@ -0,0 +1,73 @@
# Entropy Audit Report: src/
**Files Analyzed:** 48
**Total Lines:** 22,222
**Issues Found:** 1050
## Summary by Severity
- **High:** 12
- **Medium:** 1
- **Low:** 1037
## Summary by Category
- **long_function:** 12
- **magic_number:** 928
- **tech_debt:** 109
- **too_many_params:** 1
## High Severity Issues
### src\ai_client.py
- **Line 940:** Function `_send_gemini` is 229 lines (>200)
- Detail: `Lines 940-1169`
### src\ai_client.py
- **Line 1660:** Function `_send_deepseek` is 251 lines (>200)
- Detail: `Lines 1660-1911`
### src\ai_client.py
- **Line 1913:** Function `_send_minimax` is 216 lines (>200)
- Detail: `Lines 1913-2129`
### src\api_hooks.py
- **Line 88:** Function `do_GET` is 205 lines (>200)
- Detail: `Lines 88-293`
### src\api_hooks.py
- **Line 295:** Function `do_POST` is 350 lines (>200)
- Detail: `Lines 295-645`
### src\app_controller.py
- **Line 137:** Function `__init__` is 332 lines (>200)
- Detail: `Lines 137-469`
### src\app_controller.py
- **Line 716:** Function `_process_pending_gui_tasks` is 264 lines (>200)
- Detail: `Lines 716-980`
### src\app_controller.py
- **Line 1924:** Function `create_api` is 234 lines (>200)
- Detail: `Lines 1924-2158`
### src\gui_2.py
- **Line 750:** Function `_gui_func` is 580 lines (>200)
- Detail: `Lines 750-1330`
### src\gui_2.py
- **Line 2730:** Function `_render_discussion_panel` is 376 lines (>200)
- Detail: `Lines 2730-3106`
### src\gui_2.py
- **Line 4059:** Function `_render_mma_dashboard` is 420 lines (>200)
- Detail: `Lines 4059-4479`
### src\multi_agent_conductor.py
- **Line 403:** Function `run_worker_lifecycle` is 210 lines (>200)
- Detail: `Lines 403-613`
## Medium Severity Issues
- **Line 2236** (src\ai_client.py): Function `send` has 12 parameters
@@ -1,68 +1,69 @@
# Entropy Audit Findings: Data-Oriented Python Optimization Pass
## Phase 5 Status: In Progress
## Phase 5 Status: In Progress - Focused Audit Complete
## Issues Found and Fixed
**Approach:** Muratori-style - focused on actual issues, not style. "The less Python the better" means:
- Duplicate logic (same thing done in multiple places) = BAD
- Long functions that are linear and single-purpose = OK
- Nested imports in hot paths = BAD (performance)
- Mutable default arguments = BAD (bugs)
### 1. Duplicate Line Bug in `app_controller.py`
**Location:** `rag_emb_provider.setter` (around line 541)
**Issue:** Two identical lines in setter:
```python
if self.rag_engine: self.rag_engine = rag_engine.RAGEngine(self.rag_config, self.active_project_root)
if self.rag_engine: self.rag_engine = rag_engine.RAGEngine(self.rag_config, self.active_project_root)
```
**Fix:** Removed duplicate line.
**Status:** FIXED (commit f6feab9)
## Already Fixed This Session
### 2. FALSE POSITIVE: Python Property Definitions
**Location:** `app_controller.py`, `gui_2.py`
**Issue:** Audit script flagged `@property` getter/setter pairs as "duplicate definitions"
**Explanation:** These are correct Python property patterns (getter + setter), not bugs
**Status:** NOT AN ISSUE - False positive from audit script
### ✓ GUI Indentation Bug causing crash (commit f6feab9)
The `_render_mma_dashboard` had code incorrectly indented inside an `if` block.
## Issues Identified (Not Fixed - Require Design Decisions)
### ✓ Duplicate Line Bug in `rag_emb_provider.setter` (commit f6feab9)
`app_controller.py` had two identical lines.
### 3. Duplicate Blocking/Unblocking Logic
**Location:** `gui_2.py` vs `dag_engine.py`
### ✓ Nested Imports in Hot Paths (commit 54afbb9)
**gui_2.py has:**
- `_cb_block_ticket()` - manual transitive blocking with while loop
- `_cb_unblock_ticket()` - manual transitive unblocking with while loop
- `_reorder_ticket()` - manual dependency validation
**`multi_agent_conductor.py`:**
- Removed `import sys` from inside `run()` - was unused
- `from src.personas import PersonaManager` and `from src import paths` were already available at module level
**dag_engine.py has:**
- `cascade_blocks()` - transitive blocking propagation
- `topological_sort()` - dependency ordering
**`gui_2.py`:**
- Removed `import traceback` from inside `_gui_func` exception handler
- `import uvicorn` in `run()` remains lazy-loaded for `--headless` mode only
**Issue:** Both do similar transitive closure operations on tickets, but on different data structures:
- gui_2.py: `List[Dict[str, Any]]` (active_tickets)
- dag_engine.py: `List[Ticket]` (Ticket objects from models.py)
**`app_controller.py`:**
- Added `import traceback` and `import inspect` at module level
- Removed 3 nested `import traceback` from `_process_pending_gui_tasks`, `_handle_request_event`, `_do_generate`
**Impact:** Potential state inconsistency if GUI state and DAG engine state diverge
**Recommendation:** Refactor gui_2.py to call controller/engine methods rather than duplicating logic
## Actual Issues Found (Design - Require Architecture Changes)
### 4. Two Parallel Ticket Representations
**Locations:**
- `app_controller.py`: `self.active_tickets: List[Dict[str, Any]]` (dictionaries)
- `dag_engine.py`: `self.tickets: List[Ticket]` (dataclass instances)
### 1. Parallel Ticket Representations
**Severity:** HIGH - Maintenance burden
**Issue:** Ticket data is converted between dict and Ticket object forms. The `_load_active_tickets` method (line 3184) does:
```python
self.active_tickets = [asdict(t) if not isinstance(t, dict) else t for t in self.active_track.tickets]
```
`active_tickets` (Dict-based) is accessed/modified in THREE files:
- `api_hooks.py` - API endpoint handling
- `app_controller.py` - Main controller state
- `gui_2.py` - UI state
**Recommendation:** Consider unifying to a single representation, or ensure clear ownership of state management.
While `dag_engine.py` uses `List[Ticket]` objects. This creates state sync burden.
### 2. Duplicate Blocking Logic
**Severity:** MEDIUM - Potential state inconsistency
| Component | Has Blocking Logic? |
|-----------|-------------------|
| gui_2.py | Yes: `_cb_block_ticket`, `_cb_unblock_ticket` |
| dag_engine.py | Yes: `cascade_blocks` |
If GUI manually blocks tickets without going through DAG, state can diverge.
## Issues Not Addressed (Lower Priority)
### 5. Widespread Mixed Indentation
Many files contain 4-space indentation blocks within predominantly 1-space indented code. This is a style inconsistency but not a functional bug.
### Widespread Mixed Indentation
Many files have 4-space blocks within 1-space files. Style inconsistency only.
### 6. Import Consolidation
Multiple files have similar import patterns. Could benefit from a central `src/__init__.py` with commonly used imports, but this is cosmetic.
### Pattern Usage Across Files
These patterns appear in multiple files (by design - not duplicates):
- `calculate_track_progress`: gui_2.py, project_manager.py
- `topological_sort`: app_controller.py, conductor_tech_lead.py, dag_engine.py
- `push_mma_state`: app_controller.py, gui_2.py
## Summary
- **Fixed:** 1 bug (duplicate line in rag_emb_provider setter)
- **False Positives:** Property definitions flagged incorrectly by audit
- **Design Issues:** 2 (duplicate blocking logic, parallel ticket representations)
- **Cosmetic:** Mixed indentation, import patterns
- **Fixed:** Nested imports in hot paths (performance), 2 bugs
- **Design Issues:** 2 (parallel ticket state, duplicate blocking logic) - require architectural changes
- **Cosmetic:** Mixed indentation - intentional for readability in some places