conductor(followup): module_taxonomy_refactor_20260627 - track artifacts
The user-reported models.py is a 'dumping ground' (1044 lines, 36 classes,
5+ unrelated domains). This track cleans it up PLUS addresses 5 ImGui
LEAKS that violate the 'ImGui belongs in gui_2.py' boundary PLUS
unifies 2 vendor files with ai_client.py.
TIER-1 READ AGENTS.md + conductor/workflow.md + conductor/edit_workflow.md
+ conductor/code_styleguides/data_oriented_design.md + conductor/code_styleguides/error_handling.md
+ conductor/code_styleguides/type_aliases.md + conductor/code_styleguides/code_path_audit.md
+ docs/reports/FOLLOWUP_module_taxonomy_20260627.md + conductor/tracks/cruft_elimination_20260627/SPEC_CORRECTION_phase_2.md
+ src/models.py before this commit.
User's principle: unify unless good reason (import load times or
definition pollution). No sub-directories; prefix naming.
Only 3 refactors justified (12 VCs total):
1. MERGE 5 ImGui LEAKS into gui_2.py (per user directive: 'all ImGui
rendering should be in gui_2.py; only exception imgui_scopes.py'):
- bg_shader.py, shaders.py, command_palette.py, diff_viewer.py,
patch_modal.py -> content to gui_2.py, git rm originals
2. MERGE 2 vendor files into ai_client.py (per user directive: 'vendor
files are the ai vendoring layer'):
- vendor_capabilities.py + vendor_state.py -> ai_client.py
- ai_client.py grows 3147 -> ~3310 lines (justified: unified)
3. SPLIT models.py (clear definition pollution: 5+ domains, 36 classes):
- CREATE src/mma.py (MMA Core: ThinkingSegment, Ticket, Track,
WorkerContext, TrackState)
- CREATE src/project.py (ProjectContext + 5 sub + config IO)
- CREATE src/project_files.py (FileItem, ContextPreset, etc.)
- MERGE 6+ classes into existing sub-system files:
- Persona -> personas.py
- Tool/ToolPreset -> tool_presets.py
- BiasProfile -> tool_bias.py
- TextEditorConfig/ExternalEditorConfig -> external_editor.py
- MCP config classes -> mcp_client.py
- WorkspaceProfile -> workspace_manager.py
- REDUCE models.py to ~30 lines (Pydantic proxies only) or DELETE
BONUS (user caught this): AGENT_TOOL_NAMES is REDUNDANT with
mcp_tool_specs.tool_names(). The existing test literally asserts
tool_names() ⊆ AGENT_TOOL_NAMES. DELETE the constant, update 8
consumer sites to use mcp_tool_specs.tool_names() directly.
Net scope: -4 files (65 -> 61; possibly 60 if models.py deleted).
22 atomic commits. 5 phases.
blocked_by: cruft_elimination_20260627 (the cruft track has a
ProjectContext-in-models.py commit that needs to coordinate with
this refactor's move to project.py)
This commit is contained in:
@@ -0,0 +1,256 @@
|
||||
# Tier 2 Startup Brief: module_taxonomy_refactor_20260627
|
||||
|
||||
## Context
|
||||
|
||||
The user reported `models.py` is a "dumping ground" (1044 lines, 36 classes, 5+ unrelated domains). They want a clean taxonomy. Per their principle: **unify unless there's a good reason (import load times, definition pollution)**. No sub-directories. Prefix naming.
|
||||
|
||||
## MANDATORY Pre-Action Reading (per agent protocol)
|
||||
|
||||
1. `AGENTS.md` (project root) — operating rules, especially "File Size and Naming Convention" HARD RULE
|
||||
2. `conductor/workflow.md` — the workflow
|
||||
3. `conductor/edit_workflow.md` — the edit workflow
|
||||
4. `conductor/code_styleguides/data_oriented_design.md` — "Prefer Fewer Types" principle
|
||||
5. `conductor/code_styleguides/error_handling.md` — the `Result[T]` convention (Rule #0: read first)
|
||||
6. `conductor/code_styleguides/type_aliases.md` — the 10 TypeAliases convention
|
||||
7. `conductor/code_styleguides/code_path_audit.md` — code path audit styleguide
|
||||
8. `docs/reports/FOLLOWUP_module_taxonomy_20260627.md` — the audit that motivated this track
|
||||
9. `conductor/tracks/cruft_elimination_20260627/SPEC_CORRECTION_phase_2.md` — the related spec correction
|
||||
10. `src/models.py` — the 1044-line file to split (read in full)
|
||||
|
||||
**First commit of this track must include** `TIER-2 READ <list> before module_taxonomy_refactor_20260627` in the message.
|
||||
|
||||
## The Decision Rule (the user's principle)
|
||||
|
||||
**Split a file only if ONE of:**
|
||||
- Import load time: the file has heavy imports (vendored SDKs, ML models) that some code paths don't need
|
||||
- Definition pollution: the file mixes 3+ unrelated domains with 30+ classes/functions
|
||||
|
||||
**Otherwise: keep in a single file.** Move imports around, but don't fragment.
|
||||
|
||||
**No sub-directories.** All files at `src/` flat with prefix naming.
|
||||
|
||||
## The 3 Refactors (only 3 justified)
|
||||
|
||||
### Refactor 1: MERGE 5 ImGui LEAKS into `gui_2.py`
|
||||
|
||||
**Justification:** User explicit directive: "all ImGui rendering should be in `gui_2.py`. Only exception: `imgui_scopes.py`." Clear violation of the GUI boundary.
|
||||
|
||||
| File | Lines | Content | Destination |
|
||||
|---|---:|---|---|
|
||||
| `src/bg_shader.py` | 66 | ImGui background shader | `src/gui_2.py` |
|
||||
| `src/shaders.py` | 33 | ImGui shader code | `src/gui_2.py` |
|
||||
| `src/command_palette.py` | 165 | ImGui command palette UI | `src/gui_2.py` |
|
||||
| `src/diff_viewer.py` | 164 | ImGui diff viewer UI | `src/gui_2.py` |
|
||||
| `src/patch_modal.py` | 102 | ImGui patch modal UI | `src/gui_2.py` |
|
||||
|
||||
**Verification:** `git grep -l "imgui_bundle\|from imgui\\." -- 'src/*.py'` returns ONLY `gui_2.py` + `imgui_scopes.py`.
|
||||
|
||||
### Refactor 2: MERGE 2 vendor files into `ai_client.py`
|
||||
|
||||
**Justification:** User explicit directive: "vendor_capabilities.py and vendor_state.py are related to ai_client.py... they're the ai vendoring layer."
|
||||
|
||||
| File | Lines | Content | Destination |
|
||||
|---|---:|---|---|
|
||||
| `src/vendor_capabilities.py` | 85 | Vendor capability flags | `src/ai_client.py` |
|
||||
| `src/vendor_state.py` | 78 | Vendor state telemetry | `src/ai_client.py` |
|
||||
|
||||
**Growth:** `ai_client.py` 3147 → ~3310 lines. Justified: unified vendor layer, no fragmentation.
|
||||
|
||||
### Refactor 3: SPLIT `models.py` (the only justified split)
|
||||
|
||||
**Justification:** 5+ unrelated domains, 36 classes, 1044 lines. **Clear definition pollution** (the user's threshold: "3+ unrelated domains with 30+ classes").
|
||||
|
||||
**The new taxonomy:**
|
||||
|
||||
| New file | What it gets | Lines (est.) |
|
||||
|---|---|---:|
|
||||
| `src/mma.py` | MMA Core: ThinkingSegment, Ticket, Track, WorkerContext, TrackState | ~250 |
|
||||
| `src/project.py` | ProjectContext + 5 sub + config I/O + parse_history_entries | ~200 |
|
||||
| `src/project_files.py` | FileItem, ContextPreset, ContextFileEntry, NamedViewPreset, Preset | ~150 |
|
||||
|
||||
**6+ classes merge into existing sub-system files (NOT new files):**
|
||||
|
||||
| Class from `models.py` | Destination |
|
||||
|---|---|
|
||||
| `Persona` | `src/personas.py` (93 lines, exists) |
|
||||
| `Tool`, `ToolPreset` | `src/tool_presets.py` (123 lines, exists) |
|
||||
| `BiasProfile` | `src/tool_bias.py` (63 lines, exists) |
|
||||
| `TextEditorConfig`, `ExternalEditorConfig` | `src/external_editor.py` (129 lines, exists) |
|
||||
| `MCPServerConfig`, `MCPConfiguration`, `VectorStoreConfig`, `RAGConfig`, `load_mcp_config` | `src/mcp_client.py` (1803 lines, exists) |
|
||||
| `WorkspaceProfile` | `src/workspace_manager.py` (73 lines, exists) |
|
||||
|
||||
**`src/models.py` reduced:**
|
||||
- ~30 lines: Pydantic proxy helpers (`_create_generate_request`, `_create_confirm_request`, `__getattr__`)
|
||||
- OR delete the file entirely if it becomes essentially empty (it's not a "system" file; just a temporary holder)
|
||||
|
||||
## The Bonus Refactor: DELETE `AGENT_TOOL_NAMES` (redundant)
|
||||
|
||||
**User caught this:** "isn't AGENT_TOOL_NAMES a redundant thing that's directly associated with the mcp_client.py?"
|
||||
|
||||
YES. The existing test `test_tool_names_subset_of_models_agent_tool_names` literally asserts:
|
||||
```python
|
||||
native_names = mcp_tool_specs.tool_names()
|
||||
agent_names = set(models.AGENT_TOOL_NAMES)
|
||||
assert not missing_in_agent, f"Native tools not in AGENT_TOOL_NAMES: {missing_in_agent}"
|
||||
```
|
||||
|
||||
So `AGENT_TOOL_NAMES` is just a hardcoded snapshot of `mcp_tool_specs.tool_names()`. **DELETE it, not move it.**
|
||||
|
||||
**8 consumer sites to update:**
|
||||
- `src/app_controller.py:2110, 2972, 3273` (3 sites)
|
||||
- `tests/test_arch_boundary_phase2.py:23, 29, 31, 32, 33` (5 sites)
|
||||
|
||||
**Pattern:** `from src.models import AGENT_TOOL_NAMES; for tool in AGENT_TOOL_NAMES: ...` → `from src import mcp_tool_specs; for tool in mcp_tool_specs.tool_names(): ...`
|
||||
|
||||
## Net scope
|
||||
|
||||
- 7 files deleted (5 ImGui + 2 vendor)
|
||||
- 3 new files (mma.py, project.py, project_files.py)
|
||||
- 10 files modified (7 sub-system merges + ai_client.py + gui_2.py + app_controller.py)
|
||||
- 1 file potentially deleted (models.py)
|
||||
- Net: 65 → 61 files (or 60 if models.py is eliminated)
|
||||
- 22 atomic commits
|
||||
|
||||
## Coordination with `cruft_elimination_20260627`
|
||||
|
||||
The `cruft_elimination_20260627` track has a Phase 2 commit that put `ProjectContext` in `models.py` (the wrong location per this track). **DO NOT** merge that `cruft` commit until this refactor is ready. The refactor moves `ProjectContext` to `project.py` as part of Phase 3.
|
||||
|
||||
## Pre-flight verification
|
||||
|
||||
```bash
|
||||
# Verify the current state of src/
|
||||
ls src/*.py | wc -l
|
||||
# Expect: 65
|
||||
|
||||
# Verify models.py is 1044 lines
|
||||
wc -l src/models.py
|
||||
# Expect: 1044
|
||||
|
||||
# Verify ImGui LEAKS exist
|
||||
ls src/bg_shader.py src/shaders.py src/command_palette.py src/diff_viewer.py src/patch_modal.py 2>&1 | grep -v "No such"
|
||||
# Expect: all 5 exist
|
||||
|
||||
# Verify vendor files exist
|
||||
ls src/vendor_capabilities.py src/vendor_state.py 2>&1 | grep -v "No such"
|
||||
# Expect: both exist
|
||||
|
||||
# Verify AGENT_TOOL_NAMES is referenced
|
||||
git grep "AGENT_TOOL_NAMES" HEAD -- 'src/*.py' 'tests/*.py' | wc -l
|
||||
# Expect: 8 hits (3 app_controller + 5 test_arch_boundary + 1 def + ... )
|
||||
|
||||
# Verify all 7 audit gates pass (baseline)
|
||||
uv run python scripts/audit_weak_types.py --strict
|
||||
uv run python scripts/generate_type_registry.py --check
|
||||
uv run python scripts/audit_main_thread_imports.py
|
||||
uv run python scripts/audit_no_models_config_io.py
|
||||
uv run python scripts/audit_code_path_audit_coverage.py --input-dir docs/reports/code_path_audit/latest --strict
|
||||
uv run python scripts/audit_exception_handling.py --strict
|
||||
uv run python scripts/audit_optional_in_3_files.py --strict
|
||||
# All exit 0
|
||||
```
|
||||
|
||||
## Post-track verification (after Phase 5)
|
||||
|
||||
```bash
|
||||
# VC1: ImGui imports limited to gui_2.py + imgui_scopes.py
|
||||
git grep -l "imgui_bundle\|from imgui\\." HEAD -- 'src/*.py'
|
||||
# Expect: gui_2.py, imgui_scopes.py
|
||||
|
||||
# VC2-3: ImGui LEAKS + vendor files deleted
|
||||
ls src/bg_shader.py src/shaders.py src/command_palette.py src/diff_viewer.py src/patch_modal.py src/vendor_capabilities.py src/vendor_state.py 2>&1 | grep -v "No such"
|
||||
# Expect: (no output)
|
||||
|
||||
# VC5-7: New files work
|
||||
uv run python -c "from src.mma import ThinkingSegment, Ticket, Track, WorkerContext, TrackState"
|
||||
uv run python -c "from src.project import ProjectContext, ProjectMeta, ProjectOutput, ProjectFiles, ProjectScreenshots, ProjectDiscussion, _clean_nones, load_config_from_disk, save_config_to_disk, parse_history_entries"
|
||||
uv run python -c "from src.project_files import FileItem, ContextPreset, ContextFileEntry, NamedViewPreset, Preset"
|
||||
# All succeed
|
||||
|
||||
# VC8: 6+ dataclasses in proper sub-system files
|
||||
uv run python -c "from src.personas import Persona; from src.tool_presets import Tool, ToolPreset; from src.tool_bias import BiasProfile; from src.external_editor import TextEditorConfig, ExternalEditorConfig; from src.mcp_client import MCPServerConfig, MCPConfiguration, VectorStoreConfig, RAGConfig, load_mcp_config; from src.workspace_manager import WorkspaceProfile"
|
||||
# Expect: no ImportError
|
||||
|
||||
# VC9: AGENT_TOOL_NAMES deleted
|
||||
git grep "AGENT_TOOL_NAMES" HEAD -- 'src/*.py' 'tests/*.py' | wc -l
|
||||
# Expect: 0
|
||||
|
||||
# VC10: models.py reduced or eliminated
|
||||
ls src/models.py 2>&1
|
||||
# Expect: file not found (or <= 30 lines if kept)
|
||||
|
||||
# VC11-12: audit gates + batched suite
|
||||
# Same as current baseline
|
||||
```
|
||||
|
||||
## Per-phase patterns for Tier 3 workers
|
||||
|
||||
### Per-file atomic commits
|
||||
Each ImGui merge, each vendor merge, each models.py split, each AGENT_TOOL_NAMES site update is a separate commit. Per-file = atomic rollback.
|
||||
|
||||
### Pattern: move content + delete source
|
||||
|
||||
```bash
|
||||
# 1. Read source file
|
||||
cat src/bg_shader.py
|
||||
|
||||
# 2. Add to destination file (with region marker)
|
||||
manual-slop_edit_file gui_2.py
|
||||
# add at appropriate location:
|
||||
#region: Bg Shader (moved from src/bg_shader.py)
|
||||
# ... content ...
|
||||
#endregion
|
||||
|
||||
# 3. Update import sites across the codebase
|
||||
git grep "from src.bg_shader" -- 'src/*.py' 'tests/*.py'
|
||||
# Replace each with: from src.gui_2 import
|
||||
|
||||
# 4. Delete source file
|
||||
git rm src/bg_shader.py
|
||||
|
||||
# 5. Verify
|
||||
uv run python -m pytest tests/test_<affected>.py -v
|
||||
```
|
||||
|
||||
### Pattern: split models.py
|
||||
|
||||
```python
|
||||
# 1. Create new file (e.g., src/mma.py)
|
||||
manual-slop_edit_file mma.py
|
||||
# Add the moved classes with proper imports
|
||||
|
||||
# 2. Update import sites
|
||||
git grep "from src.models import.*(ThinkingSegment|Ticket|Track|WorkerContext|TrackState)" -- 'src/*.py' 'tests/*.py'
|
||||
# Replace each with: from src.mma import
|
||||
|
||||
# 3. Remove from models.py
|
||||
manual-slop_edit_file models.py
|
||||
# Delete the moved class definitions
|
||||
|
||||
# 4. Verify
|
||||
uv run python -m pytest tests/test_mma_*.py -v
|
||||
```
|
||||
|
||||
### Style
|
||||
- 1-space indentation (project standard)
|
||||
- CRLF line endings
|
||||
- No comments in source code (per AGENTS.md)
|
||||
- Use `manual-slop_edit_file` for surgical edits
|
||||
- Per-phase regression-guard test runs after each phase
|
||||
|
||||
## Notes for Tier 2 reviewer
|
||||
|
||||
- The `cruft_elimination_20260627` track's Phase 2 commit put `ProjectContext` in `models.py`. Coordinate: that commit should NOT merge until this refactor is ready (or the cruft track should re-execute Phase 2 with the corrected file location per `SPEC_CORRECTION_phase_2.md`).
|
||||
- The `__getattr__` Pydantic lazy proxy in `models.py` is needed for circular import (src.ai_client imports ToolPreset/BiasProfile/Tool from src.models). After this refactor, the imports move to the new sub-system files (tool_presets.py, tool_bias.py), so the circular import is broken and the `__getattr__` may no longer be needed. Audit during execution.
|
||||
- The `models.py` docstring needs updating throughout the refactor to reflect the new scope.
|
||||
- If `models.py` becomes essentially empty after all moves, **delete the file entirely** (it's not a "system" file).
|
||||
|
||||
## See also
|
||||
|
||||
- `conductor/tracks/module_taxonomy_refactor_20260627/spec.md` — the spec (12 VCs)
|
||||
- `conductor/tracks/module_taxonomy_refactor_20260627/plan.md` — the 5-phase plan (22 atomic commits)
|
||||
- `conductor/tracks/module_taxonomy_refactor_20260627/metadata.json` — the metadata
|
||||
- `conductor/tracks/module_taxonomy_refactor_20260627/state.toml` — the state
|
||||
- `docs/reports/FOLLOWUP_module_taxonomy_20260627.md` — the audit
|
||||
- `conductor/tracks/cruft_elimination_20260627/SPEC_CORRECTION_phase_2.md` — the related spec correction
|
||||
- `AGENTS.md` — "File Size and Naming Convention" HARD RULE
|
||||
- `conductor/code_styleguides/data_oriented_design.md` — "Prefer Fewer Types" principle
|
||||
@@ -0,0 +1,78 @@
|
||||
{
|
||||
"track_id": "module_taxonomy_refactor_20260627",
|
||||
"name": "Module Taxonomy Refactor",
|
||||
"status": "active",
|
||||
"type": "cleanup",
|
||||
"date_created": "2026-06-27",
|
||||
"created_by": "tier1-orchestrator",
|
||||
"blocks": [],
|
||||
"blocked_by": {
|
||||
"cruft_elimination_20260627": "pending (the cruft track has a ProjectContext-in-models.py commit that needs to be coordinated)"
|
||||
},
|
||||
"scope": {
|
||||
"new_files": [
|
||||
"src/mma.py",
|
||||
"src/project.py",
|
||||
"src/project_files.py",
|
||||
"conductor/tracks/module_taxonomy_refactor_20260627/TIER2_STARTUP.md"
|
||||
],
|
||||
"modified_files": [
|
||||
"src/gui_2.py",
|
||||
"src/ai_client.py",
|
||||
"src/personas.py",
|
||||
"src/tool_presets.py",
|
||||
"src/tool_bias.py",
|
||||
"src/external_editor.py",
|
||||
"src/mcp_client.py",
|
||||
"src/workspace_manager.py",
|
||||
"src/app_controller.py",
|
||||
"tests/test_arch_boundary_phase2.py"
|
||||
],
|
||||
"deleted_files": [
|
||||
"src/bg_shader.py",
|
||||
"src/shaders.py",
|
||||
"src/command_palette.py",
|
||||
"src/diff_viewer.py",
|
||||
"src/patch_modal.py",
|
||||
"src/vendor_capabilities.py",
|
||||
"src/vendor_state.py"
|
||||
],
|
||||
"potentially_deleted_files": [
|
||||
"src/models.py"
|
||||
]
|
||||
},
|
||||
"verification_criteria": [
|
||||
"ImGui imports limited to gui_2.py + imgui_scopes.py",
|
||||
"5 ImGui LEAK files deleted (bg_shader, shaders, command_palette, diff_viewer, patch_modal)",
|
||||
"2 vendor files deleted (vendor_capabilities, vendor_state); symbols now in ai_client.py",
|
||||
"src/mma.py exists with MMA Core + TrackState",
|
||||
"src/project.py exists with ProjectContext + sub + config IO",
|
||||
"src/project_files.py exists with file-related dataclasses",
|
||||
"6+ dataclasses in proper sub-system files (Persona/Tool/Editor/MCP/Workspace)",
|
||||
"AGENT_TOOL_NAMES deleted; 8 consumer sites use mcp_tool_specs.tool_names()",
|
||||
"src/models.py reduced to <=30 lines (or eliminated)",
|
||||
"All 7 audit gates pass --strict (no regression)",
|
||||
"10/11 batched test tiers pass (RAG flake acceptable)"
|
||||
],
|
||||
"estimated_effort": {
|
||||
"method": "scope (per workflow.md \u00a7Tier 1 Track Initialization Rules). NO day estimates.",
|
||||
"scope": "1 source file split into 3 (mma.py, project.py, project_files.py) + 7 files deleted (5 ImGui + 2 vendor) + 7 files modified (ai_client.py, gui_2.py, 5 sub-system files) + 8 import sites updated for AGENT_TOOL_NAMES; 22 atomic commits total"
|
||||
},
|
||||
"risk_register": [
|
||||
"R1 (low): ImGui LEAKS move breaks existing tests (e.g., command_palette is referenced in commands.py) - mitigated by running full affected test set after each move; revert + fix on regression",
|
||||
"R2 (medium): Vendor merge into ai_client.py creates circular imports (PROVIDERS lazy proxy is the workaround) - mitigated by the lazy import pattern; verify by running full test suite after merge",
|
||||
"R3 (high): models.py split breaks 136 import sites - mitigated by per-file move with regression-guard tests after each; update imports systematically",
|
||||
"R4 (medium): 6+ 'merge into existing sub-system files' moves break those files' existing tests - mitigated by running affected test file after each merge",
|
||||
"R5 (low): AGENT_TOOL_NAMES deletion breaks test_arch_boundary_phase2.py - mitigated by updating the test to use mcp_tool_specs.tool_names(); cross-check that the test's expected tool names are in the registry",
|
||||
"R6 (high): The ProjectContext Phase 2 commit (in cruft_elimination_20260627) put ProjectContext in models.py; the new track moves it to project.py - needs to coordinate with the cruft track; the cruft track should NOT merge its ProjectContext-in-models.py commit until this refactor is ready",
|
||||
"R7 (low): The _create_generate_request etc. Pydantic proxies in models.py are used by api_hooks.py; if we move them to api_hooks.py we create a different topology - mitigated by auditing the consumers; if all in api_hooks.py, move them; if not, keep in models.py or move to a new api_models.py"
|
||||
],
|
||||
"out_of_scope": [
|
||||
"Renaming existing files for prefix consistency (multi_agent_conductor.py -> mma_conductor.py, etc.) - deferred to follow-up",
|
||||
"Refactoring aggregate.py (513 lines), app_controller.py (4869 lines), gui_2.py (7773 lines) - out of scope; these have natural boundaries",
|
||||
"Modifications to mcp_client.py other than merging the config dataclasses",
|
||||
"New src/<thing>.py files beyond the 3 justified ones (mma.py, project.py, project_files.py)",
|
||||
"The RAG test pre-existing flake (per docs/reports/SSDL_CAMPAIGN_ABORTED_20260624.md Out of Scope)",
|
||||
"Any Tier 2 spec rewrites (per the user's earlier 'don't fuck with commits' directive)"
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,194 @@
|
||||
# Plan: module_taxonomy_refactor_20260627
|
||||
|
||||
5 phases, 12-15 tasks, 12+ atomic commits. Per-task TDD red-first. Tier 3 workers execute; Tier 2 reviews per phase.
|
||||
|
||||
## Phase 0: Pre-flight + TIER2_STARTUP (Tier 1, 0 commits, 1 file)
|
||||
|
||||
- [x] **Task 0.1** [Tier 1]: Create `conductor/tracks/module_taxonomy_refactor_20260627/TIER2_STARTUP.md` with:
|
||||
- Decision rule (user's principle): split ONLY for import load times or definition pollution
|
||||
- The 3 refactors (merge ImGui LEAKS, merge vendor files, split models.py)
|
||||
- 8 AGENT_TOOL_NAMES consumer sites
|
||||
- 5 ImGui LEAK files
|
||||
- 6+ sub-system merge destinations
|
||||
- MANDATORY Pre-Action Reading list
|
||||
- [x] **NOTE:** This task is done in the planning phase; no commit needed (TIER2_STARTUP.md is committed with the track artifacts in a single commit at the end)
|
||||
|
||||
## Phase 1: MERGE ImGui LEAKS into `gui_2.py` (5 commits, 1 per file)
|
||||
|
||||
**Focus:** 5 ImGui-using files that violate the "ImGui belongs in `gui_2.py`" boundary. Each is a separate commit for atomic rollback.
|
||||
|
||||
- [x] **Task 1.1** [Tier 3]: Move `src/bg_shader.py` (66 lines) → `src/gui_2.py` (add as section "Bg Shader (moved from src/bg_shader.py)")
|
||||
- HOW: `manual-slop_edit_file` to append to gui_2.py; `git mv` to delete bg_shader.py
|
||||
- SAFETY: Run `tests/test_imgui_scopes.py` + any tests that import from `src.bg_shader`
|
||||
- [x] **COMMIT 1.1:** `refactor(gui_2): merge bg_shader into gui_2; git rm src/bg_shader.py` (Tier 3)
|
||||
- [x] **Task 1.2-1.5** [Tier 3]: Same pattern for `shaders.py`, `command_palette.py`, `diff_viewer.py`, `patch_modal.py`
|
||||
- [x] **COMMITS 1.2-1.5:** One per file
|
||||
- [x] **VERIFICATION:** `git grep -l "imgui_bundle\|from imgui\\." -- 'src/*.py'` returns ONLY `gui_2.py` + `imgui_scopes.py`
|
||||
|
||||
## Phase 2: MERGE vendor files into `ai_client.py` (2 commits, 1 per file)
|
||||
|
||||
**Focus:** 2 vendor files that should be unified with `ai_client.py` per user directive.
|
||||
|
||||
- [x] **Task 2.1** [Tier 3]: Move `src/vendor_capabilities.py` (85 lines) → `src/ai_client.py` (add as section "Vendor Capabilities (moved from src/vendor_capabilities.py)")
|
||||
- HOW: `manual-slop_edit_file` to append to ai_client.py; `git mv` to delete vendor_capabilities.py
|
||||
- SAFETY: Run `tests/test_provider_state_migration.py` + any tests that import from `src.vendor_capabilities`
|
||||
- [x] **COMMIT 2.1:** `refactor(ai_client): merge vendor_capabilities into ai_client; git rm src/vendor_capabilities.py` (Tier 3)
|
||||
- [x] **Task 2.2** [Tier 3]: Same for `src/vendor_state.py` (78 lines)
|
||||
- [x] **COMMIT 2.2:** `refactor(ai_client): merge vendor_state into ai_client; git rm src/vendor_state.py` (Tier 3)
|
||||
|
||||
## Phase 3: SPLIT `models.py` (8 commits, 3 new files + 6 merges + 1 reduce)
|
||||
|
||||
**Focus:** `models.py` is the only file with clear definition pollution (5+ domains, 36 classes, 1044 lines). Split into `mma.py` + `project.py` + `project_files.py`; merge other classes into existing sub-system files; reduce `models.py`.
|
||||
|
||||
### Phase 3a: Create new files (3 commits)
|
||||
|
||||
- [x] **Task 3.1** [Tier 3]: Create `src/mma.py` with `ThinkingSegment`, `Ticket`, `Track`, `WorkerContext`, `TrackState` (moved from `models.py`)
|
||||
- HOW: `manual-slop_edit_file` to write the new file
|
||||
- Update imports in 5 files: `multi_agent_conductor.py`, `dag_engine.py`, `orchestrator_pm.py`, `conductor_tech_lead.py`, `mma_prompts.py`
|
||||
- SAFETY: Run `tests/test_mma_*.py` + `tests/test_orchestration_logic.py` + `tests/test_dag_engine.py` + `tests/test_conductor_engine_v2.py`
|
||||
- [x] **COMMIT 3.1:** `refactor(mma): create mma.py with MMA Core + TrackState (split from models.py)` (Tier 3)
|
||||
- [x] **Task 3.2** [Tier 3]: Create `src/project.py` with `ProjectContext` + 5 sub-dataclasses + config I/O (`_clean_nones`, `load_config_from_disk`, `save_config_to_disk`, `parse_history_entries`)
|
||||
- HOW: `manual-slop_edit_file` to write the new file
|
||||
- Update imports in `src/project_manager.py` (and any other consumer)
|
||||
- SAFETY: Run `tests/test_project_manager_*.py` + `tests/test_project_context_20260627.py` (new file from cruft track)
|
||||
- [x] **COMMIT 3.2:** `refactor(project): create project.py with ProjectContext + sub + config IO (split from models.py)` (Tier 3)
|
||||
- [x] **Task 3.3** [Tier 3]: Create `src/project_files.py` with `FileItem`, `ContextPreset`, `ContextFileEntry`, `NamedViewPreset`, `Preset`
|
||||
- HOW: `manual-slop_edit_file` to write the new file
|
||||
- Update imports in `src/aggregate.py`, `src/context_presets.py`, `src/gui_2.py`, `src/app_controller.py`
|
||||
- SAFETY: Run `tests/test_context_composition_*.py` + `tests/test_view_presets.py` + `tests/test_custom_slices_*.py`
|
||||
- [x] **COMMIT 3.3:** `refactor(project_files): create project_files.py (split from models.py)` (Tier 3)
|
||||
|
||||
### Phase 3b: Merge other classes into existing sub-system files (6 commits, 1 per destination)
|
||||
|
||||
- [x] **Task 3.4** [Tier 3]: Move `Persona` from `models.py` → `src/personas.py` (existing 93-line file)
|
||||
- HOW: `manual-slop_edit_file` to add Persona dataclass to personas.py; `manual-slop_edit_file` to remove from models.py
|
||||
- Update imports: `from src.models import Persona` → `from src.personas import Persona`
|
||||
- SAFETY: Run `tests/test_personas_*.py` + `tests/test_arch_boundary_*.py` (if Persona is tested there)
|
||||
- [x] **COMMIT 3.4:** `refactor(personas): move Persona dataclass from models.py to personas.py` (Tier 3)
|
||||
- [x] **Task 3.5** [Tier 3]: Move `Tool`, `ToolPreset` → `src/tool_presets.py` (existing 123-line file)
|
||||
- [x] **Task 3.6** [Tier 3]: Move `BiasProfile` → `src/tool_bias.py` (existing 63-line file)
|
||||
- [x] **Task 3.7** [Tier 3]: Move `TextEditorConfig`, `ExternalEditorConfig` → `src/external_editor.py` (existing 129-line file)
|
||||
- [x] **Task 3.8** [Tier 3]: Move `MCPServerConfig`, `MCPConfiguration`, `VectorStoreConfig`, `RAGConfig`, `load_mcp_config` → `src/mcp_client.py` (existing 1803-line file)
|
||||
- [x] **Task 3.9** [Tier 3]: Move `WorkspaceProfile` → `src/workspace_manager.py` (existing 73-line file)
|
||||
- [x] **COMMITS 3.5-3.9:** One per merge
|
||||
|
||||
### Phase 3c: Reduce `models.py` (1 commit)
|
||||
|
||||
- [x] **Task 3.10** [Tier 3]: After all moves, `src/models.py` should be ~30 lines (Pydantic proxies + AGENT_TOOL_NAMES)
|
||||
- HOW: `manual-slop_edit_file` to remove all moved classes; keep only the Pydantic proxy helpers
|
||||
- If `models.py` becomes empty, **delete the file entirely** (it's not a "system" file)
|
||||
- [x] **COMMIT 3.10:** `refactor(models): reduce to Pydantic proxy helpers only (or delete entirely if empty)` (Tier 3)
|
||||
|
||||
## Phase 4: DELETE `AGENT_TOOL_NAMES` (1 commit)
|
||||
|
||||
**Focus:** `AGENT_TOOL_NAMES` is redundant (verified by `test_tool_names_subset_of_models_agent_tool_names` which asserts `tool_names() ⊆ AGENT_TOOL_NAMES`). Derive at consumer sites.
|
||||
|
||||
- [x] **Task 4.1** [Tier 3]: Update 8 consumer sites to use `mcp_tool_specs.tool_names()` instead of `AGENT_TOOL_NAMES`:
|
||||
- `src/app_controller.py:2110, 2972, 3273` (3 sites)
|
||||
- `tests/test_arch_boundary_phase2.py:23, 29, 31, 32, 33` (5 sites)
|
||||
- HOW: `manual-slop_edit_file` per site
|
||||
- SAFETY: Run the affected tests + the full batched suite
|
||||
- [x] **Task 4.2** [Tier 3]: Delete `AGENT_TOOL_NAMES` constant from `src/models.py` (if not already removed in Phase 3c)
|
||||
- [x] **Task 4.3** [Tier 3]: DELETE or CONVERT `test_tool_names_subset_of_models_agent_tool_names` test
|
||||
- DELETE: it's a tautology once AGENT_TOOL_NAMES is derived
|
||||
- OR CONVERT to: `assert mcp_tool_specs.tool_names() == {expected canonical tools}`
|
||||
- [x] **COMMIT 4.1:** `refactor(mcp_tool_specs): delete redundant AGENT_TOOL_NAMES; use tool_names() at consumer sites` (Tier 3)
|
||||
|
||||
## Phase 5: Verification + end-of-track (2 commits, no code changes)
|
||||
|
||||
**Focus:** Run all 12 VCs; write `TRACK_COMPLETION`; update `state.toml` + `tracks.md`.
|
||||
|
||||
- [x] **Task 5.1** [Tier 2]:
|
||||
- Run all 12 VCs (see spec.md §Verification Criteria)
|
||||
- Re-measure: `wc -l src/models.py` should be ≤30 (or file should not exist)
|
||||
- Run all 7 audit gates
|
||||
- Run the full batched test suite
|
||||
- Document the result in `docs/reports/TRACK_COMPLETION_module_taxonomy_refactor_20260627.md`
|
||||
- [x] **COMMIT 5.1:** `conductor(state): module_taxonomy_refactor_20260627 SHIPPED` (Tier 2)
|
||||
- [x] **COMMIT 5.2:** `docs(reports): TRACK_COMPLETION_module_taxonomy_refactor_20260627` (Tier 2)
|
||||
- [x] **COMMIT 5.3:** `conductor(tracks): add module_taxonomy_refactor_20260627 row` (Tier 2)
|
||||
|
||||
## Commit Log (Expected, 12-15 atomic commits)
|
||||
|
||||
1. (Phase 0) `conductor(track): module_taxonomy_refactor_20260627 track artifacts` (Tier 1) — spec + plan + metadata + state + TIER2_STARTUP
|
||||
2. (Phase 1) `refactor(gui_2): merge bg_shader; git rm src/bg_shader.py` (Tier 3)
|
||||
3. (Phase 1) `refactor(gui_2): merge shaders; git rm src/shaders.py` (Tier 3)
|
||||
4. (Phase 1) `refactor(gui_2): merge command_palette; git rm src/command_palette.py` (Tier 3)
|
||||
5. (Phase 1) `refactor(gui_2): merge diff_viewer; git rm src/diff_viewer.py` (Tier 3)
|
||||
6. (Phase 1) `refactor(gui_2): merge patch_modal; git rm src/patch_modal.py` (Tier 3)
|
||||
7. (Phase 2) `refactor(ai_client): merge vendor_capabilities; git rm src/vendor_capabilities.py` (Tier 3)
|
||||
8. (Phase 2) `refactor(ai_client): merge vendor_state; git rm src/vendor_state.py` (Tier 3)
|
||||
9. (Phase 3a) `refactor(mma): create mma.py with MMA Core + TrackState (split from models.py)` (Tier 3)
|
||||
10. (Phase 3a) `refactor(project): create project.py with ProjectContext + sub + config IO (split from models.py)` (Tier 3)
|
||||
11. (Phase 3a) `refactor(project_files): create project_files.py (split from models.py)` (Tier 3)
|
||||
12. (Phase 3b) `refactor(personas): move Persona dataclass from models.py to personas.py` (Tier 3)
|
||||
13. (Phase 3b) `refactor(tool_presets): move Tool + ToolPreset from models.py to tool_presets.py` (Tier 3)
|
||||
14. (Phase 3b) `refactor(tool_bias): move BiasProfile from models.py to tool_bias.py` (Tier 3)
|
||||
15. (Phase 3b) `refactor(external_editor): move TextEditorConfig + ExternalEditorConfig from models.py to external_editor.py` (Tier 3)
|
||||
16. (Phase 3b) `refactor(mcp_client): move MCP config dataclasses from models.py to mcp_client.py` (Tier 3)
|
||||
17. (Phase 3b) `refactor(workspace_manager): move WorkspaceProfile from models.py to workspace_manager.py` (Tier 3)
|
||||
18. (Phase 3c) `refactor(models): reduce to Pydantic proxy helpers only (or delete entirely if empty)` (Tier 3)
|
||||
19. (Phase 4) `refactor(mcp_tool_specs): delete redundant AGENT_TOOL_NAMES; use tool_names() at consumer sites` (Tier 3)
|
||||
20. (Phase 5) `conductor(state): module_taxonomy_refactor_20260627 SHIPPED` (Tier 2)
|
||||
21. (Phase 5) `docs(reports): TRACK_COMPLETION_module_taxonomy_refactor_20260627` (Tier 2)
|
||||
22. (Phase 5) `conductor(tracks): add module_taxonomy_refactor_20260627 row` (Tier 2)
|
||||
|
||||
Plus per-task plan-update commits per the workflow.
|
||||
|
||||
## Verification Commands (run at end of each phase + Phase 5)
|
||||
|
||||
```bash
|
||||
# VC1: ImGui imports limited to gui_2.py + imgui_scopes.py
|
||||
git grep -l "imgui_bundle\|from imgui\\." HEAD -- 'src/*.py'
|
||||
|
||||
# VC2: 5 ImGui files deleted
|
||||
ls src/bg_shader.py src/shaders.py src/command_palette.py src/diff_viewer.py src/patch_modal.py 2>&1 | grep -v "No such file"
|
||||
|
||||
# VC3: 2 vendor files deleted
|
||||
ls src/vendor_capabilities.py src/vendor_state.py 2>&1 | grep -v "No such file"
|
||||
|
||||
# VC5-7: New files work
|
||||
uv run python -c "from src.mma import ThinkingSegment, Ticket, Track, WorkerContext, TrackState"
|
||||
uv run python -c "from src.project import ProjectContext, ProjectMeta, ProjectOutput, ProjectFiles, ProjectScreenshots, ProjectDiscussion"
|
||||
uv run python -c "from src.project_files import FileItem, ContextPreset, ContextFileEntry, NamedViewPreset, Preset"
|
||||
|
||||
# VC8: 6+ dataclasses in proper sub-system files
|
||||
uv run python -c "from src.personas import Persona; from src.tool_presets import Tool, ToolPreset; from src.tool_bias import BiasProfile; from src.external_editor import TextEditorConfig, ExternalEditorConfig; from src.mcp_client import MCPServerConfig, MCPConfiguration, VectorStoreConfig, RAGConfig, load_mcp_config; from src.workspace_manager import WorkspaceProfile"
|
||||
|
||||
# VC9: AGENT_TOOL_NAMES deleted
|
||||
git grep "AGENT_TOOL_NAMES" HEAD -- 'src/*.py' 'tests/*.py' | wc -l
|
||||
# Expect: 0
|
||||
|
||||
# VC10: models.py reduced
|
||||
Get-Item src/models.py 2>&1 | Select-Object Length
|
||||
# Expect: file not found OR <= 30 lines
|
||||
|
||||
# VC11: 7 audit gates pass
|
||||
uv run python scripts/audit_weak_types.py --strict
|
||||
uv run python scripts/generate_type_registry.py --check
|
||||
uv run python scripts/audit_main_thread_imports.py
|
||||
uv run python scripts/audit_no_models_config_io.py
|
||||
uv run python scripts/audit_code_path_audit_coverage.py --input-dir docs/reports/code_path_audit/latest --strict
|
||||
uv run python scripts/audit_exception_handling.py --strict
|
||||
uv run python scripts/audit_optional_in_3_files.py --strict
|
||||
# All exit 0
|
||||
|
||||
# VC12: 10/11 batched tiers pass
|
||||
uv run python scripts/run_tests_batched.py
|
||||
# Expect: 10/11 PASS (RAG flake acceptable)
|
||||
```
|
||||
|
||||
## Notes for Tier 3 workers
|
||||
|
||||
- **Per-file atomic commits**: each ImGui merge, each vendor merge, each models.py split, each AGENT_TOOL_NAMES site update is a separate commit
|
||||
- **Pattern consistency**: use `git mv` for renames; for merges, append content to the destination file, then `git rm` the source
|
||||
- **Import updates**: use `manual-slop_edit_file` to update import statements; for `from src.bg_shader import X` → `from src.gui_2 import X` patterns
|
||||
- **Indentation**: 1-space per level
|
||||
- **No comments** in source code (per AGENTS.md)
|
||||
- **Per-phase regression-guard test runs**: after each phase, run the full batched test suite. If a phase causes a regression, REVERT the phase commit and investigate (don't try to fix forward)
|
||||
|
||||
## Notes for Tier 2 reviewer
|
||||
|
||||
- The `cruft_elimination_20260627` track has a `ProjectContext` commit that put `ProjectContext` in `models.py` (the wrong location). This refactor track moves `ProjectContext` to `project.py`. Coordinate with the cruft track: the `cruft` track should NOT merge its `ProjectContext`-in-`models.py` commit until this refactor is ready.
|
||||
- The `__getattr__` Pydantic lazy proxy in `models.py` is needed because `src.ai_client` imports `ToolPreset`/`BiasProfile`/`Tool` from `models.py`, creating a circular import. After this refactor, the imports move to the new sub-system files (`tool_presets.py`, `tool_bias.py`), so the circular import is broken and the `__getattr__` may no longer be needed. Audit during execution.
|
||||
- The `models.py` docstring needs updating throughout the refactor to reflect the new scope.
|
||||
@@ -0,0 +1,224 @@
|
||||
# Track Specification: module_taxonomy_refactor_20260627
|
||||
|
||||
## Overview
|
||||
|
||||
The user-reported `models.py` is a "dumping ground" (1044 lines, 36 classes, 5+ unrelated domains). This track cleans it up PLUS addresses 5 ImGui LEAKS that violate the "ImGui belongs in `gui_2.py`" boundary PLUS unifies 2 vendor files with `ai_client.py`.
|
||||
|
||||
Per the user's principle: **unify unless there's a good reason (import load times, definition pollution)**. No sub-directories. Prefix naming convention.
|
||||
|
||||
## Current State Audit (master `5380b715`, measured 2026-06-27)
|
||||
|
||||
| Metric | Value |
|
||||
|---|---:|
|
||||
| `src/` file count | 65 |
|
||||
| `src/models.py` line count | 1044 |
|
||||
| `src/models.py` class/function count | 36 |
|
||||
| `src/models.py` regions | 13 (Constants, Config Utilities, History Utilities, Pydantic Models, MMA Core, State & Config, Tool Models, UI/Editor, Persona, Workspace, MCP Config, Project Context, ...more) |
|
||||
| ImGui-using files outside `gui_2.py` | 5 (`bg_shader.py`, `shaders.py`, `command_palette.py`, `diff_viewer.py`, `patch_modal.py`) |
|
||||
| Vendor files separate from `ai_client.py` | 2 (`vendor_capabilities.py`, `vendor_state.py`) |
|
||||
| `AGENT_TOOL_NAMES` consumers | 8 (3 in `app_controller.py`, 5 in `tests/test_arch_boundary_phase2.py`) |
|
||||
| `mcp_tool_specs.tool_names()` test | EXISTS (asserts `tool_names() ⊆ AGENT_TOOL_NAMES` — proves it's redundant) |
|
||||
|
||||
## Goals
|
||||
|
||||
| ID | Goal | Acceptance |
|
||||
|---|---|---|
|
||||
| G1 | **MERGE 5 ImGui LEAKS into `gui_2.py`** | `git grep -l "imgui_bundle\|from imgui\\." -- 'src/*.py'` returns ONLY `gui_2.py` + `imgui_scopes.py` |
|
||||
| G2 | **MERGE 2 vendor files into `ai_client.py`** | `ls src/{vendor_capabilities,vendor_state}.py` returns not-found; `python -c "from src.ai_client import ..."` imports the merged symbols |
|
||||
| G3 | **SPLIT `models.py`** into `mma.py` + `project.py` + `project_files.py` | `ls src/mma.py src/project.py src/project_files.py` all exist; `python -c "from src.mma import ThinkingSegment, Ticket, Track, WorkerContext, TrackState"` works |
|
||||
| G4 | **MERGE** 6+ other `models.py` classes into existing sub-system files | `Persona` in `personas.py`; `Tool`/`ToolPreset` in `tool_presets.py`; `BiasProfile` in `tool_bias.py`; `TextEditorConfig`/`ExternalEditorConfig` in `external_editor.py`; `MCPServerConfig`+etc in `mcp_client.py`; `WorkspaceProfile` in `workspace_manager.py` |
|
||||
| G5 | **DELETE `AGENT_TOOL_NAMES`** (redundant with `mcp_tool_specs.tool_names()`) | `git grep "AGENT_TOOL_NAMES" -- 'src/*.py'` returns 0 hits; 8 consumer sites updated to use `list(mcp_tool_specs.tool_names())` |
|
||||
| G6 | **`src/models.py` reduced to ≤30 lines** (or eliminated) | `wc -l src/models.py` returns ≤30 |
|
||||
| G7 | All 7 audit gates pass `--strict` | unchanged from baseline |
|
||||
| G8 | All batched test tiers pass (10/11 baseline + RAG flake) | unchanged from baseline |
|
||||
|
||||
## Non-Goals
|
||||
|
||||
- Renaming existing files for prefix consistency (`multi_agent_conductor.py` → `mma_conductor.py`, etc.) — deferred to follow-up; current names are clear enough
|
||||
- Refactoring `aggregate.py` (513 lines), `app_controller.py` (4869 lines), `gui_2.py` (7773 lines) — out of scope; these have natural boundaries; the user doesn't want more splitting without good reason
|
||||
- Modifications to `mcp_client.py` other than merging the config dataclasses — the merge itself is the change
|
||||
- New `src/<thing>.py` files (per AGENTS.md hard rule) — the 3 new files (`mma.py`, `project.py`, `project_files.py`) are justified by the `models.py` split (definition pollution)
|
||||
|
||||
## Functional Requirements
|
||||
|
||||
### FR1: MERGE ImGui LEAKS into `gui_2.py`
|
||||
|
||||
For each of these 5 files, move the content into `gui_2.py` in a clearly-marked section, then `git rm` the original:
|
||||
|
||||
```python
|
||||
# In gui_2.py, add at the appropriate location:
|
||||
|
||||
#region: Bg Shader (moved from src/bg_shader.py)
|
||||
# ... (content of src/bg_shader.py)
|
||||
#endregion
|
||||
|
||||
#region: Shaders (moved from src/shaders.py)
|
||||
# ... (content of src/shaders.py)
|
||||
#endregion
|
||||
|
||||
#region: Command Palette (moved from src/command_palette.py)
|
||||
# ... (content of src/command_palette.py)
|
||||
#endregion
|
||||
|
||||
#region: Diff Viewer (moved from src/diff_viewer.py)
|
||||
# ... (content of src/diff_viewer.py)
|
||||
#endregion
|
||||
|
||||
#region: Patch Modal (moved from src/patch_modal.py)
|
||||
# ... (content of src/patch_modal.py)
|
||||
#endregion
|
||||
```
|
||||
|
||||
**Imports to update across the codebase:**
|
||||
- `from src.bg_shader import X` → `from src.gui_2 import X`
|
||||
- `from src.shaders import X` → `from src.gui_2 import X`
|
||||
- (etc. for all 5 files)
|
||||
|
||||
### FR2: MERGE vendor files into `ai_client.py`
|
||||
|
||||
```python
|
||||
# In ai_client.py, add at the appropriate location:
|
||||
|
||||
#region: Vendor Capabilities (moved from src/vendor_capabilities.py)
|
||||
# ... (content of src/vendor_capabilities.py)
|
||||
#endregion
|
||||
|
||||
#region: Vendor State (moved from src/vendor_state.py)
|
||||
# ... (content of src/vendor_state.py)
|
||||
#endregion
|
||||
```
|
||||
|
||||
**Imports to update:**
|
||||
- `from src.vendor_capabilities import X` → `from src.ai_client import X`
|
||||
- `from src.vendor_state import X` → `from src.ai_client import X`
|
||||
|
||||
### FR3: SPLIT `models.py`
|
||||
|
||||
**Phase 1: Create `src/mma.py`** with the MMA Core + TrackState:
|
||||
- ThinkingSegment
|
||||
- Ticket
|
||||
- Track
|
||||
- WorkerContext
|
||||
- TrackState
|
||||
- Top-level docstring explaining MMA scope
|
||||
|
||||
**Phase 2: Create `src/project.py`** with the project config:
|
||||
- ProjectContext + 5 sub-dataclasses (ProjectMeta, ProjectOutput, ProjectFiles, ProjectScreenshots, ProjectDiscussion)
|
||||
- Config I/O helpers: `_clean_nones`, `load_config_from_disk`, `save_config_to_disk`, `parse_history_entries`
|
||||
- Top-level docstring explaining project config scope
|
||||
|
||||
**Phase 3: Create `src/project_files.py`** with the file-related dataclasses:
|
||||
- FileItem
|
||||
- ContextPreset
|
||||
- ContextFileEntry
|
||||
- NamedViewPreset
|
||||
- Preset
|
||||
- Top-level docstring explaining file-related project state scope
|
||||
|
||||
### FR4: MERGE other `models.py` classes into existing sub-system files
|
||||
|
||||
| Class from `models.py` | Destination (existing file) | New section name |
|
||||
|---|---|---|
|
||||
| `Persona` | `src/personas.py` | "Persona Dataclass" |
|
||||
| `Tool`, `ToolPreset` | `src/tool_presets.py` | "Tool + ToolPreset Dataclasses" |
|
||||
| `BiasProfile` | `src/tool_bias.py` | "BiasProfile Dataclass" |
|
||||
| `TextEditorConfig`, `ExternalEditorConfig` | `src/external_editor.py` | "Editor Config Dataclasses" |
|
||||
| `MCPServerConfig`, `MCPConfiguration`, `VectorStoreConfig`, `RAGConfig`, `load_mcp_config` | `src/mcp_client.py` | "MCP Config Dataclasses" |
|
||||
| `WorkspaceProfile` | `src/workspace_manager.py` | "WorkspaceProfile Dataclass" |
|
||||
|
||||
### FR5: DELETE `AGENT_TOOL_NAMES` (redundant)
|
||||
|
||||
```python
|
||||
# 8 consumer site updates:
|
||||
# Before:
|
||||
from src.models import AGENT_TOOL_NAMES
|
||||
for tool in AGENT_TOOL_NAMES:
|
||||
...
|
||||
|
||||
# After:
|
||||
from src import mcp_tool_specs
|
||||
for tool in mcp_tool_specs.tool_names():
|
||||
...
|
||||
```
|
||||
|
||||
**Consumer sites (8):**
|
||||
- `src/app_controller.py:2110, 2972, 3273` (3 sites)
|
||||
- `tests/test_arch_boundary_phase2.py:23, 29, 31, 32, 33` (5 sites)
|
||||
|
||||
**Test simplification:** `test_tool_names_subset_of_models_agent_tool_names` becomes either:
|
||||
- DELETE (it's a tautology once `AGENT_TOOL_NAMES` is derived from `tool_names()`)
|
||||
- OR convert to a positive assertion: `assert mcp_tool_specs.tool_names() == {expected canonical tools}`
|
||||
|
||||
### FR6: REDUCE `src/models.py` to ~30 lines (or eliminate)
|
||||
|
||||
After all moves, `src/models.py` contains:
|
||||
- `_create_generate_request`, `_create_confirm_request`, `__getattr__` (Pydantic lazy proxies for the API)
|
||||
- OR these move to `src/api_hooks.py` (if API-specific)
|
||||
- Top-level docstring
|
||||
|
||||
If `models.py` becomes essentially empty after these moves, **delete the file entirely** (it's not a "system" file; `models.py` is just a temporary holder).
|
||||
|
||||
## Non-Functional Requirements
|
||||
|
||||
- NFR1: 1-space indentation (per `conductor/workflow.md`)
|
||||
- NFR2: CRLF line endings on Windows
|
||||
- NFR3: No comments in source code (per AGENTS.md "No comments in source code")
|
||||
- NFR4: Per-task atomic commits with git notes
|
||||
- NFR5: No new pip dependencies
|
||||
- NFR6: `Result[T]` returns for fallible fns (per `error_handling.md`)
|
||||
- NFR7: No new `src/<thing>.py` files UNLESS justified by definition pollution (per AGENTS.md hard rule)
|
||||
|
||||
## Architecture Reference
|
||||
|
||||
- `AGENTS.md` — "File Size and Naming Convention" HARD RULE
|
||||
- `conductor/code_styleguides/data_oriented_design.md` — "Prefer Fewer Types" principle
|
||||
- `conductor/code_styleguides/error_handling.md` — the `Result[T]` convention
|
||||
- `conductor/code_styleguides/type_aliases.md` — the 10 TypeAliases convention
|
||||
- `conductor/tracks/cruft_elimination_20260627/SPEC_CORRECTION_phase_2.md` — the related spec correction (the original Phase 2 spec was wrong to put ProjectContext in `models.py`; this track fixes that)
|
||||
- `docs/reports/FOLLOWUP_module_taxonomy_20260627.md` — the previous followup report (this track supersedes it with concrete execution)
|
||||
|
||||
## Out of Scope
|
||||
|
||||
- Renaming existing files for prefix consistency (`multi_agent_conductor.py` → `mma_conductor.py`, etc.) — deferred to follow-up
|
||||
- Refactoring `aggregate.py` (513 lines), `app_controller.py` (4869 lines), `gui_2.py` (7773 lines) — out of scope; these have natural boundaries
|
||||
- Modifications to `mcp_client.py` other than merging the config dataclasses
|
||||
- New `src/<thing>.py` files beyond the 3 justified ones (`mma.py`, `project.py`, `project_files.py`)
|
||||
- The RAG test pre-existing flake (per `docs/reports/SSDL_CAMPAIGN_ABORTED_20260624.md` "Out of Scope")
|
||||
- Any Tier 2 spec rewrites (per the user's earlier "don't fuck with commits" directive)
|
||||
|
||||
## Verification Criteria (Definition of Done)
|
||||
|
||||
| # | Criterion | Verification |
|
||||
|---|---|---|
|
||||
| VC1 | ImGui imports limited to `gui_2.py` + `imgui_scopes.py` | `git grep -l "imgui_bundle\|from imgui\\." -- 'src/*.py'` returns 2 files |
|
||||
| VC2 | `src/bg_shader.py`, `src/shaders.py`, `src/command_palette.py`, `src/diff_viewer.py`, `src/patch_modal.py` deleted | `ls src/{bg_shader,shaders,command_palette,diff_viewer,patch_modal}.py` returns not-found |
|
||||
| VC3 | `src/vendor_capabilities.py`, `src/vendor_state.py` deleted | `ls src/{vendor_capabilities,vendor_state}.py` returns not-found |
|
||||
| VC4 | Vendor symbols importable from `src.ai_client` | `python -c "from src.ai_client import PROVIDER_CAPABILITIES, get_vendor_state"` works |
|
||||
| VC5 | `src/mma.py` exists with MMA Core + TrackState | `python -c "from src.mma import ThinkingSegment, Ticket, Track, WorkerContext, TrackState"` works |
|
||||
| VC6 | `src/project.py` exists with ProjectContext + sub + config I/O | `python -c "from src.project import ProjectContext, ProjectMeta, ProjectOutput, ProjectFiles, ProjectScreenshots, ProjectDiscussion, _clean_nones, load_config_from_disk, save_config_to_disk, parse_history_entries"` works |
|
||||
| VC7 | `src/project_files.py` exists with file-related dataclasses | `python -c "from src.project_files import FileItem, ContextPreset, ContextFileEntry, NamedViewPreset, Preset"` works |
|
||||
| VC8 | Persona/Tool/Editor/MCP/Workspace dataclasses in their proper sub-system files | `python -c "from src.personas import Persona; from src.tool_presets import Tool, ToolPreset; from src.tool_bias import BiasProfile; from src.external_editor import TextEditorConfig, ExternalEditorConfig; from src.mcp_client import MCPServerConfig, MCPConfiguration, VectorStoreConfig, RAGConfig, load_mcp_config; from src.workspace_manager import WorkspaceProfile"` works |
|
||||
| VC9 | `AGENT_TOOL_NAMES` deleted; all 8 consumer sites use `mcp_tool_specs.tool_names()` | `git grep "AGENT_TOOL_NAMES" -- 'src/*.py' 'tests/*.py'` returns 0 hits |
|
||||
| VC10 | `src/models.py` reduced to ≤30 lines (or eliminated entirely) | `wc -l src/models.py` returns ≤30; OR `ls src/models.py` returns not-found |
|
||||
| VC11 | All 7 audit gates pass `--strict` | unchanged from baseline |
|
||||
| VC12 | 10/11 batched test tiers pass (RAG flake acceptable) | unchanged from baseline |
|
||||
|
||||
## Risks
|
||||
|
||||
| # | Risk | Likelihood | Mitigation |
|
||||
|---|---|---|---|
|
||||
| R1 | ImGui LEAKS move breaks existing tests (e.g., `command_palette` is referenced in commands.py) | low | Run full affected test set after each move; revert + fix on regression |
|
||||
| R2 | Vendor merge into `ai_client.py` creates circular imports (PROVIDERS lazy proxy is the workaround) | medium | The lazy import pattern (`__getattr__`) handles this; verify by running the full test suite after merge |
|
||||
| R3 | `models.py` split breaks 136 import sites | high | Per-file move with regression-guard tests after each; update imports systematically |
|
||||
| R4 | The 6+ "merge into existing sub-system files" moves break those files' existing tests | medium | Run the affected test file after each merge |
|
||||
| R5 | `AGENT_TOOL_NAMES` deletion breaks `test_arch_boundary_phase2.py` | low | Update the test to use `mcp_tool_specs.tool_names()`; cross-check that the test's expected tool names are in the registry |
|
||||
| R6 | The `ProjectContext` Phase 2 commit (in `cruft_elimination_20260627`) put `ProjectContext` in `models.py`; the new track moves it to `project.py` — needs to coordinate with the cruft track | high | The cruft track should NOT merge its `models.py` `ProjectContext` commit; this refactor track handles the move |
|
||||
| R7 | The `_create_generate_request` etc. Pydantic proxies in `models.py` are used by `api_hooks.py`; if we move them to `api_hooks.py` we create a different topology | low | Audit the consumers; if they're all in `api_hooks.py`, move them; if not, keep in `models.py` or move to a new `api_models.py` |
|
||||
|
||||
## See also
|
||||
|
||||
- `docs/reports/FOLLOWUP_module_taxonomy_20260627.md` — the previous followup report (this spec supersedes it)
|
||||
- `conductor/tracks/cruft_elimination_20260627/SPEC_CORRECTION_phase_2.md` — the related spec correction
|
||||
- `conductor/tracks/cruft_elimination_20260627/spec.md` — the parent spec (which is currently in flux)
|
||||
- `AGENTS.md` — "File Size and Naming Convention" HARD RULE
|
||||
- `conductor/code_styleguides/data_oriented_design.md` — "Prefer Fewer Types" principle
|
||||
@@ -0,0 +1,62 @@
|
||||
# Track state for module_taxonomy_refactor_20260627
|
||||
# Updated by Tier 2 Tech Lead as tasks complete
|
||||
|
||||
[meta]
|
||||
track_id = "module_taxonomy_refactor_20260627"
|
||||
name = "Module Taxonomy Refactor"
|
||||
status = "active"
|
||||
current_phase = 0
|
||||
last_updated = "2026-06-27"
|
||||
|
||||
[blocked_by]
|
||||
cruft_elimination_20260627 = "pending (the cruft track has a ProjectContext-in-models.py commit that needs to be coordinated)"
|
||||
|
||||
[blocks]
|
||||
|
||||
[phases]
|
||||
phase_0 = { status = "pending", checkpointsha = "", name = "Pre-flight + TIER2_STARTUP" }
|
||||
phase_1 = { status = "pending", checkpointsha = "", name = "MERGE ImGui LEAKS into gui_2.py (5 commits)" }
|
||||
phase_2 = { status = "pending", checkpointsha = "", name = "MERGE vendor files into ai_client.py (2 commits)" }
|
||||
phase_3 = { status = "pending", checkpointsha = "", name = "SPLIT models.py into mma.py + project.py + project_files.py + 6 sub-system merges (10 commits)" }
|
||||
phase_4 = { status = "pending", checkpointsha = "", name = "DELETE AGENT_TOOL_NAMES (1 commit)" }
|
||||
phase_5 = { status = "pending", checkpointsha = "", name = "Verification + end-of-track report" }
|
||||
|
||||
[tasks]
|
||||
t0_1 = { status = "pending", commit_sha = "", description = "Create TIER2_STARTUP.md with decision rule + 3 refactors + 8 AGENT_TOOL_NAMES consumers" }
|
||||
t1_1 = { status = "pending", commit_sha = "", description = "Move src/bg_shader.py to src/gui_2.py" }
|
||||
t1_2 = { status = "pending", commit_sha = "", description = "Move src/shaders.py to src/gui_2.py" }
|
||||
t1_3 = { status = "pending", commit_sha = "", description = "Move src/command_palette.py to src/gui_2.py" }
|
||||
t1_4 = { status = "pending", commit_sha = "", description = "Move src/diff_viewer.py to src/gui_2.py" }
|
||||
t1_5 = { status = "pending", commit_sha = "", description = "Move src/patch_modal.py to src/gui_2.py" }
|
||||
t2_1 = { status = "pending", commit_sha = "", description = "Move src/vendor_capabilities.py to src/ai_client.py" }
|
||||
t2_2 = { status = "pending", commit_sha = "", description = "Move src/vendor_state.py to src/ai_client.py" }
|
||||
t3_1 = { status = "pending", commit_sha = "", description = "Create src/mma.py with MMA Core + TrackState (split from models.py)" }
|
||||
t3_2 = { status = "pending", commit_sha = "", description = "Create src/project.py with ProjectContext + sub + config IO (split from models.py)" }
|
||||
t3_3 = { status = "pending", commit_sha = "", description = "Create src/project_files.py (split from models.py)" }
|
||||
t3_4 = { status = "pending", commit_sha = "", description = "Move Persona from models.py to personas.py" }
|
||||
t3_5 = { status = "pending", commit_sha = "", description = "Move Tool + ToolPreset from models.py to tool_presets.py" }
|
||||
t3_6 = { status = "pending", commit_sha = "", description = "Move BiasProfile from models.py to tool_bias.py" }
|
||||
t3_7 = { status = "pending", commit_sha = "", description = "Move TextEditorConfig + ExternalEditorConfig from models.py to external_editor.py" }
|
||||
t3_8 = { status = "pending", commit_sha = "", description = "Move MCP config dataclasses from models.py to mcp_client.py" }
|
||||
t3_9 = { status = "pending", commit_sha = "", description = "Move WorkspaceProfile from models.py to workspace_manager.py" }
|
||||
t3_10 = { status = "pending", commit_sha = "", description = "Reduce models.py to Pydantic proxy helpers only (or delete entirely if empty)" }
|
||||
t4_1 = { status = "pending", commit_sha = "", description = "Update 8 consumer sites to use mcp_tool_specs.tool_names() instead of AGENT_TOOL_NAMES" }
|
||||
t4_2 = { status = "pending", commit_sha = "", description = "Delete AGENT_TOOL_NAMES constant from src/models.py" }
|
||||
t4_3 = { status = "pending", commit_sha = "", description = "DELETE or CONVERT test_tool_names_subset_of_models_agent_tool_names test" }
|
||||
t5_1 = { status = "pending", commit_sha = "", description = "Run all 12 VCs; write TRACK_COMPLETION; update state.toml + tracks.md" }
|
||||
|
||||
[verification]
|
||||
phase_0_complete = false
|
||||
phase_1_complete = false
|
||||
phase_2_complete = false
|
||||
phase_3_complete = false
|
||||
phase_4_complete = false
|
||||
phase_5_complete = false
|
||||
|
||||
[track_specific]
|
||||
file_change_summary = { files_deleted = 7, files_created = 4, files_modified = 10, potentially_deleted = 1 }
|
||||
net_files_change = "-4 files (65 -> 61, with potential additional -1 if models.py is eliminated)"
|
||||
im_gui_leak_count = 5
|
||||
vendor_files_to_merge = 2
|
||||
models_py_split_targets = 3
|
||||
agent_tool_names_consumers = 8
|
||||
Reference in New Issue
Block a user