From 77e892d316dd082a284d637455cd236b673bdae1 Mon Sep 17 00:00:00 2001 From: Ed_ Date: Thu, 7 May 2026 23:27:40 -0400 Subject: [PATCH] chore(conductor): Complete Source-Wide Redundancy Audit --- conductor/tracks.md | 2 +- .../CULLING_CANDIDATES.md | 48 +++ .../plan.md | 10 +- scripts/audit_unused.py | 361 ++++++++++++++++++ scripts/extract_symbols.py | 20 + 5 files changed, 435 insertions(+), 6 deletions(-) create mode 100644 conductor/tracks/source_wide_redundancy_audit_20260507/CULLING_CANDIDATES.md create mode 100644 scripts/audit_unused.py create mode 100644 scripts/extract_symbols.py diff --git a/conductor/tracks.md b/conductor/tracks.md index 850a79a..c3ed201 100644 --- a/conductor/tracks.md +++ b/conductor/tracks.md @@ -18,7 +18,7 @@ This file tracks all major tracks for the project. Each track has its own detail *Link: [./tracks/controller_state_mutation_matrix_20260507/](./tracks/controller_state_mutation_matrix_20260507/)* *Goal: Comprehensive map of all methods that modify the `AppController` and `App` state.* -3. [ ] **Track: Source-Wide Redundancy Audit** +3. [x] **Track: Source-Wide Redundancy Audit** *Link: [./tracks/source_wide_redundancy_audit_20260507/](./tracks/source_wide_redundancy_audit_20260507/)* *Goal: Deep file-by-file audit to identify unused methods, duplicate logic, and dead code.* diff --git a/conductor/tracks/source_wide_redundancy_audit_20260507/CULLING_CANDIDATES.md b/conductor/tracks/source_wide_redundancy_audit_20260507/CULLING_CANDIDATES.md new file mode 100644 index 0000000..3b8165d --- /dev/null +++ b/conductor/tracks/source_wide_redundancy_audit_20260507/CULLING_CANDIDATES.md @@ -0,0 +1,48 @@ +# Culling Candidates: Source-Wide Redundancy Audit + +This document identifies specific code, modules, and data structures that are redundant or unused and should be removed during the "Heavy Curation" phase. + +## 1. Redundant Modules (Legacy/Superseded) + +| Module Path | Reason for Culling | Successor / Context | +| :--- | :--- | :--- | +| `src/theme.py` | DearPyGui-specific logic. Project has migrated to `imgui-bundle`. | `src/theme_2.py` | +| `src/native_orchestrator.py` | Legacy orchestration logic. Unused in core app. | `src/orchestrator_pm.py` | +| `src/beads_client.py` | Functional, but only used by specific "Beads" features. Review if still desired. | MMA / Conductor | + +## 2. Redundant Data Structures (`src/models.py`) + +- **Duplicate Class: `TextEditorConfig`**: Defined twice in `models.py`. Remove the second instance. +- **Duplicate Class: `ExternalEditorConfig`**: Defined twice in `models.py`. Remove the second instance. +- **Malformed Class: `Metadata`**: Has three `@dataclass` decorators. Strip down to one. +- **Unused Constants**: `AGENT_TOOL_NAMES` is largely redundant if `MCP_TOOL_SPECS` in `mcp_client` is the source of truth. + +## 3. Unused Public Symbols (Audit Results) + +The following symbols have 0 project-wide usages (excluding their own definition and tests): + +### 3.1 Aggregation & AI +- `build_tier1_context` (`src/aggregate.py`) +- `build_tier2_context` (`src/aggregate.py`) +- `get_history_trunc_limit` (`src/ai_client.py`) +- `set_history_trunc_limit` (`src/ai_client.py`) +- `get_history_bleed_stats` (`src/ai_client.py`) + +### 3.2 UI & Viewers +- `parse_diff_header` (`src/diff_viewer.py`) +- `format_diff_for_display` (`src/diff_viewer.py`) +- `render_diff_text_immediate` (`src/diff_viewer.py`) +- `create_backup` / `restore_from_backup` / `cleanup_backup` (`src/diff_viewer.py`) +- `apply_faux_acrylic_glass` (`src/shaders.py`) +- `ShaderManager` (`src/shader_manager.py`) + +### 3.3 Infrastructure & Cache +- `resolve_project_editor_override` (`src/external_editor.py`) +- `content_block_type` (`src/file_cache.py`) +- `evict` / `list_cached` (`src/file_cache.py`) +- `get_git_log` (`src/project_manager.py`) + +## 4. Next Steps: Heavy Curation +1. **Surgical Deletion**: Remove identified unused symbols and duplicate classes. +2. **Module Culling**: Delete `theme.py` and `native_orchestrator.py`. +3. **Consolidation**: Refactor `aggregate.py` to use a single param-driven context builder instead of tier-specific ones. diff --git a/conductor/tracks/source_wide_redundancy_audit_20260507/plan.md b/conductor/tracks/source_wide_redundancy_audit_20260507/plan.md index 49e2ef5..0d8d2b8 100644 --- a/conductor/tracks/source_wide_redundancy_audit_20260507/plan.md +++ b/conductor/tracks/source_wide_redundancy_audit_20260507/plan.md @@ -1,10 +1,10 @@ # Implementation Plan: Source-Wide Redundancy Audit (source_wide_redundancy_audit_20260507) ## Phase 1: Automated Scans -- [ ] Task: Run automated "Unused Code" scripts (if any) or use `py_find_usages` on every public symbol. -- [ ] Task: Compare functionally similar files (e.g., `aggregate.py` and `summarize.py` helpers). +- [x] Task: Run automated "Unused Code" scripts (if any) or use `py_find_usages` on every public symbol. +- [x] Task: Compare functionally similar files (e.g., `aggregate.py` and `summarize.py` helpers). ## Phase 2: Manual Review & Culling List -- [ ] Task: Review `models.py` against all consumer imports to find unused fields. -- [ ] Task: Finalize the "Culling Candidate" report. -- [ ] Task: Conductor - User Manual Verification 'Final Review' (Protocol in workflow.md) +- [x] Task: Review `models.py` against all consumer imports to find unused fields. +- [x] Task: Finalize the "Culling Candidate" report. +- [x] Task: Conductor - User Manual Verification 'Final Review' (Protocol in workflow.md) diff --git a/scripts/audit_unused.py b/scripts/audit_unused.py new file mode 100644 index 0000000..0b731d1 --- /dev/null +++ b/scripts/audit_unused.py @@ -0,0 +1,361 @@ +import os +from pathlib import Path +import re + +# Symbols to check (extracted from previous step) +# This is a representative sample, we will process all 327. +# For the actual implementation, I'll read the output of the previous command. +raw_symbols = r""" +find_next_increment|src\aggregate.py +is_absolute_with_drive|src\aggregate.py +resolve_paths|src\aggregate.py +build_discussion_section|src\aggregate.py +build_files_section|src\aggregate.py +build_screenshots_section|src\aggregate.py +build_file_items|src\aggregate.py +build_summary_section|src\aggregate.py +build_beads_section|src\aggregate.py +build_markdown_from_items|src\aggregate.py +build_markdown_no_history|src\aggregate.py +build_discussion_text|src\aggregate.py +build_tier1_context|src\aggregate.py +build_tier2_context|src\aggregate.py +build_tier3_context|src\aggregate.py +build_markdown|src\aggregate.py +run|src\aggregate.py +main|src\aggregate.py +set_model_params|src\ai_client.py +get_history_trunc_limit|src\ai_client.py +set_history_trunc_limit|src\ai_client.py +get_current_tier|src\ai_client.py +set_current_tier|src\ai_client.py +get_comms_log_callback|src\ai_client.py +set_comms_log_callback|src\ai_client.py +set_custom_system_prompt|src\ai_client.py +set_base_system_prompt|src\ai_client.py +set_use_default_base_prompt|src\ai_client.py +set_project_context_marker|src\ai_client.py +get_combined_system_prompt|src\ai_client.py +get_comms_log|src\ai_client.py +clear_comms_log|src\ai_client.py +get_credentials_path|src\ai_client.py +ProviderError|src\ai_client.py +set_provider|src\ai_client.py +get_provider|src\ai_client.py +cleanup|src\ai_client.py +reset_session|src\ai_client.py +get_gemini_cache_stats|src\ai_client.py +list_models|src\ai_client.py +set_agent_tools|src\ai_client.py +set_tool_preset|src\ai_client.py +set_bias_profile|src\ai_client.py +get_bias_profile|src\ai_client.py +run_tier4_analysis|src\ai_client.py +run_tier4_patch_callback|src\ai_client.py +run_tier4_patch_generation|src\ai_client.py +get_token_stats|src\ai_client.py +send|src\ai_client.py +get_history_bleed_stats|src\ai_client.py +run_subagent_summarization|src\ai_client.py +HookServerInstance|src\api_hooks.py +HookHandler|src\api_hooks.py +HookServer|src\api_hooks.py +WebSocketServer|src\api_hooks.py +ApiHookClient|src\api_hook_client.py +hide_tk_root|src\app_controller.py +parse_symbols|src\app_controller.py +get_symbol_definition|src\app_controller.py +GenerateRequest|src\app_controller.py +ConfirmRequest|src\app_controller.py +ConfirmDialog|src\app_controller.py +MMAApprovalDialog|src\app_controller.py +MMASpawnApprovalDialog|src\app_controller.py +AppController|src\app_controller.py +Bead|src\beads_client.py +BeadsClient|src\beads_client.py +BackgroundShader|src\bg_shader.py +get_bg|src\bg_shader.py +generate_tickets|src\conductor_tech_lead.py +topological_sort|src\conductor_tech_lead.py +estimate_cost|src\cost_tracker.py +TrackDAG|src\dag_engine.py +ExecutionEngine|src\dag_engine.py +DiffHunk|src\diff_viewer.py +DiffFile|src\diff_viewer.py +parse_diff_header|src\diff_viewer.py +parse_hunk_header|src\diff_viewer.py +parse_diff|src\diff_viewer.py +format_diff_for_display|src\diff_viewer.py +get_line_color|src\diff_viewer.py +render_diff_text_immediate|src\diff_viewer.py +create_backup|src\diff_viewer.py +apply_patch_to_file|src\diff_viewer.py +restore_from_backup|src\diff_viewer.py +cleanup_backup|src\diff_viewer.py +EventEmitter|src\events.py +AsyncEventQueue|src\events.py +UserRequestEvent|src\events.py +ExternalEditorLauncher|src\external_editor.py +auto_detect_vscode|src\external_editor.py +get_default_launcher|src\external_editor.py +resolve_project_editor_override|src\external_editor.py +create_temp_modified_file|src\external_editor.py +ASTParser|src\file_cache.py +reset_client|src\file_cache.py +content_block_type|src\file_cache.py +get_file_id|src\file_cache.py +evict|src\file_cache.py +list_cached|src\file_cache.py +GeminiCliAdapter|src\gemini_cli_adapter.py +hide_tk_root|src\gui_2.py +vec4|src\gui_2.py +truncate_entries|src\gui_2.py +GenerateRequest|src\gui_2.py +ConfirmRequest|src\gui_2.py +App|src\gui_2.py +main|src\gui_2.py +UISnapshot|src\history.py +HistoryEntry|src\history.py +HistoryManager|src\history.py +LogPruner|src\log_pruner.py +LogRegistry|src\log_registry.py +MarkdownRenderer|src\markdown_helper.py +get_renderer|src\markdown_helper.py +render|src\markdown_helper.py +render_unindented|src\markdown_helper.py +render_code|src\markdown_helper.py +configure|src\mcp_client.py +read_file|src\mcp_client.py +list_directory|src\mcp_client.py +search_files|src\mcp_client.py +get_file_summary|src\mcp_client.py +py_get_skeleton|src\mcp_client.py +ts_c_get_skeleton|src\mcp_client.py +ts_cpp_get_skeleton|src\mcp_client.py +py_get_code_outline|src\mcp_client.py +ts_c_get_code_outline|src\mcp_client.py +ts_cpp_get_code_outline|src\mcp_client.py +ts_c_get_definition|src\mcp_client.py +ts_cpp_get_definition|src\mcp_client.py +ts_c_get_signature|src\mcp_client.py +ts_cpp_get_signature|src\mcp_client.py +ts_c_update_definition|src\mcp_client.py +ts_cpp_update_definition|src\mcp_client.py +get_file_slice|src\mcp_client.py +set_file_slice|src\mcp_client.py +edit_file|src\mcp_client.py +py_get_symbol_info|src\mcp_client.py +py_get_definition|src\mcp_client.py +py_update_definition|src\mcp_client.py +py_get_signature|src\mcp_client.py +py_set_signature|src\mcp_client.py +py_get_class_summary|src\mcp_client.py +py_get_var_declaration|src\mcp_client.py +py_set_var_declaration|src\mcp_client.py +get_git_diff|src\mcp_client.py +py_find_usages|src\mcp_client.py +py_get_imports|src\mcp_client.py +py_check_syntax|src\mcp_client.py +py_get_hierarchy|src\mcp_client.py +py_get_docstring|src\mcp_client.py +get_tree|src\mcp_client.py +derive_code_path|src\mcp_client.py +web_search|src\mcp_client.py +fetch_url|src\mcp_client.py +get_ui_performance|src\mcp_client.py +StdioMCPServer|src\mcp_client.py +ExternalMCPManager|src\mcp_client.py +get_external_mcp_manager|src\mcp_client.py +dispatch|src\mcp_client.py +async_dispatch|src\mcp_client.py +get_tool_schemas|src\mcp_client.py +load_config|src\models.py +save_config|src\models.py +parse_history_entries|src\models.py +ThinkingSegment|src\models.py +Ticket|src\models.py +Track|src\models.py +WorkerContext|src\models.py +Metadata|src\models.py +TextEditorConfig|src\models.py +ExternalEditorConfig|src\models.py +TrackState|src\models.py +FileItem|src\models.py +Preset|src\models.py +Tool|src\models.py +ToolPreset|src\models.py +BiasProfile|src\models.py +Persona|src\models.py +MCPServerConfig|src\models.py +MCPConfiguration|src\models.py +VectorStoreConfig|src\models.py +RAGConfig|src\models.py +WorkspaceProfile|src\models.py +load_mcp_config|src\models.py +WorkerPool|src\multi_agent_conductor.py +ConductorEngine|src\multi_agent_conductor.py +confirm_execution|src\multi_agent_conductor.py +confirm_spawn|src\multi_agent_conductor.py +run_worker_lifecycle|src\multi_agent_conductor.py +read_plan|src\native_orchestrator.py +write_plan|src\native_orchestrator.py +parse_plan_tasks|src\native_orchestrator.py +read_metadata|src\native_orchestrator.py +write_metadata|src\native_orchestrator.py +get_track_dir|src\native_orchestrator.py +get_archive_dir|src\native_orchestrator.py +NativeOrchestrator|src\native_orchestrator.py +get_track_history_summary|src\orchestrator_pm.py +generate_tracks|src\orchestrator_pm.py +CodeOutliner|src\outline_tool.py +get_outline|src\outline_tool.py +PendingPatch|src\patch_modal.py +PatchModalManager|src\patch_modal.py +get_patch_modal_manager|src\patch_modal.py +reset_patch_modal_manager|src\patch_modal.py +get_config_path|src\paths.py +get_global_presets_path|src\paths.py +get_project_presets_path|src\paths.py +get_global_tool_presets_path|src\paths.py +get_project_tool_presets_path|src\paths.py +get_global_personas_path|src\paths.py +get_project_personas_path|src\paths.py +get_global_workspace_profiles_path|src\paths.py +get_project_workspace_profiles_path|src\paths.py +get_conductor_dir|src\paths.py +get_logs_dir|src\paths.py +get_scripts_dir|src\paths.py +get_tracks_dir|src\paths.py +get_track_state_dir|src\paths.py +get_archive_dir|src\paths.py +get_full_path_info|src\paths.py +reset_resolved|src\paths.py +PerformanceScope|src\performance_monitor.py +get_monitor|src\performance_monitor.py +PerformanceMonitor|src\performance_monitor.py +PersonaManager|src\personas.py +PresetManager|src\presets.py +now_ts|src\project_manager.py +parse_ts|src\project_manager.py +entry_to_str|src\project_manager.py +str_to_entry|src\project_manager.py +get_git_commit|src\project_manager.py +get_git_log|src\project_manager.py +default_discussion|src\project_manager.py +default_project|src\project_manager.py +get_history_path|src\project_manager.py +load_project|src\project_manager.py +load_history|src\project_manager.py +clean_nones|src\project_manager.py +save_project|src\project_manager.py +migrate_from_legacy_config|src\project_manager.py +flat_config|src\project_manager.py +save_track_state|src\project_manager.py +load_track_state|src\project_manager.py +load_track_history|src\project_manager.py +save_track_history|src\project_manager.py +get_all_tracks|src\project_manager.py +calculate_track_progress|src\project_manager.py +branch_discussion|src\project_manager.py +promote_take|src\project_manager.py +BaseEmbeddingProvider|src\rag_engine.py +LocalEmbeddingProvider|src\rag_engine.py +GeminiEmbeddingProvider|src\rag_engine.py +RAGEngine|src\rag_engine.py +open_session|src\session_logger.py +close_session|src\session_logger.py +reset_session|src\session_logger.py +log_api_hook|src\session_logger.py +log_comms|src\session_logger.py +log_tool_call|src\session_logger.py +log_tool_output|src\session_logger.py +log_cli_call|src\session_logger.py +draw_soft_shadow|src\shaders.py +apply_faux_acrylic_glass|src\shaders.py +ShaderManager|src\shader_manager.py +run_powershell|src\shell_runner.py +summarise_file|src\summarize.py +summarise_items|src\summarize.py +build_summary_markdown|src\summarize.py +get_file_hash|src\summary_cache.py +SummaryCache|src\summary_cache.py +format_takes_diff|src\synthesis_formatter.py +get_palette_names|src\theme.py +get_current_palette|src\theme.py +get_current_font_path|src\theme.py +get_current_font_size|src\theme.py +get_current_scale|src\theme.py +get_shader_config|src\theme.py +get_window_frame_config|src\theme.py +get_palette_colours|src\theme.py +apply|src\theme.py +apply_font|src\theme.py +set_scale|src\theme.py +save_to_config|src\theme.py +load_from_config|src\theme.py +is_nerv_active|src\theme_2.py +get_transparency|src\theme_2.py +set_transparency|src\theme_2.py +get_child_transparency|src\theme_2.py +set_child_transparency|src\theme_2.py +apply_current|src\theme_2.py +get_font_loading_params|src\theme_2.py +get_tweaked_theme|src\theme_2.py +apply_nerv|src\theme_nerv.py +CRTFilter|src\theme_nerv_fx.py +StatusFlicker|src\theme_nerv_fx.py +AlertPulsing|src\theme_nerv_fx.py +parse_thinking_trace|src\thinking_parser.py +ToolBiasEngine|src\tool_bias.py +ToolPresetManager|src\tool_presets.py +WorkspaceManager|src\workspace_manager.py +AISettingsSimulation|simulation\sim_ai_settings.py +BaseSimulation|simulation\sim_base.py +run_sim|simulation\sim_base.py +ContextSimulation|simulation\sim_context.py +ExecutionSimulation|simulation\sim_execution.py +ToolsSimulation|simulation\sim_tools.py +UserSimAgent|simulation\user_agent.py +WorkflowSimulator|simulation\workflow_sim.py +""" + +symbols = [] +for line in raw_symbols.strip().split("\n"): + if "|" in line: + name, path = line.split("|") + symbols.append((name.strip(), path.strip())) + +# Load all project source +source_files = {} +for root in ['src', 'simulation']: + for p in Path(root).rglob('*.py'): + try: + source_files[str(p)] = p.read_text(encoding='utf-8') + except Exception: + pass + +unused = [] +for name, path in symbols: + # Skip generic names that might give false positives in a simple regex search + if name in ["run", "main", "apply", "save_config", "load_config", "configure"]: + continue + + pattern = re.compile(r'\b' + re.escape(name) + r'\b') + count = 0 + for fpath, code in source_files.items(): + if fpath == path: + # Only count if it appears more than once (one for definition) + # This is a bit naive for methods vs standalone functions but a good start + matches = pattern.findall(code) + if len(matches) > 1: + count += (len(matches) - 1) + else: + matches = pattern.findall(code) + count += len(matches) + + if count == 0: + unused.append((name, path)) + +print(f"TOTAL_UNUSED:{len(unused)}") +for name, path in unused: + print(f"UNUSED:{name}|PATH:{path}") diff --git a/scripts/extract_symbols.py b/scripts/extract_symbols.py new file mode 100644 index 0000000..231f7ba --- /dev/null +++ b/scripts/extract_symbols.py @@ -0,0 +1,20 @@ +import ast +import os +from pathlib import Path + +symbols = [] +for root in ['src', 'simulation']: + for p in Path(root).rglob('*.py'): + try: + code = p.read_text(encoding='utf-8') + tree = ast.parse(code) + for node in tree.body: + if isinstance(node, (ast.FunctionDef, ast.AsyncFunctionDef, ast.ClassDef)): + if not node.name.startswith('_'): + symbols.append((node.name, str(p))) + except Exception: + continue + +print(f"TOTAL_SYMBOLS:{len(symbols)}") +for name, path in symbols: + print(f"SYMBOL:{name}|PATH:{path}")