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
+8
View File
@@ -94,5 +94,13 @@
"C:\\Users\\Ed\\AppData\\Local\\Temp\\pytest-of-Ed\\pytest-847\\test_force_full0\\other.txt": { "C:\\Users\\Ed\\AppData\\Local\\Temp\\pytest-of-Ed\\pytest-847\\test_force_full0\\other.txt": {
"hash": "04d61c0832f9cbc2a210334352425d2519890a0a5945da96ccc5bd9ff101c4d3", "hash": "04d61c0832f9cbc2a210334352425d2519890a0a5945da96ccc5bd9ff101c4d3",
"summary": "This document is a plain text file containing ten lines of content, with the first eight lines previewed. Its purpose appears to be simply to hold and present this sequential text.\n\n**Outline:**\n**TXT** \u2014 10 lines\npreview:\n```\nline1\nline2\nline3\nline4\nline5\nline6\nline7\nline8\n```" "summary": "This document is a plain text file containing ten lines of content, with the first eight lines previewed. Its purpose appears to be simply to hold and present this sequential text.\n\n**Outline:**\n**TXT** \u2014 10 lines\npreview:\n```\nline1\nline2\nline3\nline4\nline5\nline6\nline7\nline8\n```"
},
"C:\\Users\\Ed\\AppData\\Local\\Temp\\pytest-of-Ed\\pytest-848\\test_auto_aggregate_skip0\\file1.txt": {
"hash": "d0b425e00e15a0d36b9b361f02bab63563aed6cb4665083905386c55d5b679fa",
"summary": "This document contains a single line of text, \"content1\". Its purpose and key takeaways are limited to this singular piece of content.\n\n**Outline:**\n**TXT** \u2014 1 lines\npreview:\n```\ncontent1\n```"
},
"C:\\Users\\Ed\\AppData\\Local\\Temp\\pytest-of-Ed\\pytest-848\\test_force_full0\\other.txt": {
"hash": "04d61c0832f9cbc2a210334352425d2519890a0a5945da96ccc5bd9ff101c4d3",
"summary": "This document is a simple text file containing ten lines of content, with the first eight lines previewed. Its purpose appears to be for basic data storage or as a placeholder.\n\n**Outline:**\n**TXT** \u2014 10 lines\npreview:\n```\nline1\nline2\nline3\nline4\nline5\nline6\nline7\nline8\n```"
} }
} }
@@ -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 # 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` ## Already Fixed This Session
**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)
### 2. FALSE POSITIVE: Python Property Definitions ### ✓ GUI Indentation Bug causing crash (commit f6feab9)
**Location:** `app_controller.py`, `gui_2.py` The `_render_mma_dashboard` had code incorrectly indented inside an `if` block.
**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
## 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 ### ✓ Nested Imports in Hot Paths (commit 54afbb9)
**Location:** `gui_2.py` vs `dag_engine.py`
**gui_2.py has:** **`multi_agent_conductor.py`:**
- `_cb_block_ticket()` - manual transitive blocking with while loop - Removed `import sys` from inside `run()` - was unused
- `_cb_unblock_ticket()` - manual transitive unblocking with while loop - `from src.personas import PersonaManager` and `from src import paths` were already available at module level
- `_reorder_ticket()` - manual dependency validation
**dag_engine.py has:** **`gui_2.py`:**
- `cascade_blocks()` - transitive blocking propagation - Removed `import traceback` from inside `_gui_func` exception handler
- `topological_sort()` - dependency ordering - `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: **`app_controller.py`:**
- gui_2.py: `List[Dict[str, Any]]` (active_tickets) - Added `import traceback` and `import inspect` at module level
- dag_engine.py: `List[Ticket]` (Ticket objects from models.py) - 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 ## Actual Issues Found (Design - Require Architecture Changes)
**Recommendation:** Refactor gui_2.py to call controller/engine methods rather than duplicating logic
### 4. Two Parallel Ticket Representations ### 1. Parallel Ticket Representations
**Locations:** **Severity:** HIGH - Maintenance burden
- `app_controller.py`: `self.active_tickets: List[Dict[str, Any]]` (dictionaries)
- `dag_engine.py`: `self.tickets: List[Ticket]` (dataclass instances)
**Issue:** Ticket data is converted between dict and Ticket object forms. The `_load_active_tickets` method (line 3184) does: `active_tickets` (Dict-based) is accessed/modified in THREE files:
```python - `api_hooks.py` - API endpoint handling
self.active_tickets = [asdict(t) if not isinstance(t, dict) else t for t in self.active_track.tickets] - `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) ## Issues Not Addressed (Lower Priority)
### 5. Widespread Mixed Indentation ### 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. Many files have 4-space blocks within 1-space files. Style inconsistency only.
### 6. Import Consolidation ### Pattern Usage Across Files
Multiple files have similar import patterns. Could benefit from a central `src/__init__.py` with commonly used imports, but this is cosmetic. 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 ## Summary
- **Fixed:** 1 bug (duplicate line in rag_emb_provider setter) - **Fixed:** Nested imports in hot paths (performance), 2 bugs
- **False Positives:** Property definitions flagged incorrectly by audit - **Design Issues:** 2 (parallel ticket state, duplicate blocking logic) - require architectural changes
- **Design Issues:** 2 (duplicate blocking logic, parallel ticket representations) - **Cosmetic:** Mixed indentation - intentional for readability in some places
- **Cosmetic:** Mixed indentation, import patterns
+266
View File
@@ -0,0 +1,266 @@
#!/usr/bin/env python3
"""
Comprehensive Entropy Audit Script for Manual Slop src/
Checks for:
1. Duplicate function definitions
2. Duplicate class definitions
3. Very long functions (>200 lines)
4. Nested imports within functions
5. Inconsistent patterns (TODO, FIXME comments)
6. Cyclomatic complexity indicators (nested conditionals)
7. Dead code indicators (unused variables, commented out code)
"""
import os
import re
import ast
from pathlib import Path
from dataclasses import dataclass, field
from typing import List, Dict, Set, Optional
@dataclass
class EntropyIssue:
file: str
line: int
severity: str # 'high', 'medium', 'low'
category: str
description: str
detail: str = ""
@dataclass
class FileAnalysis:
path: str
size_kb: float
issues: List[EntropyIssue] = field(default_factory=list)
stats: Dict = field(default_factory=dict)
class EntropyAuditor:
def __init__(self, src_dir: str = "src"):
self.src_dir = Path(src_dir)
self.issues: List[EntropyIssue] = []
self.files_analyzed = 0
self.total_lines = 0
def analyze_file(self, filepath: Path) -> FileAnalysis:
with open(filepath, encoding='utf-8', errors='ignore') as f:
content = f.read()
lines = content.split('\n')
self.total_lines += len(lines)
analysis = FileAnalysis(
path=str(filepath),
size_kb=filepath.stat().st_size / 1024
)
# 1. Check for nested imports
self._check_nested_imports(filepath, content)
# 2. Check for very long functions
self._check_long_functions(filepath, content)
# 3. Check for TODO/FIXME
self._check_todos(filepath, content)
# 4. Check for nested depth (complexity)
self._check_nesting_depth(filepath, lines)
# 5. Check for duplicate code patterns
self._check_duplicate_patterns(filepath, lines)
# 6. Check for magic numbers
self._check_magic_numbers(filepath, lines)
return analysis
def _check_nested_imports(self, filepath: Path, content: str) -> None:
"""Check for imports inside function bodies."""
tree = ast.parse(content, filename=str(filepath))
for node in ast.walk(tree):
if isinstance(node, ast.FunctionDef):
for child in ast.walk(node):
if isinstance(child, (ast.Import, ast.ImportFrom)):
# Check if it's not at module level
if not any(isinstance(p, (ast.Import, ast.ImportFrom)) for p in tree.body):
line = child.lineno or 0
self.issues.append(EntropyIssue(
file=str(filepath),
line=line,
severity='medium',
category='nested_import',
description=f'Nested import in function `{node.name}`',
detail=ast.unparse(child)[:100]
))
def _check_long_functions(self, filepath: Path, content: str) -> None:
"""Check for functions with >200 lines or >10 parameters."""
tree = ast.parse(content, filename=str(filepath))
for node in ast.walk(tree):
if isinstance(node, (ast.FunctionDef, ast.AsyncFunctionDef)):
if node.end_lineno and node.lineno:
length = node.end_lineno - node.lineno
if length > 200:
self.issues.append(EntropyIssue(
file=str(filepath),
line=node.lineno,
severity='high',
category='long_function',
description=f'Function `{node.name}` is {length} lines (>{200})',
detail=f'Lines {node.lineno}-{node.end_lineno}'
))
if len(node.args.args) > 10:
self.issues.append(EntropyIssue(
file=str(filepath),
line=node.lineno,
severity='medium',
category='too_many_params',
description=f'Function `{node.name}` has {len(node.args.args)} parameters',
detail=str(node.args.args[:5]) + '...'
))
def _check_todos(self, filepath: Path, content: str) -> None:
"""Check for TODO/FIXME/BUG comments."""
for i, line in enumerate(content.split('\n'), 1):
if re.search(r'(TODO|FIXME|BUG|HACK|XXX)', line, re.IGNORECASE):
self.issues.append(EntropyIssue(
file=str(filepath),
line=i,
severity='low',
category='tech_debt',
description=line.strip()[:80],
detail=f'Technical debt marker'
))
def _check_nesting_depth(self, filepath: Path, lines: List[str]) -> None:
"""Check for deeply nested code blocks."""
for i, line in enumerate(lines, 1):
if line and not line.strip().startswith('#'):
# Count leading spaces
stripped = line.lstrip()
indent = len(line) - len(stripped)
if indent > 20: # More than ~10 levels deep
self.issues.append(EntropyIssue(
file=str(filepath),
line=i,
severity='medium',
category='deep_nesting',
description=f'Line has {indent} spaces of indentation',
detail=line.strip()[:60]
))
def _check_duplicate_patterns(self, filepath: Path, lines: List[str]) -> None:
"""Check for consecutive duplicate non-blank lines."""
prev_line = None
dup_start = None
for i, line in enumerate(lines, 1):
stripped = line.strip()
if stripped and not stripped.startswith('#') and stripped == prev_line:
if dup_start is None:
dup_start = i - 1
else:
if dup_start and i - dup_start > 2:
self.issues.append(EntropyIssue(
file=str(filepath),
line=dup_start,
severity='high',
category='duplicate_lines',
description=f'{i - dup_start} consecutive duplicate lines starting at {dup_start}',
detail=lines[dup_start-1].strip()[:60] if dup_start <= len(lines) else ''
))
dup_start = None
prev_line = stripped
def _check_magic_numbers(self, filepath: Path, lines: List[str]) -> None:
"""Check for magic numbers (unnamed constants)."""
magic_pattern = re.compile(r'(?<!\w)([0-9]{3,})(?!\w)') # Numbers with 3+ digits
for i, line in enumerate(lines, 1):
if not line.strip().startswith('#'):
matches = magic_pattern.findall(line)
for m in matches:
self.issues.append(EntropyIssue(
file=str(filepath),
line=i,
severity='low',
category='magic_number',
description=f'Magic number: {m}',
detail=line.strip()[:60]
))
def run_audit(self) -> None:
"""Run audit on all Python files in src/."""
py_files = list(self.src_dir.glob("*.py"))
print(f"Auditing {len(py_files)} Python files in {self.src_dir}...")
for filepath in sorted(py_files):
if filepath.name == "__init__.py":
continue
try:
self.analyze_file(filepath)
self.files_analyzed += 1
except Exception as e:
print(f"Error analyzing {filepath}: {e}")
def generate_report(self) -> str:
"""Generate a markdown report of findings."""
by_severity = {'high': [], 'medium': [], 'low': []}
by_category = {}
for issue in self.issues:
by_severity[issue.severity].append(issue)
if issue.category not in by_category:
by_category[issue.category] = []
by_category[issue.category].append(issue)
report = [
"# Entropy Audit Report: src/",
"",
f"**Files Analyzed:** {self.files_analyzed}",
f"**Total Lines:** {self.total_lines:,}",
f"**Issues Found:** {len(self.issues)}",
"",
"## Summary by Severity",
"",
f"- **High:** {len(by_severity['high'])}",
f"- **Medium:** {len(by_severity['medium'])}",
f"- **Low:** {len(by_severity['low'])}",
"",
"## Summary by Category",
""
]
for cat, issues in sorted(by_category.items()):
report.append(f"- **{cat}:** {len(issues)}")
report.extend(["", "## High Severity Issues", ""])
for issue in sorted(by_severity['high'], key=lambda x: (x.file, x.line)):
report.append(f"### {issue.file}")
report.append(f"- **Line {issue.line}:** {issue.description}")
if issue.detail:
report.append(f" - Detail: `{issue.detail[:80]}`")
report.append("")
report.extend(["", "## Medium Severity Issues", ""])
for issue in sorted(by_severity['medium'], key=lambda x: (x.file, x.line))[:50]:
report.append(f"- **Line {issue.line}** ({issue.file}): {issue.description}")
if len(by_severity['medium']) > 50:
report.append(f"\n_... and {len(by_severity['medium']) - 50} more medium issues_")
return "\n".join(report)
def main():
auditor = EntropyAuditor("src")
auditor.run_audit()
report = auditor.generate_report()
print(report)
# Also write to file
report_path = "conductor/tracks/data_oriented_optimization_20260312/entropy_audit_report.md"
with open(report_path, 'w') as f:
f.write(report)
print(f"\nReport written to {report_path}")
if __name__ == "__main__":
main()
+199
View File
@@ -0,0 +1,199 @@
#!/usr/bin/env python3
"""
Focused Entropy Audit for Manual Slop - Muratori Style
Focuses on ACTUAL issues, not style:
1. Duplicate logic (same thing done in multiple places)
2. State inconsistencies (parallel representations)
3. Logic errors / bugs
4. Performance concerns
"""
import os
import re
import ast
from pathlib import Path
from collections import defaultdict
from typing import List, Dict, Set, Tuple, Optional
def find_duplicate_logic_files():
"""Find files with similar patterns that might indicate duplicate logic."""
patterns = {
'calculate_track_progress': [],
'cascade_blocks': [],
'topological_sort': [],
'push_mma_state': [],
'active_tickets': [],
}
for f in Path('src').glob('*.py'):
content = f.read_text(encoding='utf-8', errors='ignore')
for pattern in patterns:
if re.search(pattern, content):
patterns[pattern].append(f.name)
return patterns
def check_ticket_state_management():
"""Check for state management issues in ticket handling."""
issues = []
# Check if there are parallel ticket representations
gui_2_content = Path('src/gui_2.py').read_text(encoding='utf-8', errors='ignore')
app_ctrl_content = Path('src/app_controller.py').read_text(encoding='utf-8', errors='ignore')
dag_content = Path('src/dag_engine.py').read_text(encoding='utf-8', errors='ignore')
# gui_2 uses dict-based tickets
if 'active_tickets' in gui_2_content:
if 'ticket["status"]' in gui_2_content or "t['status']" in gui_2_content:
issues.append(("gui_2.py", "Dict-based ticket access pattern found"))
# Check for blocking logic duplication
gui_blocking = len(re.findall(r'_cb_block_ticket|_cb_unblock_ticket', gui_2_content))
dag_blocking = len(re.findall(r'cascade_blocks', dag_content))
if gui_blocking > 0 and dag_blocking > 0:
issues.append(("architecture", "GUI has manual block/unblock that could conflict with DAG cascade_blocks"))
return issues
def check_import_issues():
"""Check for actual import problems - nested imports causing runtime issues."""
issues = []
for f in Path('src').glob('*.py'):
try:
content = f.read_text(encoding='utf-8', errors='ignore')
tree = ast.parse(content, filename=str(f))
for node in ast.walk(tree):
if isinstance(node, ast.FunctionDef):
for child in ast.walk(node):
if isinstance(child, (ast.Import, ast.ImportFrom)):
line = child.lineno or 0
# Check if this import is inside a HOT PATH function
if node.name in ['_process_pending_gui_tasks', '_gui_func', 'run', 'tick']:
issues.append((f.name, f"Nested import `{ast.unparse(child).strip()[:50]}` in hot path `{node.name}` line {line}"))
except:
pass
return issues
def check_potential_bugs():
"""Check for potential bugs - undefined variables, etc."""
bugs = []
# Check for == None vs is None patterns
for f in Path('src').glob('*.py'):
content = f.read_text(encoding='utf-8', errors='ignore')
lines = content.split('\n')
for i, line in enumerate(lines, 1):
# Skip comments
if line.strip().startswith('#'):
continue
# Check for mutable default arguments (common bug)
if re.search(r'def\s+\w+\([^)]*=\s*\[\s*\]', line):
bugs.append((f.name, i, "Mutable default argument", line.strip()[:60]))
if re.search(r'def\s+\w+\([^)]*=\s*\{\s*\}', line):
bugs.append((f.name, i, "Mutable default argument", line.strip()[:60]))
return bugs
def check_actual_duplicates():
"""Check for ACTUAL duplicate code - same logic copied."""
duplicates = []
seen_snippets = defaultdict(list)
# Look for duplicate patterns (3+ lines identical)
for f in sorted(Path('src').glob('*.py')):
try:
content = f.read_text(encoding='utf-8', errors='ignore')
lines = content.split('\n')
# Normalize and check consecutive duplicate lines
prev_normalized = None
dup_start = None
for i, line in enumerate(lines, 1):
if line.strip().startswith('#'):
prev_normalized = None
dup_start = None
continue
normalized = line.strip()
if not normalized:
prev_normalized = None
dup_start = None
continue
if normalized == prev_normalized:
if dup_start is None:
dup_start = i - 1
else:
if dup_start and i - dup_start >= 3:
# Found 3+ consecutive duplicate lines
duplicates.append((f.name, dup_start, i - 1, lines[dup_start-1].strip()[:60]))
dup_start = None
prev_normalized = normalized
except:
pass
return duplicates
def main():
print("=" * 70)
print("FOCUSED ENTROPY AUDIT - Muratori Style")
print("=" * 70)
print()
print("1. TICKET STATE MANAGEMENT ISSUES")
print("-" * 40)
issues = check_ticket_state_management()
if issues:
for issue in issues:
print(f" [{issue[0]}] {issue[1]}")
else:
print(" None found")
print()
print("2. NESTED IMPORTS IN HOT PATH FUNCTIONS")
print("-" * 40)
issues = check_import_issues()
if issues:
for fname, msg in issues[:10]:
print(f" [{fname}] {msg}")
else:
print(" None found")
print()
print("3. POTENTIAL BUGS (mutable defaults, etc)")
print("-" * 40)
issues = check_potential_bugs()
if issues:
for fname, line, bugtype, code in issues[:10]:
print(f" [{fname}:{line}] {bugtype}: {code}")
else:
print(" None found")
print()
print("4. ACTUAL DUPLICATE CODE (3+ consecutive lines)")
print("-" * 40)
duplicates = check_actual_duplicates()
if duplicates:
for fname, start, end, code in duplicates[:10]:
print(f" [{fname}:{start}-{end}] {code}")
else:
print(" None found")
print()
print("5. PATTERN USAGE ACROSS FILES")
print("-" * 40)
patterns = find_duplicate_logic_files()
for pattern, files in patterns.items():
if len(files) > 1:
print(f" {pattern}: {files}")
print()
if __name__ == "__main__":
main()
+2 -4
View File
@@ -2,8 +2,10 @@ import threading
import time import time
import copy import copy
import sys import sys
import traceback
import os import os
import re import re
import inspect
from typing import Any, List, Dict, Optional, Callable from typing import Any, List, Dict, Optional, Callable
from pathlib import Path from pathlib import Path
from src import workspace_manager from src import workspace_manager
@@ -865,7 +867,6 @@ class AppController:
elif item == "btn_mma_load_track": elif item == "btn_mma_load_track":
self._cb_load_track(str(user_data or "")) self._cb_load_track(str(user_data or ""))
elif item in self._clickable_actions: elif item in self._clickable_actions:
import inspect
func = self._clickable_actions[item] func = self._clickable_actions[item]
try: try:
sig = inspect.signature(func) sig = inspect.signature(func)
@@ -974,7 +975,6 @@ class AppController:
self.mma_streams[stream_id] = "" self.mma_streams[stream_id] = ""
self.mma_streams[stream_id] += f"[BEAD UPDATE] {bead_id} -> status: {status}\n" self.mma_streams[stream_id] += f"[BEAD UPDATE] {bead_id} -> status: {status}\n"
except Exception as e: except Exception as e:
import traceback
sys.stderr.write(f"[DEBUG] Error executing GUI task: {e}\n{traceback.format_exc()}\n") sys.stderr.write(f"[DEBUG] Error executing GUI task: {e}\n{traceback.format_exc()}\n")
sys.stderr.flush() sys.stderr.flush()
print(f"Error executing GUI task: {e}") print(f"Error executing GUI task: {e}")
@@ -1642,7 +1642,6 @@ class AppController:
sys.stderr.flush() sys.stderr.flush()
self.event_queue.put("response", {"text": e.ui_message(), "status": "error", "role": "Vendor API"}) self.event_queue.put("response", {"text": e.ui_message(), "status": "error", "role": "Vendor API"})
except Exception as e: except Exception as e:
import traceback
sys.stderr.write(f"[DEBUG] _handle_request_event ERROR: {e}\n{traceback.format_exc()}\n") sys.stderr.write(f"[DEBUG] _handle_request_event ERROR: {e}\n{traceback.format_exc()}\n")
sys.stderr.flush() sys.stderr.flush()
self.event_queue.put("response", {"text": f"ERROR: {e}", "status": "error", "role": "System"}) self.event_queue.put("response", {"text": f"ERROR: {e}", "status": "error", "role": "System"})
@@ -2642,7 +2641,6 @@ class AppController:
sys.stderr.write("[DEBUG] Enqueued user_request event\n") sys.stderr.write("[DEBUG] Enqueued user_request event\n")
sys.stderr.flush() sys.stderr.flush()
except Exception as e: except Exception as e:
import traceback
sys.stderr.write(f"[DEBUG] _do_generate ERROR: {e}\n{traceback.format_exc()}\n") sys.stderr.write(f"[DEBUG] _do_generate ERROR: {e}\n{traceback.format_exc()}\n")
sys.stderr.flush() sys.stderr.flush()
self._set_status(f"generate error: {e}") self._set_status(f"generate error: {e}")
+1 -1
View File
@@ -35,6 +35,7 @@ from src import thinking_parser
import re import re
import difflib import difflib
import subprocess import subprocess
import traceback
if sys.platform == "win32": if sys.platform == "win32":
import win32gui import win32gui
import win32con import win32con
@@ -1319,7 +1320,6 @@ class App:
imgui.end_popup() imgui.end_popup()
except Exception as e: except Exception as e:
print(f"ERROR in _gui_func: {e}") print(f"ERROR in _gui_func: {e}")
import traceback
traceback.print_exc() traceback.print_exc()
if pushed_prior_tint: if pushed_prior_tint:
-4
View File
@@ -218,7 +218,6 @@ class ConductorEngine:
md_content: The full markdown context (history + files) for AI workers. md_content: The full markdown context (history + files) for AI workers.
max_ticks: Optional limit on number of iterations (for testing). max_ticks: Optional limit on number of iterations (for testing).
""" """
import sys
tick_count = 0 tick_count = 0
while True: while True:
if self._pause_event.is_set(): if self._pause_event.is_set():
@@ -282,10 +281,7 @@ class ConductorEngine:
else: else:
# Check if ticket has a persona with preferred_models # Check if ticket has a persona with preferred_models
if ticket.persona_id: if ticket.persona_id:
# Try to load preferred_models from persona
try: try:
from src.personas import PersonaManager
from src import paths
pm = PersonaManager(Path(paths.get_project_personas_path(Path.cwd())) if paths.get_project_personas_path(Path.cwd()).exists() else None) pm = PersonaManager(Path(paths.get_project_personas_path(Path.cwd())) if paths.get_project_personas_path(Path.cwd()).exists() else None)
personas = pm.load_all() personas = pm.load_all()
if ticket.persona_id in personas: if ticket.persona_id in personas: