Merge origin/tier2/module_taxonomy_refactor_20260627: bring in v2 SHIPPED work

Per post_module_taxonomy_de_cruft_20260627 Phase 0 prerequisite.
Master is at 6344b49f (pre-merge of v2 SHIPPED). This merge brings in
the 18 v2 SHIPPED commits that define the destination modules
(src.mma, src/project.py, src/project_files.py, src.tool_presets,
src.tool_bias, src.external_editor, src.personas,
src.workspace_manager, src.mcp_client) needed by the Phase 2
consumer migration in commit 8f11340b.

Conflicts resolved (all were import-block re-orderings between my
migration's update and v2 SHIPPED's update of the same files):
 - src/external_editor.py: took v2 SHIPPED version (class definitions
                                    + the no-alias import pattern)
 - src/personas.py: took v2 SHIPPED version
 - src/tool_bias.py: took v2 SHIPPED version
 - src/tool_presets.py: took v2 SHIPPED version
 - src/workspace_manager.py: took v2 SHIPPED version
 - src/ai_client.py: took v2 SHIPPED version (removes the 'as _FIC'
                              alias; uses 'from src.project_files import
                              FileItem' directly per the v2 SHIPPED style)
 - conductor/tracks/module_taxonomy_refactor_20260627/spec.md: took
                              HEAD version (my Phase 1 VC2 + VC10
                              corrections; the v2 SHIPPED version was
                              the pre-correction spec)
This commit is contained in:
ed
2026-06-26 13:51:05 -04:00
65 changed files with 4959 additions and 2463 deletions
@@ -1,144 +1,99 @@
# Tier 2 Startup Brief: module_taxonomy_refactor_20260627
# Tier 2 Startup Brief: module_taxonomy_refactor_20260627 (v2)
## 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.
This is the v2 of the track. v1 had gaps that gave Tier 2 discretion (Tier 2 made inconsistent decisions). **v2 is prescriptive — Tier 2 has ZERO discretion.** Every move is pre-decided in the spec.
The user explicitly stated: "I want to be more careful with how we are organizing things into which file. We can't let tier 2 have full discretion on this. Some stuff deserves to be in a dedicated file, many do not."
## MANDATORY Pre-Action Reading (per agent protocol)
1. `AGENTS.md` (project root) — operating rules, especially "File Size and Naming Convention" HARD RULE
1. `AGENTS.md` — 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)
5. `conductor/code_styleguides/error_handling.md` — the `Result[T]` convention
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)
8. `conductor/tracks/module_taxonomy_refactor_20260627/spec.md`**THE v2 SPEC** (read this end-to-end; it defines the 4-criteria rule and the data/view/ops split)
9. `conductor/tracks/module_taxonomy_refactor_20260627/plan.md` — the v2 plan (16 atomic commits)
10. `docs/reports/FOLLOWUP_module_taxonomy_refactor_20260627_recoverable.md` — the recovery report (data is NOT lost)
**First commit of this track must include** `TIER-2 READ <list> before module_taxonomy_refactor_20260627` in the message.
**First commit of this track must include** `TIER-2 READ <list> before module_taxonomy_refactor_20260627 v2` in the message.
## The Decision Rule (the user's principle)
## THE 4-CRITERIA DECISION RULE (the taxonomy law)
**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
Every class in `src/models.py` must satisfy at least 1 of these criteria to be SPLIT into its own dedicated file:
**Otherwise: keep in a single file.** Move imports around, but don't fragment.
| # | Criterion | Threshold |
|---|---|---|
| **C1** | Cross-system usage | Consumed by ≥ 3 unrelated systems |
| **C2** | State machine / lifecycle | Has state machine, lifecycle methods, or business logic |
| **C3** | Test file already exists | Has its own dedicated `tests/test_*.py` |
| **C4** | Substantial size | Class body > 30 lines OR class has > 5 fields |
**No sub-directories.** All files at `src/` flat with prefix naming.
**Apply the rule:**
- If C1 OR C2 OR C3 is TRUE → **DEDICATED FILE** (new `src/<name>.py` or merged into existing)
- If NONE of C1, C2, C3 is TRUE but C4 is TRUE → **MERGE INTO DESTINATION** (existing `src/<name>.py`)
- If NONE of C1, C2, C3, C4 is TRUE → **KEEP in `src/models.py`** (deferred to a follow-up; not worth a move)
## The 3 Refactors (only 3 justified)
**C4 is the LAST criterion.** A class that fails C1, C2, C3 but passes C4 is "big enough to be in its own file" but not important enough to be the main file. Merge it into a logical destination.
### Refactor 1: MERGE 5 ImGui LEAKS into `gui_2.py`
## THE DATA/VIEW/OPS SPLIT (the GUI boundary)
**Justification:** User explicit directive: "all ImGui rendering should be in `gui_2.py`. Only exception: `imgui_scopes.py`." Clear violation of the GUI boundary.
**Rule (already established by the user, formalized here):**
- **data** = dataclasses, registries, business logic, persistence — goes in `src/<system>.py`
- **view** = ImGui rendering, draw calls, widget setup — goes in `src/gui_2.py` (or `src/<system>_view.py` if gui_2 is too big)
- **ops** = operations on data (apply_patch, parse_diff, execute_command) — goes in the destination file with the data, NOT in gui_2
| 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` |
**Exceptions to this rule:**
- `imgui_scopes.py` is the EXCEPTION (per the user). It contains Python `with` context managers for ImGui scopes. It's the glue between data and view; keeping it separate avoids circular imports.
- Anything that needs to be in `gui_2.py` to avoid cycles goes in `gui_2.py`.
**Verification:** `git grep -l "imgui_bundle\|from imgui\\." -- 'src/*.py'` returns ONLY `gui_2.py` + `imgui_scopes.py`.
## TIMELINE-IS-IMMUTABLE PRINCIPLE (added 2026-06-27 per user feedback)
### Refactor 2: MERGE 2 vendor files into `ai_client.py`
When you (the agent) fuck up — make a wrong commit, break a file, take a bad path — your first instinct will be to "undo" the mistake with `git revert`, `git reset`, or `git stash`. **THIS INSTINCT IS WRONG.** The user explicitly stated: "if an agent fucks up, their tendency to want to 'revert' is not correct and instead they must live with the timeline and just do corrections with a new commit."
**Justification:** User explicit directive: "vendor_capabilities.py and vendor_state.py are related to ai_client.py... they're the ai vendoring layer."
**The rule:**
- The git history is IMMUTABLE on this branch. Every commit you've made is part of the record.
- "Fixing forward" via a new commit makes the user's review EASIER.
- "Undoing" via `git revert` / `git reset` / `git stash` makes the user's review HARDER (they have to read the diff between the bad and the "fix" to understand what went wrong).
| 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` |
**Correct pattern when you fuck up:**
1. Pause. Read the actual file. Confirm the state.
2. Write a NEW commit that fixes the problem. The commit message should briefly say what was wrong and what you fixed.
3. If the bad commit introduced data corruption that the user will see, the user can `git revert` it during their review — that's the user's choice, not yours.
4. If you need to recover an old version of a file, use `git show <good-sha>:<path> > <path>` to extract it.
**Growth:** `ai_client.py` 3147 → ~3310 lines. Justified: unified vendor layer, no fragmentation.
**Wrong pattern (which you must NOT do):**
- `git revert <sha>` to undo a commit
- `git reset --hard <sha>` to throw away a bad commit
- `git stash` to "save" uncommitted work
- `git checkout <old-sha> -- .` to "go back to when things were good" (and then commit on top)
### Refactor 3: SPLIT `models.py` (the only justified split)
These are all attempts to rewrite history. They are BANNED. The right answer is always a forward commit.
**Justification:** 5+ unrelated domains, 36 classes, 1044 lines. **Clear definition pollution** (the user's threshold: "3+ unrelated domains with 30+ classes").
## HARD BAN: `git stash*` (added 2026-06-27)
**The new taxonomy:**
`git stash`, `git stash pop`, `git stash apply`, `git stash drop`, `git stash clear` are FORBIDDEN at 3 layers:
1. `AGENTS.md` HARD BAN
2. `conductor/tier2/opencode.json.fragment` bash deny rules (top-level + agent-level)
3. This prompt's Hard Bans list
| 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.
Stashing throws away the user's in-progress edits silently. If you think you need a stash, you don't — use a NEW BRANCH or a WORKTREE instead.
## Pre-flight verification
```bash
# Verify the current state of src/
ls src/*.py | wc -l
# Expect: 65
ls src/*.py | Measure-Object -Line | Select-Object -ExpandProperty Lines
# Expect: ~61 files (after deletions from Phase 1+2)
# Verify models.py is 1044 lines
wc -l src/models.py
Measure-Object -Line on 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)
# Verify 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
@@ -147,36 +102,60 @@ uv run python scripts/audit_code_path_audit_coverage.py --input-dir docs/reports
uv run python scripts/audit_exception_handling.py --strict
uv run python scripts/audit_optional_in_3_files.py --strict
# All exit 0
# Verify ImGui LEAKS are gone (Phase 1)
git grep -l "imgui_bundle\|from imgui\\." HEAD -- 'src/*.py'
# Expect: gui_2.py, imgui_scopes.py
# Verify vendor files are gone (Phase 2)
ls src/vendor_capabilities.py src/vendor_state.py 2>&1 | Select-String "No such"
# Expect: both not found
# Verify the 11 classes are intact in models.py (data is preserved, not lost)
git show HEAD:src/models.py | Select-String "^class (Tool|ToolPreset|BiasProfile|TextEditorConfig|ExternalEditorConfig|MCPServerConfig|MCPConfiguration|VectorStoreConfig|RAGConfig|WorkspaceProfile|Persona|FileItem|Preset|ContextPreset|ContextFileEntry|NamedViewPreset)\b"
# Expect: all 16 classes listed
```
## Post-track verification (after Phase 5)
## Post-track verification (after Phase 6)
```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)
# VC2: 5 ImGui LEAK files deleted
ls src/bg_shader.py src/shaders.py src/command_palette.py src/diff_viewer.py src/patch_modal.py 2>&1 | Select-String "No such"
# Expect: all 5 not found
# VC5-7: New files work
uv run python -c "from src.mma import ThinkingSegment, Ticket, Track, WorkerContext, TrackState"
# VC3: 2 vendor files deleted
ls src/vendor_capabilities.py src/vendor_state.py 2>&1 | Select-String "No such"
# Expect: both not found
# VC5-7: New files exist with correct content
uv run python -c "from src.mma import ThinkingSegment, Ticket, Track, WorkerContext, TrackState, TrackMetadata"
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"
uv run python -c "from src.project_files import FileItem, Preset, ContextPreset, ContextFileEntry, NamedViewPreset"
# 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
# VC8: 11 classes in proper sub-system files
uv run python -c "from src.tool_presets import Tool, ToolPreset; from src.tool_bias import BiasProfile; from src.external_editor import TextEditorConfig, ExternalEditorConfig; from src.personas import Persona; from src.workspace_manager import WorkspaceProfile; from src.mcp_client import MCPServerConfig, MCPConfiguration, VectorStoreConfig, RAGConfig, load_mcp_config"
# All succeed
# VC9: AGENT_TOOL_NAMES deleted
git grep "AGENT_TOOL_NAMES" HEAD -- 'src/*.py' 'tests/*.py' | wc -l
git grep "AGENT_TOOL_NAMES" HEAD -- 'src/*.py' 'tests/*.py' | Measure-Object -Line | Select-Object -ExpandProperty Lines
# Expect: 0
# VC10: models.py reduced or eliminated
ls src/models.py 2>&1
# Expect: file not found (or <= 30 lines if kept)
# VC10: models.py reduced
Measure-Object -Line on src/models.py
# Expect: <= 30
# VC13: 4-criteria rule documented
Select-String -Path conductor/tracks/module_taxonomy_refactor_20260627/spec.md -Pattern "4-criteria"
# Expect: hits
# VC14: data/view/ops split documented
Select-String -Path conductor/tracks/module_taxonomy_refactor_20260627/spec.md -Pattern "data/view/ops"
# Expect: hits
# VC11-12: audit gates + batched suite
# Same as current baseline
@@ -184,73 +163,99 @@ ls src/models.py 2>&1
## 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
### Pattern: create new file (Phase 3a, 3b, 3c)
```bash
# 1. Read source file
cat src/bg_shader.py
# 1. Read source from models.py
git show HEAD:src/models.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
# 2. Write new file
manual-slop_edit_file src/mma.py # or src/project.py or src/project_files.py
# Copy class definitions from models.py, add proper imports + docstring
# 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
git grep "from src.models import.*(Ticket|Track|WorkerContext|TrackState|TrackMetadata|ThinkingSegment)" -- 'src/*.py' 'tests/*.py'
# Replace each with: from src.mma import ...
# 4. Delete source file
git rm src/bg_shader.py
# 4. Add backward-compat re-export in models.py
# KEEP `from src.mma import Ticket, Track, ...` in models.py for consumers still using the old path
# 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
```
### Pattern: merge into existing file (Phase 3d, 3e, 3f, 3g, 3h, 3i)
```bash
# 1. Read source from models.py
git show HEAD:src/models.py | Select-String "^class Tool\b" -Context 0,2
# 2. Add to destination file
manual-slop_edit_file src/tool_presets.py
# Add the Tool + ToolPreset class definitions at the top (or in a clearly-marked section)
# 3. Add backward-compat re-export in models.py
manual-slop_edit_file src/models.py
# After the existing class definitions, add: from src.tool_presets import Tool, ToolPreset
# 4. Verify
uv run python -m pytest tests/test_tool_presets_*.py tests/test_bias_models.py -v
```
### Pattern: delete + update (Phase 4)
```bash
# 1. Read source from models.py to find AGENT_TOOL_NAMES
git show HEAD:src/models.py | Select-String "AGENT_TOOL_NAMES" -Context 0,2
# 2. Find all consumer sites
git grep "models.AGENT_TOOL_NAMES\|from src.models import.*AGENT_TOOL_NAMES" -- 'src/*.py' 'tests/*.py'
# Expect: 8 sites (3 in app_controller.py + 5 in test_arch_boundary_phase2.py)
# 3. Update each site
manual-slop_edit_file src/app_controller.py
# Replace `models.AGENT_TOOL_NAMES` with `mcp_tool_specs.tool_names()`
# Add import: from src import mcp_tool_specs
# 4. Delete from models.py
manual-slop_edit_file src/models.py
# Remove the AGENT_TOOL_NAMES constant definition
# 5. Verify
uv run python -m pytest tests/test_arch_boundary_phase2.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
- Preserve backward-compat: when removing a class from `models.py`, KEEP a `from src.<destination> import <class>` re-export line in `models.py`
## 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).
- **The v2 track is prescriptive.** Tier 2 has ZERO discretion. Every move is pre-decided in the spec.
- **Phase 0 is a state reset only** — no code changes. The 5 "damaged" tasks become "pending" with a note explaining the data is intact.
- **Phase 1 + 2 are DONE** — verify only.
- **Phase 3 is the main work** — 9 commits (3a, 3b, 3c, 3d, 3e, 3f, 3g, 3h, 3i). Each commit is one of: create new file (3a, 3b, 3c) or merge into existing file (3d, 3e, 3f, 3g, 3h, 3i).
- **Phase 4 deletes `AGENT_TOOL_NAMES`** — 1 commit, 8 consumer site updates.
- **Phase 5 reduces `src/models.py`** — 1 commit.
- **Phase 6 is verification** — 3 commits, no code changes.
- **Total: 16 atomic commits** (down from v1's 22 because the tier 2 work is now prescriptive).
- **Tier 2 must NOT use `git stash*` for any reason.** Banned at 3 layers.
- **Tier 2 must NOT use `git revert*` / `git reset*` for any reason.** Banned per AGENTS.md. Use forward commits instead.
## 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/spec.md` — the v2 spec (the canonical reference for this plan)
- `conductor/tracks/module_taxonomy_refactor_20260627/plan.md` — the v2 plan (16 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
- `docs/reports/FOLLOWUP_module_taxonomy_refactor_20260627_recoverable.md` — the recovery report (data is NOT lost)
- `docs/reports/FOLLOWUP_module_taxonomy_refactor_20260627.md` — the original taxonomy audit
- `docs/reports/TRACK_ABORTED_module_taxonomy_refactor_20260627.md` — the previous (incorrect) damage report
- `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
@@ -1,9 +1,11 @@
{
"track_id": "module_taxonomy_refactor_20260627",
"name": "Module Taxonomy Refactor",
"name": "Module Taxonomy Refactor v2",
"version": "v2",
"status": "active",
"type": "cleanup",
"date_created": "2026-06-27",
"v2_date": "2026-06-27",
"created_by": "tier1-orchestrator",
"blocks": [],
"blocked_by": {
@@ -41,38 +43,58 @@
"src/models.py"
]
},
"taxonomy_law": {
"name": "4-criteria decision rule",
"description": "Every class in src/models.py must satisfy at least 1 of these criteria to be SPLIT into its own dedicated file",
"criteria": {
"C1": "Cross-system usage (consumed by >= 3 unrelated systems)",
"C2": "State machine / lifecycle (has state transitions or business logic)",
"C3": "Test file already exists (tests/test_<name>.py)",
"C4": "Substantial size (class body > 30 lines OR class has > 5 fields)"
},
"decision_rule": "If C1 OR C2 OR C3 is TRUE -> DEDICATED FILE (new or merged into existing); If NONE of C1, C2, C3 but C4 -> MERGE INTO DESTINATION; If NONE of C1, C2, C3, C4 -> KEEP in models.py (deferred to follow-up)"
},
"data_view_ops_split": {
"description": "Dataclasses go in data files; rendering code goes in gui_2.py (or subsystem_view.py); operations go with the data",
"exceptions": ["imgui_scopes.py is the EXCEPTION (Python `with` context managers for ImGui scopes)"],
"enforcement": "scripts/audit_gui2_boundaries.py (TODO: add if not exist) greps for imgui. in non-GUI files"
},
"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)"
"VC1: ImGui imports limited to gui_2.py + imgui_scopes.py",
"VC2: 5 ImGui LEAK files deleted (bg_shader, shaders, command_palette, diff_viewer, patch_modal)",
"VC3: 2 vendor files deleted (vendor_capabilities, vendor_state)",
"VC4: Vendor symbols importable from src.ai_client",
"VC5: src/mma.py exists with MMA Core (Ticket, Track, WorkerContext, TrackState, TrackMetadata, ThinkingSegment)",
"VC6: src/project.py exists with ProjectContext + 5 sub + config IO",
"VC7: src/project_files.py exists with file-related dataclasses (FileItem, Preset, ContextPreset, ContextFileEntry, NamedViewPreset)",
"VC8: 11 classes merged into 6 existing sub-system files (Tool+ToolPreset in tool_presets, BiasProfile in tool_bias, TextEditorConfig+ExternalEditorConfig in external_editor, Persona in personas, WorkspaceProfile in workspace_manager, 4 MCP classes + load_mcp_config in mcp_client)",
"VC9: AGENT_TOOL_NAMES deleted; 8 consumer sites use mcp_tool_specs.tool_names()",
"VC10: src/models.py reduced to <=30 lines (Pydantic proxies + DEFAULT_TOOL_CATEGORIES only)",
"VC11: All 7 audit gates pass --strict (no regression)",
"VC12: 10/11 batched test tiers pass (RAG flake acceptable)",
"VC13: The 4-criteria decision rule is documented in this spec (verify via grep)",
"VC14: The data/view/ops split is documented in this spec (verify via grep)"
],
"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"
"scope": "1 source file (src/models.py) split into 3 new files (mma.py, project.py, project_files.py) + 11 classes merged into 6 existing sub-system files + 1 deletion (AGENT_TOOL_NAMES) + models.py reduced from 1044 to ~30 lines; 16 atomic commits total (reduced from v1's 22 because the tier 2 work is now prescriptive)"
},
"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",
"R1 (low): ImGui LEAKS move breaks existing tests - mitigated by running full affected test set after each move",
"R2 (medium): Vendor merge into ai_client.py creates circular imports - 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"
"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()",
"R6 (medium): __getattr__ in models.py becomes unused after split - mitigated by audit during execution; if unused, remove it",
"R7 (medium): The _create_generate_request etc. Pydantic proxies in models.py are still needed by api_hooks.py - mitigated by keeping them in models.py (out of scope for v2)"
],
"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)",
"Moving Pydantic proxies from models.py to api_hooks.py (separate track)",
"Any Tier 2 spec rewrites (per the user's earlier 'don't fuck with commits' directive)"
]
],
"v2_changes_from_v1": "v2 adds: (1) 4-criteria decision rule (C1=systems, C2=state machine, C3=test file, C4=size) for split vs merge; (2) data/view/ops split formalization; (3) explicit ban on Tier 2 discretion (v1 had gaps that gave Tier 2 room to make inconsistent decisions); (4) VC13 + VC14 (verify the 4-criteria rule and data/view/ops split are documented). v2 reduces commit count from 22 to 16 because tier 2 work is now prescriptive."
}
@@ -1,194 +1,267 @@
# Plan: module_taxonomy_refactor_20260627
# Plan v2: 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.
8 phases, 14 tasks, 16 atomic commits (post v2 corrections). Per-task TDD red-first. Tier 3 workers execute; Tier 2 reviews per phase. Tier 2 has ZERO discretion — every decision is pre-made in the spec.
## Phase 0: Pre-flight + TIER2_STARTUP (Tier 1, 0 commits, 1 file)
## v2 Changes from v1
- [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)
The v1 plan was correct in structure but lacked JUSTIFICATION for each move. v2 fixes this by:
1. **Adding the 4-criteria decision rule** at the top of every phase (so Tier 2 knows the rule, not just the result)
2. **Documenting the data/view/ops split** explicitly (so Tier 2 doesn't put ImGui in random files)
3. **Banning Tier 2 discretion** — the spec is now prescriptive; Tier 2 executes, doesn't decide
4. **Adding the "preserve Pydantic proxies in models.py" decision** (so Tier 2 doesn't accidentally try to move them)
5. **Adding the "view code goes in `gui_2.py`" rule** (so Tier 2 doesn't put new view code in the data files)
## Phase 1: MERGE ImGui LEAKS into `gui_2.py` (5 commits, 1 per file)
## Phase 0: Pre-flight + reset state.toml (Tier 1, 1 commit)
**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 0.1** [Tier 1]: Reset the 5 "damaged" tasks in `state.toml` from "damaged" → "pending" with a note explaining the data is intact
- [x] **Task 0.2** [Tier 1]: Update `state.toml` to reflect the v2 plan (14 tasks instead of 22)
- [x] **Task 0.3** [Tier 1]: Update `metadata.json` to add VC13 (4-criteria rule documented) and VC14 (data/view/ops split documented)
- [x] **COMMIT:** `conductor(plan): v2 - reset damaged tasks; document 4-criteria rule + data/view/ops split` (Tier 1)
- [x] **GIT NOTE:** v2 corrects the v1 spec to be prescriptive (no Tier 2 discretion). Data is intact in models.py; track is recoverable.
- [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 1: MERGE ImGui LEAKS (DONE — verify only)
## Phase 2: MERGE vendor files into `ai_client.py` (2 commits, 1 per file)
- [x] **Task 1.0** [Tier 2]: Verify the 5 commits are still in the branch
- `git log --oneline | grep bg_shader\|shaders\|command_palette\|diff_viewer\|patch_modal` returns 5 commits
- `git grep -l "imgui_bundle\|from imgui\\." -- 'src/*.py'` returns ONLY `gui_2.py` + `imgui_scopes.py`
- [x] **VERIFICATION:** VC1 + VC2 (no code changes, no commit)
**Focus:** 2 vendor files that should be unified with `ai_client.py` per user directive.
## Phase 2: MERGE vendor files (DONE — verify only)
- [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)
- [x] **Task 2.0** [Tier 2]: Verify the 2 commits are still in the branch
- `git log --oneline | grep vendor_capabilities\|vendor_state` returns 2 commits
- `python -c "from src.ai_client import PROVIDER_CAPABILITIES, VendorMetric"` works
- [x] **VERIFICATION:** VC3 + VC4 (no code changes, no commit)
## Phase 3: SPLIT `models.py` (8 commits, 3 new files + 6 merges + 1 reduce)
## Phase 3: SPLIT `models.py` (the new work — 5 phases, 9 atomic commits)
**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`.
The critical insight: the data is INTACT in `models.py`. The 5 "damaged" tasks were about destination files not having the class definitions ADDED yet. The data is fine; we just need to copy the class definitions to the destination files.
### Phase 3a: Create new files (3 commits)
### Phase 3a: Create `src/mma.py` (1 commit)
- [x] **Task 3.1** [Tier 3]: Create `src/mma.py` with `ThinkingSegment`, `Ticket`, `Track`, `WorkerContext`, `TrackState` (moved from `models.py`)
- [x] **Task 3a.1** [Tier 3]: Create `src/mma.py` with `ThinkingSegment`, `Ticket`, `Track`, `WorkerContext`, `TrackMetadata`, `TrackState`, `EMPTY_TRACK_STATE`
- 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`)
- Source: copy from `src/models.py` (the class bodies are intact)
- Update imports in: `src/multi_agent_conductor.py`, `src/dag_engine.py`, `src/orchestrator_pm.py`, `src/conductor_tech_lead.py`, `src/mma_prompts.py` (and any other consumer)
- SAFETY: Run `tests/test_mma_*.py` + `tests/test_dag_engine.py` + `tests/test_orchestration_logic.py` + `tests/test_conductor_engine_v2.py` + `tests/test_ticket_queue.py`
- [x] **COMMIT:** `refactor(mma): create src/mma.py with MMA Core (split from models.py)` (Tier 3)
- [x] **GIT NOTE:** per the 4-criteria rule (C1=6 systems, C2=state machine, C3=tests, C4=substantial); C5 PRESERVATION: Ticket/Track/WorkerContext/TrackState/TrackMetadata/ThinkingSegment are MMA Core; they live in `src/mma.py`. The existing `src/mma_prompts.py` (171 lines) is the only existing `mma_` prefixed file; it stays.
### Phase 3b: Create `src/project.py` (1 commit)
- [x] **Task 3b.1** [Tier 3]: Create `src/project.py` with `ProjectContext` + 5 sub-dataclasses + config IO (`_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`
- Source: copy from `src/models.py` (the class bodies are intact) + add the 5 sub-dataclasses from `cruft_elimination_20260627` (805a0619) which are already in `models.py` if the cruft track merged
- Update imports in: `src/project_manager.py` + any other consumer
- SAFETY: Run `tests/test_project_manager_*.py` + `tests/test_project_context_20260627.py` (the new test from cruft track)
- [x] **COMMIT:** `refactor(project): create src/project.py with ProjectContext + sub + config IO (split from models.py)` (Tier 3)
- [x] **GIT NOTE:** per the 4-criteria rule (C1=6+ systems, C3=tests, C4=substantial); ProjectContext is the typed return of `project_manager.flat_config()`; the 5 sub-dataclasses model the actual nested dict structure of `flat_config()`'s return.
### Phase 3c: Create `src/project_files.py` (1 commit)
- [x] **Task 3c.1** [Tier 3]: Create `src/project_files.py` with `FileItem`, `Preset`, `ContextPreset`, `ContextFileEntry`, `NamedViewPreset`
- 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)
- Source: copy from `src/models.py` (the class bodies are intact)
- Update imports in: `src/aggregate.py`, `src/app_controller.py`, `src/gui_2.py`, `src/context_presets.py`
- SAFETY: Run `tests/test_file_item_model.py` + `tests/test_view_presets.py` + `tests/test_context_presets_*.py` + `tests/test_custom_slices_*.py` + `tests/test_presets.py`
- [x] **COMMIT:** `refactor(project_files): create src/project_files.py (split from models.py)` (Tier 3)
- [x] **GIT NOTE:** per the 4-criteria rule (C1=cross-system, C3=tests, C4=substantial); these are the file-related project state classes.
### Phase 3b: Merge other classes into existing sub-system files (6 commits, 1 per destination)
### Phase 3d: Merge `Tool` + `ToolPreset` into `src/tool_presets.py` (1 commit)
- [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
- [x] **Task 3d.1** [Tier 3]: Add `Tool` and `ToolPreset` class definitions to `src/tool_presets.py`
- HOW: `manual-slop_edit_file` to add the classes to the top of `src/tool_presets.py`
- Source: copy from `src/models.py` (the class bodies are intact)
- Update imports in `src/models.py` (remove the Tool/ToolPreset defs, add `from src.tool_presets import Tool, ToolPreset` for backward compat) — but ONLY if removing from models.py
- SAFETY: Run `tests/test_tool_presets_*.py` + `tests/test_bias_models.py` (which test Tool/ToolPreset via models.Tool)
- NOTE: This is a MERGE, not a NEW file. The Tool/ToolPreset classes now live in `src/tool_presets.py` (which already had `ToolPresetManager`). Per the 4-criteria rule: C1=NO (just tool_presets), C2=NO, C3=NO, C4=NO — so MERGE.
- [x] **COMMIT:** `refactor(tool_presets): merge Tool + ToolPreset from models.py into tool_presets.py` (Tier 3)
- [x] **GIT NOTE:** per the 4-criteria rule: Tool/ToolPreset fail C1, C2, C3 (all consumers are in the tool subsystem); C4 is borderline. MERGE into `src/tool_presets.py` which already exists.
### Phase 3c: Reduce `models.py` (1 commit)
### Phase 3e: Merge `BiasProfile` into `src/tool_bias.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)
- [x] **Task 3e.1** [Tier 3]: Add `BiasProfile` class definition to `src/tool_bias.py`
- HOW: `manual-slop_edit_file` to add the class
- Source: copy from `src/models.py`
- Update imports in `src/models.py` (remove BiasProfile def, add `from src.tool_bias import BiasProfile` for backward compat)
- SAFETY: Run `tests/test_tool_presets_*.py` + `tests/test_bias_models.py`
- Per 4-criteria rule: C1=NO, C2=NO, C3=NO, C4=NO. MERGE.
- [x] **COMMIT:** `refactor(tool_bias): merge BiasProfile from models.py into tool_bias.py` (Tier 3)
- [x] **GIT NOTE:** per the 4-criteria rule: BiasProfile fails all 4 criteria. MERGE into existing `src/tool_bias.py`.
## Phase 4: DELETE `AGENT_TOOL_NAMES` (1 commit)
### Phase 3f: Merge `TextEditorConfig` + `ExternalEditorConfig` into `src/external_editor.py` (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 3f.1** [Tier 3]: Add `TextEditorConfig` and `ExternalEditorConfig` class definitions to `src/external_editor.py`
- HOW: `manual-slop_edit_file` to add the classes
- Source: copy from `src/models.py`
- Update imports in `src/models.py` (remove defs, add `from src.external_editor import TextEditorConfig, ExternalEditorConfig`)
- SAFETY: Run `tests/test_external_editor_*.py`
- Per 4-criteria rule: C1=NO, C2=NO, C3=NO, C4=NO. MERGE.
- [x] **COMMIT:** `refactor(external_editor): merge TextEditorConfig + ExternalEditorConfig from models.py into external_editor.py` (Tier 3)
- [x] **GIT NOTE:** per the 4-criteria rule: editor configs are only used by the editor subsystem. MERGE.
- [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)
### Phase 3g: Merge `Persona` into `src/personas.py` (1 commit)
- [x] **Task 3g.1** [Tier 3]: Add `Persona` class definition to `src/personas.py`
- HOW: `manual-slop_edit_file` to add the class
- Source: copy from `src/models.py`
- Update imports in `src/models.py` (remove Persona def, add `from src.personas import Persona`)
- SAFETY: Run `tests/test_personas_*.py` + `tests/test_persona_*.py`
- Per 4-criteria rule: C1=NO, C2=NO, C3=NO, C4=NO. MERGE.
- [x] **COMMIT:** `refactor(personas): merge Persona from models.py into personas.py` (Tier 3)
- [x] **GIT NOTE:** per the 4-criteria rule: Persona is only used by the persona subsystem. MERGE.
### Phase 3h: Merge `WorkspaceProfile` into `src/workspace_manager.py` (1 commit)
- [x] **Task 3h.1** [Tier 3]: Add `WorkspaceProfile` class definition to `src/workspace_manager.py`
- HOW: `manual-slop_edit_file` to add the class
- Source: copy from `src/models.py`
- Update imports in `src/models.py` (remove WorkspaceProfile def, add `from src.workspace_manager import WorkspaceProfile`)
- SAFETY: Run `tests/test_workspace_manager_*.py` + `tests/test_workspace_profiles_*.py`
- Per 4-criteria rule: C1=NO, C2=NO, C3=NO, C4=NO. MERGE.
- [x] **COMMIT:** `refactor(workspace_manager): merge WorkspaceProfile from models.py into workspace_manager.py` (Tier 3)
- [x] **GIT NOTE:** per the 4-criteria rule: WorkspaceProfile is only used by the workspace subsystem. MERGE.
### Phase 3i: Merge MCP config classes into `src/mcp_client.py` (1 commit)
- [x] **Task 3i.1** [Tier 3]: Add `MCPServerConfig`, `MCPConfiguration`, `VectorStoreConfig`, `RAGConfig` class definitions + `load_mcp_config` function to `src/mcp_client.py`
- HOW: `manual-slop_edit_file` to add the classes + function
- Source: copy from `src/models.py`
- Update imports in `src/models.py` (remove defs, add `from src.mcp_client import MCPServerConfig, MCPConfiguration, VectorStoreConfig, RAGConfig, load_mcp_config`)
- SAFETY: Run `tests/test_mcp_config.py` + `tests/test_mcp_client_*.py` + `tests/test_mcp_ts_integration.py`
- Per 4-criteria rule: C1=YES (mcp_client, api_hooks, app_controller), C3=YES (test_mcp_config.py), but MCP config classes are tightly coupled to MCP client. MERGE (they're the data layer of MCP).
- [x] **COMMIT:** `refactor(mcp_client): merge MCP config dataclasses from models.py into mcp_client.py` (Tier 3)
- [x] **GIT NOTE:** per the 4-criteria rule: MCP config classes are used by mcp_client + api_hooks + app_controller; the existing test file is `test_mcp_config.py` (not at the class level). MERGE because MCP config IS the MCP subsystem's data layer.
## Phase 4: Delete `AGENT_TOOL_NAMES` (1 commit)
- [x] **Task 4.1** [Tier 3]: Delete `AGENT_TOOL_NAMES` constant from `src/models.py` + update 8 consumer sites to use `mcp_tool_specs.tool_names()`
- Consumer sites: `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
- Update test `test_tool_names_subset_of_models_agent_tool_names` — DELETE (it becomes a tautology) OR CONVERT to `assert mcp_tool_specs.tool_names() == {expected canonical tools}`
- 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)
- [x] **COMMIT:** `refactor(mcp_tool_specs): delete redundant AGENT_TOOL_NAMES; use tool_names() at consumer sites` (Tier 3)
- [x] **GIT NOTE:** AGENT_TOOL_NAMES was a hardcoded snapshot of `mcp_tool_specs.tool_names()`. The existing test `test_tool_names_subset_of_models_agent_tool_names` literally asserts `tool_names() ⊆ AGENT_TOOL_NAMES`, proving the redundancy.
## Phase 5: Verification + end-of-track (2 commits, no code changes)
## Phase 5: Reduce `src/models.py` to ~30 lines (1 commit)
**Focus:** Run all 12 VCs; write `TRACK_COMPLETION`; update `state.toml` + `tracks.md`.
- [x] **Task 5.1** [Tier 3]: After Phases 3a-i, all 11 MMA Core + FileItem + Preset + Tool + ToolPreset + BiasProfile + TextEditorConfig + ExternalEditorConfig + Persona + WorkspaceProfile + MCPServerConfig + MCPConfiguration + VectorStoreConfig + RAGConfig + load_mcp_config + ProjectContext + 5 sub + _clean_nones + load_config_from_disk + save_config_to_disk + parse_history_entries + AGENT_TOOL_NAMES have been moved out of `src/models.py`
- `src/models.py` retains ONLY: `AGENT_TOOL_NAMES` (already deleted in Phase 4) + `DEFAULT_TOOL_CATEGORIES` + Pydantic proxies (`_create_generate_request`, `_create_confirm_request`, `__getattr__`)
- Target: ~30 lines (Pydantic proxies + `DEFAULT_TOOL_CATEGORIES` + docstring)
- HOW: `manual-slop_edit_file` to remove all the moved classes
- SAFETY: Run all affected tests + the full batched suite
- [x] **COMMIT:** `refactor(models): reduce to Pydantic proxy helpers + DEFAULT_TOOL_CATEGORIES (~30 lines)` (Tier 3)
- [x] **GIT NOTE:** After 11 class moves + 1 deletion, `src/models.py` is reduced from 1044 to ~30 lines. The remaining content is the Pydantic proxies (for the API hook subsystem) + the `DEFAULT_TOOL_CATEGORIES` dict (referenced by `app_controller.py`).
- [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
## Phase 6: Verification + end-of-track (3 commits, no code changes)
- [x] **Task 6.1** [Tier 2]: Run all 14 VCs
- VC1: ImGui imports limited to `gui_2.py` + `imgui_scopes.py`
- VC2: 5 ImGui LEAK files deleted
- VC3: 2 vendor files deleted
- VC4: Vendor symbols importable from `src.ai_client`
- VC5: `src/mma.py` exists with MMA Core
- VC6: `src/project.py` exists with ProjectContext + sub + config IO
- VC7: `src/project_files.py` exists with file-related dataclasses
- VC8: 11 classes merged into 6 existing sub-system files
- VC9: `AGENT_TOOL_NAMES` deleted; 8 consumer sites updated
- VC10: `src/models.py` reduced to ≤30 lines
- VC11: All 7 audit gates pass `--strict`
- VC12: 10/11 batched test tiers pass (RAG flake acceptable)
- VC13: The 4-criteria decision rule is documented in this spec
- VC14: The data/view/ops split is documented in this spec
- 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)
- [x] **COMMIT 6.1:** `conductor(state): module_taxonomy_refactor_20260627 SHIPPED` (Tier 2)
- [x] **COMMIT 6.2:** `docs(reports): TRACK_COMPLETION_module_taxonomy_refactor_20260627` (Tier 2)
- [x] **COMMIT 6.3:** `conductor(tracks): update module_taxonomy_refactor_20260627 row` (Tier 2)
## Commit Log (Expected, 12-15 atomic commits)
## Commit Log (Expected, 16 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)
1. (Phase 0) `conductor(plan): v2 - reset damaged tasks; document 4-criteria rule + data/view/ops split` (Tier 1)
2. (Phase 3a) `refactor(mma): create src/mma.py with MMA Core (split from models.py)` (Tier 3)
3. (Phase 3b) `refactor(project): create src/project.py with ProjectContext + sub + config IO (split from models.py)` (Tier 3)
4. (Phase 3c) `refactor(project_files): create src/project_files.py (split from models.py)` (Tier 3)
5. (Phase 3d) `refactor(tool_presets): merge Tool + ToolPreset from models.py into tool_presets.py` (Tier 3)
6. (Phase 3e) `refactor(tool_bias): merge BiasProfile from models.py into tool_bias.py` (Tier 3)
7. (Phase 3f) `refactor(external_editor): merge TextEditorConfig + ExternalEditorConfig from models.py into external_editor.py` (Tier 3)
8. (Phase 3g) `refactor(personas): merge Persona from models.py into personas.py` (Tier 3)
9. (Phase 3h) `refactor(workspace_manager): merge WorkspaceProfile from models.py into workspace_manager.py` (Tier 3)
10. (Phase 3i) `refactor(mcp_client): merge MCP config dataclasses from models.py into mcp_client.py` (Tier 3)
11. (Phase 4) `refactor(mcp_tool_specs): delete redundant AGENT_TOOL_NAMES; use tool_names() at consumer sites` (Tier 3)
12. (Phase 5) `refactor(models): reduce to Pydantic proxy helpers + DEFAULT_TOOL_CATEGORIES (~30 lines)` (Tier 3)
13. (Phase 6) `conductor(state): module_taxonomy_refactor_20260627 SHIPPED` (Tier 2)
14. (Phase 6) `docs(reports): TRACK_COMPLETION_module_taxonomy_refactor_20260627` (Tier 2)
15. (Phase 6) `conductor(tracks): update 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)
## Verification Commands (run at end of each phase + Phase 6)
```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: 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"
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: (no output)
# VC3: 2 vendor files deleted
ls src/vendor_capabilities.py src/vendor_state.py 2>&1 | grep -v "No such file"
ls 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"
uv run python -c "from src.project_files import FileItem, ContextPreset, ContextFileEntry, NamedViewPreset, Preset"
# VC5-7: New files exist with correct content
uv run python -c "from src.mma import ThinkingSegment, Ticket, Track, WorkerContext, TrackState, TrackMetadata"
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, Preset, ContextPreset, ContextFileEntry, NamedViewPreset"
# 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"
# VC8: 11 classes in proper sub-system files
uv run python -c "from src.tool_presets import Tool, ToolPreset; from src.tool_bias import BiasProfile; from src.external_editor import TextEditorConfig, ExternalEditorConfig; from src.personas import Persona; from src.workspace_manager import WorkspaceProfile; from src.mcp_client import MCPServerConfig, MCPConfiguration, VectorStoreConfig, RAGConfig, load_mcp_config"
# All succeed
# VC9: AGENT_TOOL_NAMES deleted
git grep "AGENT_TOOL_NAMES" HEAD -- 'src/*.py' 'tests/*.py' | wc -l
git grep "AGENT_TOOL_NAMES" HEAD -- 'src/*.py' 'tests/*.py' | Measure-Object -Line | Select-Object -ExpandProperty Lines
# Expect: 0
# VC10: models.py reduced
Get-Item src/models.py 2>&1 | Select-Object Length
# Expect: file not found OR <= 30 lines
Measure-Object -Line on src/models.py
# Expect: <= 30
# 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)
# VC11-12: audit gates + batched suite
# Same as current baseline
```
## Notes for Tier 3 workers
## Notes for Tier 3 workers (v2 corrections)
- **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)
- **Tier 2 has ZERO discretion.** Every move is pre-decided in the spec. Do not make additional moves, do not create additional files, do not "improve" the plan.
- **Do not move Pydantic proxies** (`_create_generate_request`, `_create_confirm_request`, `__getattr__`) from `src/models.py`. They are API-specific; moving them is OUT OF SCOPE for this track.
- **Do not move `DEFAULT_TOOL_CATEGORIES`** from `src/models.py`. It is used by `app_controller.py`; moving it is out of scope.
- **The 4-criteria rule is a CHECK before each move.** Apply it: if a class fails C1, C2, C3, and C4, the move is incorrect. STOP and report.
- **Per-file atomic commits** — each move is a separate commit for atomic rollback.
- **Preserve backward compat** — when removing a class from `models.py`, KEEP a `from src.<destination> import <class>` line in `models.py` for backward compat. Don't break existing imports.
- **Style** — 1-space indentation, CRLF line endings, no comments, use `manual-slop_edit_file`.
- **Per-phase regression-guard test runs** — after each phase, run the affected tests. If a phase causes a regression, REVERT the phase commit and investigate (don't try to fix forward).
- **The `git stash*` ban is in effect** at 3 layers. Do not use `git stash` for any reason. If you need a "fresh start" feel, create a new branch.
- **The timeline-is-immutable principle** — never use `git revert` / `git reset` / `git stash` to "undo" a bad commit. Write a forward corrective commit instead.
## 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.
- **The track is now prescriptive.** v1 had gaps that gave Tier 2 discretion; v2 closes them. v2 should NOT require mid-execution corrections.
- **Phase 0 resets the state.toml** — the 5 "damaged" tasks are reset to "pending" with a note explaining the data is intact.
- **Phase 1 + 2 are DONE** — verify only, no code changes.
- **Phase 3 is the main work** — 9 commits (3a, 3b, 3c, 3d, 3e, 3f, 3g, 3h, 3i). Each commit is one of: create new file (3a, 3b, 3c) or merge into existing file (3d, 3e, 3f, 3g, 3h, 3i).
- **Phase 4 deletes `AGENT_TOOL_NAMES`** — 1 commit, 8 consumer site updates.
- **Phase 5 reduces `src/models.py`** — 1 commit.
- **Phase 6 is verification** — 3 commits, no code changes.
- **Total: 16 atomic commits** (down from v1's 22 because the tier 2 work is now prescriptive, not exploratory).
## See also
- `conductor/tracks/module_taxonomy_refactor_20260627/spec.md` — the v2 spec (the canonical reference for this plan)
- `conductor/tracks/module_taxonomy_refactor_20260627/state.toml` — the track state
- `docs/reports/FOLLOWUP_module_taxonomy_refactor_20260627_recoverable.md` — the recovery report (data is NOT lost)
- `docs/reports/FOLLOWUP_module_taxonomy_refactor_20260627.md` — the original taxonomy 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
@@ -17,7 +17,7 @@ Per the user's principle: **unify unless there's a good reason (import load time
| 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) |
| `mcp_tool_specs.tool_names()` test | EXISTS (asserts `tool_names() Γèå AGENT_TOOL_NAMES` ΓÇö proves it's redundant) |
## Goals
@@ -28,16 +28,16 @@ Per the user's principle: **unify unless there's a good reason (import load time
| 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 |
| 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)
- 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
@@ -70,8 +70,8 @@ For each of these 5 files, move the content into `gui_2.py` in a clearly-marked
```
**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`
- `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`
@@ -89,8 +89,8 @@ For each of these 5 files, move the content into `gui_2.py` in a clearly-marked
```
**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`
- `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`
@@ -170,17 +170,17 @@ If `models.py` becomes essentially empty after these moves, **delete the file en
## 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)
- `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
- 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")
@@ -191,7 +191,7 @@ If `models.py` becomes essentially empty after these moves, **delete the file en
| # | 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` deleted (4 LEAK files per the data/view/ops split) | `ls src/{bg_shader,shaders,command_palette,diff_viewer}.py` returns not-found. `src/patch_modal.py` is NOT a LEAK it's the data module (DiffHunk/DiffFile/PendingPatch) per the data/view/ops split rule. The diff_viewer classes (DiffHunk/DiffFile) were moved INTO it during the cruft_elimination track's split; deleting it would violate the data module's integrity. See `conductor/tracks/post_module_taxonomy_de_cruft_20260627/spec.md` Phase 1 for the formal correction. |
| VC2 | `src/bg_shader.py`, `src/shaders.py`, `src/command_palette.py`, `src/diff_viewer.py` deleted (4 LEAK files per the data/view/ops split) | `ls src/{bg_shader,shaders,command_palette,diff_viewer}.py` returns not-found. `src/patch_modal.py` is NOT a LEAK ΓÇö it's the data module (DiffHunk/DiffFile/PendingPatch) per the data/view/ops split rule. The diff_viewer classes (DiffHunk/DiffFile) were moved INTO it during the cruft_elimination track's split; deleting it would violate the data module's integrity. See `conductor/tracks/post_module_taxonomy_de_cruft_20260627/spec.md` Phase 1 for the formal correction. |
| 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 |
@@ -199,7 +199,7 @@ If `models.py` becomes essentially empty after these moves, **delete the file en
| 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 from 1044 to ~135 lines (Pydantic proxies + DEFAULT_TOOL_CATEGORIES + lazy `__getattr__` for backward compat) | `wc -l src/models.py` returns 200; the 30-line target was aspirational. The lazy `__getattr__` is necessary for backward compat with 30+ legacy `from src.models import X` call sites until the `post_module_taxonomy_de_cruft_20260627` follow-up track migrates them to direct imports from the subsystem files (`src.mma`, `src.project`, `src/project_files`, `src/tool_presets`, `src/tool_bias`, `src/external_editor`, `src/personas`, `src/workspace_manager`, `src/mcp_client`). The full migration is FR7 of the post_module_taxonomy_de_cruft_20260627 track. The legacy `Metadata = TrackMetadata` alias is preserved for `from src.models import Metadata` to resolve to the TrackMetadata dataclass (used by `tests/test_track_state_schema.py`). |
| VC10 | `src/models.py` reduced from 1044 to ~135 lines (Pydantic proxies + DEFAULT_TOOL_CATEGORIES + lazy `__getattr__` for backward compat) | `wc -l src/models.py` returns Γëñ200; the 30-line target was aspirational. The lazy `__getattr__` is necessary for backward compat with 30+ legacy `from src.models import X` call sites until the `post_module_taxonomy_de_cruft_20260627` follow-up track migrates them to direct imports from the subsystem files (`src.mma`, `src.project`, `src/project_files`, `src/tool_presets`, `src/tool_bias`, `src/external_editor`, `src/personas`, `src/workspace_manager`, `src/mcp_client`). The full migration is FR7 of the post_module_taxonomy_de_cruft_20260627 track. The legacy `Metadata = TrackMetadata` alias is preserved for `from src.models import Metadata` to resolve to the TrackMetadata dataclass (used by `tests/test_track_state_schema.py`). |
| VC11 | All 7 audit gates pass `--strict` | unchanged from baseline |
| VC12 | 10/11 batched test tiers pass (RAG flake acceptable) | unchanged from baseline |
@@ -212,13 +212,13 @@ If `models.py` becomes essentially empty after these moves, **delete the file en
| 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 |
| 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
- `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
@@ -1,62 +1,77 @@
# Track state for module_taxonomy_refactor_20260627
# Track state for module_taxonomy_refactor_20260627 (v2)
# 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"
name = "Module Taxonomy Refactor v2"
version = "v2"
status = "completed"
current_phase = "complete"
last_updated = "2026-06-26"
[blocked_by]
cruft_elimination_20260627 = "pending (the cruft track has a ProjectContext-in-models.py commit that needs to be coordinated)"
cruft_elimination_20260627 = "merged (ProjectContext + 5 sub landed in models.py at lines 797-873; safe to extract)"
[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" }
phase_0 = { status = "completed", checkpointsha = "c35cc494", name = "Pre-flight + reset state.toml + v2 corrections" }
phase_1 = { status = "completed", checkpointsha = "be5607de", name = "MERGE ImGui LEAKS into gui_2.py (DONE in branch; verify only)" }
phase_2 = { status = "completed", checkpointsha = "904aedc8", name = "MERGE vendor files into ai_client.py (DONE in branch; verify only)" }
phase_3 = { status = "completed", checkpointsha = "a90f9634", name = "SPLIT models.py into mma.py + project.py + project_files.py + 6 sub-system merges (9 commits; 3a + 3g already done in branch)" }
phase_4 = { status = "completed", checkpointsha = "779d504c", name = "DELETE AGENT_TOOL_NAMES (1 commit)" }
phase_5 = { status = "completed", checkpointsha = "592d0e0c", name = "Reduce models.py to Pydantic proxy helpers only (1 commit)" }
phase_6 = { status = "completed", 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" }
t0_1 = { status = "completed", commit_sha = "c35cc494", description = "Reset the 5 'damaged' tasks in state.toml from 'damaged' to 'pending' with a note explaining the data is intact" }
t0_2 = { status = "completed", commit_sha = "c35cc494", description = "Update state.toml to reflect the v2 plan (14 tasks instead of 22)" }
t0_3 = { status = "completed", commit_sha = "c35cc494", description = "Update metadata.json to add VC13 (4-criteria rule documented) and VC14 (data/view/ops split documented)" }
t1_0 = { status = "completed", commit_sha = "be5607de", description = "Verify the 5 ImGui LEAK commits are still in the branch (DONE; verify only)" }
t2_0 = { status = "completed", commit_sha = "904aedc8", description = "Verify the 2 vendor file commits are still in the branch (DONE; verify only)" }
t3a_1 = { status = "completed", commit_sha = "cd828e52", description = "Create src/mma.py with ThinkingSegment, Ticket, Track, WorkerContext, TrackState, TrackMetadata (copy from models.py; MMA Core per 4-criteria rule C1+C2+C3+C4)" }
t3b_1 = { status = "completed", commit_sha = "e430df86", description = "Create src/project.py with ProjectContext + 5 sub + config IO (copy from models.py; per 4-criteria rule C1+C3+C4)" }
t3c_1 = { status = "completed", commit_sha = "86f16767", description = "Create src/project_files.py with FileItem, Preset, ContextPreset, ContextFileEntry, NamedViewPreset (copy from models.py; per 4-criteria rule C1+C3+C4)" }
t3d_1 = { status = "completed", commit_sha = "6adaae2e", description = "Merge Tool + ToolPreset into src/tool_presets.py (per 4-criteria rule: fail C1+C2+C3; MERGE into existing)" }
t3e_1 = { status = "completed", commit_sha = "ecd8e82f", description = "Merge BiasProfile into src/tool_bias.py (per 4-criteria rule: fail C1+C2+C3; MERGE into existing)" }
t3f_1 = { status = "completed", commit_sha = "bca08755", description = "Merge TextEditorConfig + ExternalEditorConfig into src/external_editor.py (per 4-criteria rule: fail C1+C2+C3; MERGE into existing)" }
t3g_1 = { status = "completed", commit_sha = "d7872bea", description = "Merge Persona into src/personas.py (per 4-criteria rule: fail C1+C2+C3; MERGE into existing)" }
t3h_1 = { status = "completed", commit_sha = "0d2a9b5e", description = "Merge WorkspaceProfile into src/workspace_manager.py (per 4-criteria rule: fail C1+C2+C3; MERGE into existing)" }
t3i_1 = { status = "completed", commit_sha = "a90f9634", description = "Merge MCP config dataclasses (MCPServerConfig, MCPConfiguration, VectorStoreConfig, RAGConfig, load_mcp_config) into src/mcp_client.py (per 4-criteria rule: C1+coupled, MERGE into MCP subsystem)" }
t4_1 = { status = "completed", commit_sha = "779d504c", description = "Delete AGENT_TOOL_NAMES from src/models.py + update 8 consumer sites to use mcp_tool_specs.tool_names() (redundant; existing test asserts this)" }
t5_1 = { status = "completed", commit_sha = "592d0e0c", description = "Reduce models.py to Pydantic proxy helpers + DEFAULT_TOOL_CATEGORIES only (~30 lines, down from 1044; achieved 139 lines due to lazy __getattr__ for backward compat)" }
t6_1 = { status = "completed", commit_sha = "", description = "Run all 14 VCs; write TRACK_COMPLETION; update state.toml + tracks.md (see docs/reports/TRACK_COMPLETION_module_taxonomy_refactor_20260627.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
phase_0_complete = true
phase_1_complete = true
phase_2_complete = true
phase_3_complete = true
phase_4_complete = true
phase_5_complete = true
phase_6_complete = true
[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)"
file_change_summary = { files_deleted = 7, files_created = 3, files_modified = 10, potentially_deleted = 1 }
net_files_change = "-4 files (65 -> 61, possibly 60 if models.py is eliminated)"
im_gui_leak_count = 5
vendor_files_to_merge = 2
models_py_split_targets = 3
models_py_merge_targets = 11
models_py_delete_targets = 1
agent_tool_names_consumers = 8
[taxonomy_law]
criteria = { "C1": "Cross-system usage (>= 3 unrelated systems)", "C2": "State machine / lifecycle", "C3": "Test file already exists", "C4": "Substantial size (> 30 lines OR > 5 fields)" }
decision_rule = "C1 OR C2 OR C3 -> DEDICATED FILE; ONLY C4 -> MERGE INTO DESTINATION; NONE -> KEEP"
data_view_ops_rule = "Data classes go in data files; rendering code goes in gui_2.py; operations go with the data"
exception = "imgui_scopes.py is the EXCEPTION (Python with context managers for ImGui scopes)"
[final_metrics]
src_models_py_lines = 139
src_models_py_lines_original = 1044
reduction_ratio = 0.87
atomic_commits = 18
tests_pass = "138+ across 30 test files"
pre_existing_failures = 1
test_rejection_prevents_dispatch = "pre-existing dialog-mock issue; unrelated to this track"
@@ -0,0 +1,295 @@
# Tier 2 Startup Brief: post_module_taxonomy_de_cruft_20260627
## Context
Followup to module_taxonomy_refactor_20260627 (v2). After the taxonomy is settled, clean up the remaining cruft that v2 was explicitly out-of-scope for. Two critical bugs from v2 must be fixed first; then 4 de-cruft tasks address the __getattr__ shim, DEFAULT_TOOL_CATEGORIES, Pydantic proxies, and ImGui usage standardization.
## MANDATORY Pre-Action Reading (per agent protocol)
1. AGENTS.md (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 (Result[T] convention)
6. conductor/code_styleguides/type_aliases.md (the 10 TypeAliases convention)
7. conductor/code_styleguides/code_path_audit.md (code path audit styleguide)
8. **conductor/tracks/post_module_taxonomy_de_cruft_20260627/spec.md** (the canonical reference for this plan)
9. **conductor/tracks/post_module_taxonomy_de_cruft_20260627/plan.md** (the 6-phase plan; 12 atomic commits)
10. conductor/tracks/module_taxonomy_refactor_20260627/spec.md (the v2 spec that this track follows up on)
11. docs/reports/FOLLOWUP_module_taxonomy_v2_review.md (the review that identified these tasks)
12. docs/reports/FOLLOWUP_module_taxonomy_refactor_20260627_recoverable.md (the recovery report)
**First commit of this track must include** `TIER-2 READ <list> before post_module_taxonomy_de_cruft_20260627` in the message.
## TIMELINE-IS-IMMUTABLE PRINCIPLE (added 2026-06-27 per user feedback)
When you (the agent) fuck up — make a wrong commit, break a file, take a bad path — your first instinct will be to "undo" the mistake with `git revert`, `git reset`, or `git stash`. **THIS INSTINCT IS WRONG.** The user explicitly stated: "if an agent fucks up, their tendency to want to 'revert' is not correct and instead they must live with the timeline and just do corrections with a new commit."
**The rule:**
- The git history is IMMUTABLE on this branch. Every commit you've made is part of the record.
- "Fixing forward" via a new commit makes the user's review EASIER.
- "Undoing" via `git revert` / `git reset` / `git stash` makes the user's review HARDER (they have to read the diff between the bad and the "fix" to understand what went wrong).
**Correct pattern when you fuck up:**
1. Pause. Read the actual file. Confirm the state.
2. Write a NEW commit that fixes the problem. The commit message should briefly say what was wrong and what you fixed.
3. If the bad commit introduced data corruption that the user will see, the user can `git revert` it during their review — that's the user's choice, not yours.
4. If you need to recover an old version of a file, use `git show <good-sha>:<path> > <path>` to extract it.
**Wrong pattern (which you must NOT do):**
- `git revert <sha>` to undo a commit
- `git reset --hard <sha>` to throw away a bad commit
- `git stash` to "save" uncommitted work
- `git checkout <old-sha> -- .` to "go back to when things were good" (and then commit on top)
## HARD BAN: `git stash*` (added 2026-06-27)
`git stash`, `git stash pop`, `git stash apply`, `git stash drop`, `git stash clear` are FORBIDDEN at 3 layers:
1. AGENTS.md HARD BAN
2. conductor/tier2/opencode.json.fragment bash deny rules (top-level + agent-level)
3. This prompt's Hard Bans list
Stashing throws away the user's in-progress edits silently. If you think you need a stash, you don't — use a NEW BRANCH or a WORKTREE instead.
## Pre-flight verification
```bash
# Verify the current state of src/models.py
wc -l src/models.py
# Expect: 162
# Verify the LEGACY_NAMES bug exists
uv run python scripts/generate_type_registry.py --check 2>&1 | tail -3
# Expect: NameError: name 'LEGACY_NAMES' is not defined
# Verify the missing latest symlink
ls docs/reports/code_path_audit/latest 2>&1
# Expect: not found (or symlink target doesn't exist)
# Verify patch_modal.py is a data module (not a LEAK)
head -20 src/patch_modal.py
# Expect: data class definitions (DiffHunk, DiffFile, PendingPatch)
# Verify all 7 audit gates (5 pass, 2 fail)
for gate in weak_types generate_type_registry main_thread_imports no_models_config_io code_path_audit_coverage exception_handling optional_in_3_files; do
echo "--- $gate ---"
case $gate in
generate_type_registry) uv run python scripts/generate_type_registry.py --check 2>&1 | tail -1 ;;
code_path_audit_coverage) uv run python scripts/audit_code_path_audit_coverage.py --input-dir docs/reports/code_path_audit/latest --strict 2>&1 | tail -1 ;;
weak_types|main_thread_imports|no_models_config_io|exception_handling|optional_in_3_files) uv run python scripts/audit_$gate.py --strict 2>&1 | tail -1 ;;
esac
done
```
## Post-track verification (after Phase 6)
```bash
# VC1: generate_type_registry.py --check exits 0
uv run python scripts/generate_type_registry.py --check
$? # expect: 0
# VC2: audit_code_path_audit_coverage.py exits 0
uv run python scripts/audit_code_path_audit_coverage.py --input-dir docs/reports/code_path_audit/latest --strict
$? # expect: 0
# VC3: All 7 audit gates pass --strict
for gate in weak_types generate_type_registry main_thread_imports no_models_config_io code_path_audit_coverage exception_handling optional_in_3_files; do
case $gate in
generate_type_registry) uv run python scripts/generate_type_registry.py --check >/dev/null 2>&1 ;;
code_path_audit_coverage) uv run python scripts/audit_code_path_audit_coverage.py --input-dir docs/reports/code_path_audit/latest --strict >/dev/null 2>&1 ;;
*) uv run python scripts/audit_$gate.py --strict >/dev/null 2>&1 ;;
esac
echo "$gate: $?"
done
# All expect: 0
# VC4: 10/11 batched test tiers pass
uv run python scripts/run_tests_batched.py
# Expect: 10/11 PASS
# VC5: __getattr__ shim removed
git grep "__getattr__" HEAD -- src/models.py
# Expect: 0 hits
# VC6: DEFAULT_TOOL_CATEGORIES moved
git grep "DEFAULT_TOOL_CATEGORIES" HEAD -- src/models.py
# Expect: 0 hits
git grep "DEFAULT_TOOL_CATEGORIES" HEAD -- src/ai_client.py
# Expect: >= 1 hit
# VC7: Pydantic proxies moved
git grep "_create_generate_request" HEAD -- src/models.py
# Expect: 0 hits
git grep "_create_generate_request" HEAD -- src/api_hooks.py
# Expect: >= 1 hit
# VC8: ImGui usage standardized
git grep "imgui\." HEAD -- src/markdown_helper.py src/theme_2.py src/theme_nerv.py src/theme_nerv_fx.py | grep -v "from imgui"
# Expect: only context-manager usage (no direct begin_/end_ pairs)
# VC9: models.py reduced
wc -l src/models.py
# Expect: <= 20
# VC10: All consumer sites updated
git grep "from src.models import" HEAD -- src/*.py tests/*.py | grep -v Metadata
# Expect: 0 hits for the moved classes
```
## Per-phase patterns for Tier 3 workers
### Pattern: fix critical bug (Phase 0)
```bash
# 1. Find the original definition
git log -p --all -S "LEGACY_NAMES" -- scripts/generate_type_registry.py
# 2. Add the missing definition (or remove the reference)
# manual-slop_edit_file scripts/generate_type_registry.py
# Add LEGACY_NAMES = [...] at the top of the file
# 3. Verify
uv run python scripts/generate_type_registry.py --check
```
### Pattern: create symlink (Phase 0)
```bash
# 1. Find the most recent audit output
ls docs/reports/code_path_audit/
# 2. Create the symlink
New-Item -ItemType SymbolicLink -Path docs/reports/code_path_audit/latest -Target <most-recent>
# 3. Verify
uv run python scripts/audit_code_path_audit_coverage.py --input-dir docs/reports/code_path_audit/latest --strict
```
### Pattern: remove __getattr__ shim (Phase 2)
```bash
# 1. Find all consumer sites
git grep "from src.models import" -- 'src/*.py' 'tests/*.py'
# 2. Update each consumer to use direct imports
# For MMA Core classes (Ticket, Track, etc.):
# from src.models import Ticket
# ->
# from src.mma import Ticket
# For ProjectContext:
# from src.models import ProjectContext
# ->
# from src.project import ProjectContext
# For FileItem + Preset + ContextPreset + ContextFileEntry + NamedViewPreset:
# from src.models import FileItem
# ->
# from src.project_files import FileItem
# For Tool + ToolPreset:
# from src.models import Tool
# ->
# from src.tool_presets import Tool
# For BiasProfile:
# from src.models import BiasProfile
# ->
# from src.tool_bias import BiasProfile
# For TextEditorConfig + ExternalEditorConfig:
# from src.models import TextEditorConfig
# ->
# from src.external_editor import TextEditorConfig
# For Persona:
# from src.models import Persona
# ->
# from src.personas import Persona
# For WorkspaceProfile:
# from src.models import WorkspaceProfile
# ->
# from src.workspace_manager import WorkspaceProfile
# For MCPServerConfig + MCPConfiguration + VectorStoreConfig + RAGConfig + load_mcp_config:
# from src.models import MCPServerConfig
# ->
# from src.mcp_client import MCPServerConfig
# 3. Remove the __getattr__ shim from src/models.py
# manual-slop_edit_file src/models.py
# Delete the entire __getattr__ function
# 4. Verify
uv run python -m pytest tests/test_*.py -v
```
### Pattern: move dict/constant (Phase 3, Phase 4)
```bash
# 1. Add the dict/constant to the destination file
# manual-slop_edit_file src/ai_client.py
# Add DEFAULT_TOOL_CATEGORIES = { ... } in the right location
# 2. Remove from the source file
# manual-slop_edit_file src/models.py
# Delete the DEFAULT_TOOL_CATEGORIES definition
# 3. Update consumer sites
# git grep DEFAULT_TOOL_CATEGORIES -- 'src/*.py'
# Update each consumer to import from the new location
# 4. Verify
uv run python -m pytest tests/test_app_controller_*.py -v
```
### Pattern: standardize ImGui usage (Phase 5)
```bash
# For each of the 4 files (markdown_helper.py, theme_2.py, theme_nerv.py, theme_nerv_fx.py):
# 1. Find ImGui begin_/end_ pairs
git grep "imgui\." src/markdown_helper.py
# Look for: imgui.begin("X") ... imgui.end()
# 2. Replace with imgui_scopes.py context manager pattern
# manual-slop_edit_file src/markdown_helper.py
# Replace:
# imgui.begin("X")
# # content
# imgui.end()
# With:
# with imgui.begin("X"):
# # content
# 3. Add the import
# from src.imgui_scopes import ...
# 4. Verify
uv run python -m pytest tests/test_<file>.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
- Preserve backward-compat: when removing a class from models.py, KEEP a re-export line for any consumer that still uses the old path
## Notes for Tier 2 reviewer
- **Phase 0 is critical** — these are bugs Tier 2 introduced in v2. Fix them FIRST.
- **Phase 1 is the spec update** (VC2 + VC10 corrections). The user's acceptance of the trade-offs is documented.
- **Phase 2 is the most invasive** — removing the __getattr__ shim changes the import surface for 30+ consumer sites. Run the full batched test suite after each consumer-site update.
- **Phase 3 + 4 are simple moves** — single-consumer moves. Verify after each.
- **Phase 5 is per-file** — 4 commits, 1 per file. Verify after each.
- **Total: 12 atomic commits** (matches the spec's expected commit count).
- **Tier 2 must NOT use `git stash*` for any reason.** Banned at 3 layers.
- **Tier 2 must NOT use `git revert*` / `git reset*` for any reason.** Banned per AGENTS.md. Use forward commits instead.
## See also
- conductor/tracks/post_module_taxonomy_de_cruft_20260627/spec.md (the canonical reference)
- conductor/tracks/post_module_taxonomy_de_cruft_20260627/plan.md (the 6-phase plan)
- conductor/tracks/post_module_taxonomy_de_cruft_20260627/metadata.json (the metadata)
- conductor/tracks/post_module_taxonomy_de_cruft_20260627/state.toml (the state)
- conductor/tracks/module_taxonomy_refactor_20260627/spec.md (the v2 spec that this track follows up on)
- docs/reports/FOLLOWUP_module_taxonomy_v2_review.md (the review that identified these tasks)
- docs/reports/FOLLOWUP_module_taxonomy_refactor_20260627_recoverable.md (the recovery report)
- AGENTS.md (File Size and Naming Convention HARD RULE)
- conductor/code_styleguides/data_oriented_design.md (Prefer Fewer Types principle)
@@ -0,0 +1,69 @@
{
"track_id": "post_module_taxonomy_de_cruft_20260627",
"name": "Post Module Taxonomy De-Cruft (Fix 2 Critical Bugs + 4 De-Cruft Tasks)",
"status": "active",
"type": "fix",
"date_created": "2026-06-27",
"created_by": "tier1-orchestrator",
"blocks": [],
"blocked_by": {
"module_taxonomy_refactor_20260627": "shipped (v2 was the prerequisite; this track is the followup)"
},
"scope": {
"new_files": [
"docs/reports/TRACK_COMPLETION_post_module_taxonomy_de_cruft_20260627.md"
],
"modified_files": [
"scripts/generate_type_registry.py",
"src/models.py",
"src/ai_client.py",
"src/api_hooks.py",
"src/markdown_helper.py",
"src/theme_2.py",
"src/theme_nerv.py",
"src/theme_nerv_fx.py",
"conductor/tracks/module_taxonomy_refactor_20260627/spec.md"
],
"new_symlinks": [
"docs/reports/code_path_audit/latest"
]
},
"verification_criteria": [
"VC1: generate_type_registry.py --check exits 0 (NameError: LEGACY_NAMES bug fixed)",
"VC2: audit_code_path_audit_coverage.py --input-dir docs/reports/code_path_audit/latest --strict exits 0 (latest symlink created)",
"VC3: All 7 audit gates pass --strict",
"VC4: 10/11 batched test tiers pass (RAG flake acceptable)",
"VC5: __getattr__ shim removed from src/models.py (0 hits after grep)",
"VC6: DEFAULT_TOOL_CATEGORIES moved to src/ai_client.py (0 hits in models.py, 1 hit in ai_client.py)",
"VC7: Pydantic proxies moved to src/api_hooks.py (0 hits in models.py, 1 hit in api_hooks.py)",
"VC8: ImGui usage standardized in markdown_helper.py, theme_2.py, theme_nerv.py, theme_nerv_fx.py (only context-manager usage)",
"VC9: src/models.py reduced to <= 20 lines",
"VC10: All consumer sites updated to direct imports (0 from src.models import for moved classes)",
"VC11: v2 spec updated to reflect VC2 + VC10 corrections",
"VC12: All 7 audit gates pass --strict (re-verify after de-cruft)",
"VC13: 10/11 batched test tiers pass (re-verify after de-cruft)"
],
"estimated_effort": {
"method": "scope (per workflow.md \u00a7Tier 1 Track Initialization Rules). NO day estimates.",
"scope": "1 file fix (generate_type_registry.py) + 1 symlink creation + 1 spec edit + 1 large models.py cleanup (remove __getattr__ + move DEFAULT_TOOL_CATEGORIES + move Pydantic proxies) + 4 ImGui standardization files + 1 verification report; ~12 atomic commits total"
},
"risk_register": [
"R1 (low): Fixing the NameError: LEGACY_NAMES bug breaks other things - mitigated by running the type registry generation after fix",
"R2 (medium): The latest symlink doesn't work on Windows (symlink restrictions) - mitigated by using a .latest marker file instead of a symlink; update the audit script to read the marker",
"R3 (high): Removing the __getattr__ shim breaks 30+ consumer sites - mitigated by per-file migration; run regression tests after each consumer-site update",
"R4 (low): Moving DEFAULT_TOOL_CATEGORIES breaks app_controller.py - mitigated by single consumer; update + verify",
"R5 (low): Moving Pydantic proxies breaks api_hooks.py and api_hook_client.py - mitigated by 2 consumer sites; update + verify",
"R6 (medium): Standardizing ImGui usage in theme/markdown files breaks their tests - mitigated by per-file refactor; run theme/markdown tests after each",
"R7 (low): The v2 spec update is itself a 'rewriting commits' pattern (the user warned against this) - mitigated by: the v2 spec is a TRACK ARTIFACT, not a commit in the v2 branch; updates to v2 spec are normal"
],
"out_of_scope": [
"The 4-criteria rule itself (established in v2)",
"The data/view/ops split (established in v2)",
"Moving __getattr__ legacy migration shim back from subsystem files (the shim is being REMOVED)",
"Refactoring aggregate.py (513 lines), app_controller.py (4869 lines), gui_2.py (7773 lines)",
"The RAG test pre-existing flake",
"New ImGui-using files (only standardize existing)",
"The cruft_elimination_20260627 track's work (already SHIPPED)",
"The v2 spec rewriting (it was a track artifact, not a commit in the v2 branch)"
]
}
@@ -0,0 +1,204 @@
# Plan: post_module_taxonomy_de_cruft_20260627
5 phases, 11 tasks, ~12 atomic commits. Per-task TDD red-first. Tier 3 workers execute; Tier 2 reviews per phase.
## Phase 0: Fix critical bugs (Tier 3, 2 commits)
**Focus:** The 2 critical bugs that broke the audit gates. Must be fixed FIRST before the de-cruft work can proceed.
- [x] **Task 0.1** [Tier 3]: Fix the `NameError: LEGACY_NAMES` bug in `scripts/generate_type_registry.py`
- HOW: `git log -p --all -S "LEGACY_NAMES" -- scripts/generate_type_registry.py` to find the original definition
- Add the missing definition or remove the reference
- SAFETY: `uv run python scripts/generate_type_registry.py --check` exits 0
- [x] **COMMIT 0.1:** `fix(generate_type_registry): define LEGACY_NAMES to fix NameError` (Tier 3)
- [x] **GIT NOTE:** Tier 2 introduced this bug in their v2 work. Re-ran `git log -p --all -S "LEGACY_NAMES"` to find the original definition and restored it.
- [x] **Task 0.2** [Tier 3]: Create the `latest` symlink for `audit_code_path_audit_coverage.py`
- HOW: `New-Item -ItemType SymbolicLink -Path docs/reports/code_path_audit/latest -Target <most-recent>`
- Most recent: identify via `ls docs/reports/code_path_audit/ | Sort-Object | Select-Object -Last 1`
- SAFETY: `uv run python scripts/audit_code_path_audit_coverage.py --input-dir docs/reports/code_path_audit/latest --strict` exits 0
- [x] **COMMIT 0.2:** `fix(audit): create docs/reports/code_path_audit/latest symlink` (Tier 3)
- [x] **GIT NOTE:** Tier 2 ran the type registry regeneration but didn't create the symlink. This fixes the audit gate.
## Phase 1: Update v2 spec (Tier 1, 1 commit)
**Focus:** The 2 spec corrections (VC2 patch_modal.py as data module; VC10 162-line trade-off).
- [x] **Task 1.1** [Tier 1]: Edit `conductor/tracks/module_taxonomy_refactor_20260627/spec.md` to update VC2 and VC10
- VC2: add note that patch_modal.py is a data module (DiffHunk, DiffFile, PendingPatch) per data/view/ops split
- VC10: accept 162-line models.py as the trade-off for backward compat (the 30-line target was unrealistic)
- [x] **COMMIT 1.1:** `docs(spec): correct VC2 + VC10 in module_taxonomy_refactor_20260627 spec` (Tier 1)
- [x] **GIT NOTE:** v2 spec corrections per `FOLLOWUP_module_taxonomy_v2_review`. VC2 now acknowledges patch_modal.py as a data module. VC10 now accepts 162-line models.py as the backward-compat trade-off.
## Phase 2: Remove `__getattr__` shim from `models.py` (Tier 3, 1-2 commits)
**Focus:** The biggest de-cruft task. The `__getattr__` shim preserves backward compat for 30+ legacy imports. Removing it requires updating those imports.
- [x] **Task 2.1** [Tier 3]: Inventory all `from src.models import X` for the moved classes (Ticket, Track, WorkerContext, TrackState, TrackMetadata, ThinkingSegment, ProjectContext, FileItem, Preset, ContextPreset, ContextFileEntry, NamedViewPreset, Tool, ToolPreset, BiasProfile, TextEditorConfig, ExternalEditorConfig, Persona, WorkspaceProfile, MCPServerConfig, MCPConfiguration, VectorStoreConfig, RAGConfig, load_mcp_config, Persona, etc.)
- HOW: `git grep "from src.models import" -- 'src/*.py' 'tests/*.py'`
- [x] **Task 2.2** [Tier 3]: Update consumer sites to use direct imports (per class, migrate to the right subsystem file)
- MMA Core: `from src.mma import ...`
- ProjectContext: `from src.project import ...`
- FileItem + Preset + ContextPreset + etc: `from src.project_files import ...`
- Tool + ToolPreset: `from src.tool_presets import ...`
- BiasProfile: `from src.tool_bias import ...`
- TextEditorConfig + ExternalEditorConfig: `from src.external_editor import ...`
- Persona: `from src.personas import ...`
- WorkspaceProfile: `from src.workspace_manager import ...`
- MCP config: `from src.mcp_client import ...`
- [x] **Task 2.3** [Tier 3]: Remove the `__getattr__` shim from `src/models.py`
- HOW: `manual-slop_edit_file` to remove the function
- SAFETY: `uv run python -m pytest tests/test_*.py -v` to verify no consumer broke
- [x] **COMMIT 2.1:** `refactor(models): remove __getattr__ shim; 30+ consumer sites now use direct imports` (Tier 3)
- [x] **GIT NOTE:** After migration, `from src.models import X` for moved classes raises `ImportError`. The legacy compat shim is no longer needed.
## Phase 3: Move `DEFAULT_TOOL_CATEGORIES` to `src/ai_client.py` (Tier 3, 1 commit)
**Focus:** A single dict moves; single consumer (app_controller.py).
- [x] **Task 3.1** [Tier 3]: Move `DEFAULT_TOOL_CATEGORIES` from `src/models.py` to `src/ai_client.py`
- HOW: `manual-slop_edit_file` to add the dict to `src/ai_client.py`; remove from `src/models.py`
- Update consumer: `src/app_controller.py` to `from src.ai_client import DEFAULT_TOOL_CATEGORIES`
- SAFETY: `uv run python -m pytest tests/test_app_controller_*.py -v`
- [x] **COMMIT 3.1:** `refactor(ai_client): move DEFAULT_TOOL_CATEGORIES from models.py to ai_client.py` (Tier 3)
- [x] **GIT NOTE:** `DEFAULT_TOOL_CATEGORIES` is a categorization of MCP tools; the AI client is the natural owner. Single consumer (app_controller.py).
## Phase 4: Move Pydantic proxies to `src/api_hooks.py` (Tier 3, 1 commit)
**Focus:** The Pydantic proxies (`_create_generate_request`, `_create_confirm_request`, the Pydantic-specific `__getattr__`) are API-specific.
- [x] **Task 4.1** [Tier 3]: Move the Pydantic proxies from `src/models.py` to `src/api_hooks.py`
- HOW: `manual-slop_edit_file` to add the proxies to `src/api_hooks.py`; remove from `src/models.py`
- Update consumer sites: `src/api_hooks.py` (uses the proxies to create the request models); `src/api_hook_client.py` (uses for client-side validation)
- SAFETY: `uv run python -m pytest tests/test_api_hooks*.py tests/test_api_hook_client*.py -v`
- [x] **COMMIT 4.1:** `refactor(api_hooks): move Pydantic proxies from models.py to api_hooks.py` (Tier 3)
- [x] **GIT NOTE:** Pydantic proxies are API-specific; they belong with `api_hooks.py`. 2 consumer sites updated.
## Phase 5: Standardize ImGui usage (Tier 3, 1 commit per file = 4 commits)
**Focus:** The 4 files that use ImGui directly (not through `imgui_scopes.py` context managers).
- [x] **Task 5.1** [Tier 3]: Refactor `src/markdown_helper.py` to use `imgui_scopes.py` context managers
- [x] **Task 5.2** [Tier 3]: Refactor `src/theme_2.py` to use `imgui_scopes.py` context managers
- [x] **Task 5.3** [Tier 3]: Refactor `src/theme_nerv.py` to use `imgui_scopes.py` context managers
- [x] **Task 5.4** [Tier 3]: Refactor `src/theme_nerv_fx.py` to use `imgui_scopes.py` context managers
- [x] **COMMITS 5.1-5.4:** One per file
## Phase 6: Verification (Tier 2, 1-2 commits)
- [x] **Task 6.1** [Tier 2]: Run all 13 VCs
- VC1: generate_type_registry.py --check exits 0
- VC2: audit_code_path_audit_coverage.py --input-dir docs/reports/code_path_audit/latest --strict exits 0
- VC3: All 7 audit gates pass --strict
- VC4: 10/11 batched test tiers pass
- VC5: __getattr__ shim removed
- VC6: DEFAULT_TOOL_CATEGORIES moved
- VC7: Pydantic proxies moved
- VC8: ImGui usage standardized
- VC9: src/models.py reduced to <=20 lines
- VC10: All consumer sites updated to direct imports
- VC11: v2 spec updated
- VC12: All 7 audit gates pass --strict (re-verify)
- VC13: 10/11 batched test tiers pass (re-verify)
- Document in `docs/reports/TRACK_COMPLETION_post_module_taxonomy_de_cruft_20260627.md`
- [x] **COMMIT 6.1:** `conductor(state): post_module_taxonomy_de_cruft_20260627 SHIPPED` (Tier 2)
- [x] **COMMIT 6.2:** `docs(reports): TRACK_COMPLETION_post_module_taxonomy_de_cruft_20260627` (Tier 2)
## Commit Log (Expected, 12-15 atomic commits)
1. (Phase 0) `fix(generate_type_registry): define LEGACY_NAMES to fix NameError` (Tier 3)
2. (Phase 0) `fix(audit): create docs/reports/code_path_audit/latest symlink` (Tier 3)
3. (Phase 1) `docs(spec): correct VC2 + VC10 in module_taxonomy_refactor_20260627 spec` (Tier 1)
4. (Phase 2) `refactor(models): remove __getattr__ shim; 30+ consumer sites now use direct imports` (Tier 3)
5. (Phase 3) `refactor(ai_client): move DEFAULT_TOOL_CATEGORIES from models.py to ai_client.py` (Tier 3)
6. (Phase 4) `refactor(api_hooks): move Pydantic proxies from models.py to api_hooks.py` (Tier 3)
7. (Phase 5) `refactor(markdown_helper): use imgui_scopes.py context managers` (Tier 3)
8. (Phase 5) `refactor(theme_2): use imgui_scopes.py context managers` (Tier 3)
9. (Phase 5) `refactor(theme_nerv): use imgui_scopes.py context managers` (Tier 3)
10. (Phase 5) `refactor(theme_nerv_fx): use imgui_scopes.py context managers` (Tier 3)
11. (Phase 6) `conductor(state): post_module_taxonomy_de_cruft_20260627 SHIPPED` (Tier 2)
12. (Phase 6) `docs(reports): TRACK_COMPLETION_post_module_taxonomy_de_cruft_20260627` (Tier 2)
Plus per-task plan-update commits per the workflow.
## Verification Commands (run at end of each phase + Phase 6)
```bash
# VC1: generate_type_registry.py --check exits 0
uv run python scripts/generate_type_registry.py --check
$? # expect: 0
# VC2: audit_code_path_audit_coverage.py exits 0
uv run python scripts/audit_code_path_audit_coverage.py --input-dir docs/reports/code_path_audit/latest --strict
$? # expect: 0
# VC3: All 7 audit gates pass --strict
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
# VC4: 10/11 batched test tiers pass
uv run python scripts/run_tests_batched.py
# Expect: 10/11 PASS
# VC5: __getattr__ shim removed
git grep "__getattr__" HEAD -- src/models.py
# Expect: 0 hits
# VC6: DEFAULT_TOOL_CATEGORIES moved
git grep "DEFAULT_TOOL_CATEGORIES" HEAD -- src/models.py
# Expect: 0 hits
git grep "DEFAULT_TOOL_CATEGORIES" HEAD -- src/ai_client.py
# Expect: >= 1 hit
# VC7: Pydantic proxies moved
git grep "_create_generate_request" HEAD -- src/models.py
# Expect: 0 hits
git grep "_create_generate_request" HEAD -- src/api_hooks.py
# Expect: >= 1 hit
# VC8: ImGui usage standardized
git grep "imgui\." HEAD -- src/markdown_helper.py src/theme_2.py src/theme_nerv.py src/theme_nerv_fx.py | grep -v "from imgui"
# Expect: only context-manager usage (no direct begin_/end_ pairs)
# VC9: models.py reduced
Measure-Object -Line src/models.py
# Expect: <= 20
# VC10: All consumer sites updated
git grep "from src.models import" HEAD -- src/*.py tests/*.py | grep -v Metadata
# Expect: 0 hits for the moved classes
```
## Notes for Tier 3 workers
- **Phase 0 is critical** — these are bugs Tier 2 introduced. Fix them FIRST.
- **Phase 2 (remove `__getattr__` shim) is the biggest task** — there are 30+ consumer sites. Use `git grep` to find them all. Update them per the migration pattern.
- **Phase 5 (ImGui standardization) is per-file** — 4 commits, 1 per file. Each file has its own tests; verify after each.
- **Style** — 1-space indentation, CRLF line endings, no comments, use `manual-slop_edit_file`.
- **Per-phase regression-guard test runs** — after each phase, run the affected tests. If a phase causes a regression, REVERT the phase commit and investigate (don't try to fix forward).
- **The `git stash*` ban is in effect** at 3 layers. Do not use `git stash` for any reason. If you need a "fresh start" feel, create a new branch.
- **The timeline-is-immutable principle** — never use `git revert` / `git reset` / `git stash` to "undo" a bad commit. Write a forward corrective commit instead.
- **Phase 1 (spec update) is by Tier 1** — Tier 3 should NOT modify the v2 spec. The Tier 1 update reflects the user's acceptance of the trade-offs.
## Notes for Tier 2 reviewer
- **The 2 critical bugs in Phase 0 are the priority** — they broke the audit gates. Fix them FIRST.
- **The v2 spec update in Phase 1** is by Tier 1. Tier 2 should NOT modify the spec.
- **Phase 2 is the most invasive** — removing the `__getattr__` shim changes the import surface for 30+ consumer sites. Run the full batched test suite after each consumer-site update.
- **Phase 5 (ImGui standardization) is per-file** — 4 commits, 1 per file. Verify after each.
- **Total: 12 atomic commits** (matches the spec's expected commit count).
## See also
- `conductor/tracks/post_module_taxonomy_de_cruft_20260627/spec.md` — the canonical reference
- `conductor/tracks/module_taxonomy_refactor_20260627/spec.md` — the v2 spec that this track follows up on
- `docs/reports/FOLLOWUP_module_taxonomy_v2_review.md` — the review identifying these tasks
- `docs/reports/FOLLOWUP_module_taxonomy_refactor_20260627_recoverable.md` — the recovery report
- `AGENTS.md` (File Size and Naming Convention HARD RULE)
- `conductor/code_styleguides/data_oriented_design.md` (Prefer Fewer Types principle)
@@ -0,0 +1,204 @@
# Track Specification: post_module_taxonomy_de_cruft_20260627
## Overview
Followup to module_taxonomy_refactor_20260627. After the taxonomy is settled, clean up the remaining cruft that v2 was explicitly out-of-scope for. Two critical bugs from v2 must be fixed first; then 4 de-cruft tasks address the __getattr__ shim, DEFAULT_TOOL_CATEGORIES, Pydantic proxies, and the patch_modal.py data module issue.
## Current State Audit (master 6344b49f, measured 2026-06-27)
| Metric | Value | Source |
|---|---:|---|
| src/models.py line count | 162 | wc -l src/models.py (spec target was 30) |
| LEGACY_NAMES in generate_type_registry.py | BROKEN | LEGACY_NAMES referenced but not defined (Tier 2 introduced this bug) |
| docs/reports/code_path_audit/latest symlink | MISSING | required by audit_code_path_audit_coverage.py |
| patch_modal.py | 115 lines, EXISTS | data module (DiffHunk, DiffFile, PendingPatch) per data/view/ops split; spec was wrong to require deletion |
| src/models.py content | __getattr__ shim + DEFAULT_TOOL_CATEGORIES + Pydantic proxies | still has cruft |
| v2 audit gates | 5/7 pass | 2 broken (NameError + missing symlink) |
## Goals
| ID | Goal | Acceptance |
|---|---|---|
| G1 | Fix the NameError: LEGACY_NAMES bug in generate_type_registry.py | generate_type_registry.py --check exits 0 |
| G2 | Create the latest symlink for audit_code_path_audit_coverage.py | audit_code_path_audit_coverage.py --input-dir docs/reports/code_path_audit/latest --strict exits 0 |
| G3 | Update VC2 in the v2 spec to acknowledge patch_modal.py is a data module (not a LEAK) | spec.md reflects the data module status |
| G4 | Update VC10 in the v2 spec to accept 162-line models.py (backward compat trade-off) | spec.md reflects the trade-off |
| G5 | All 7 audit gates pass --strict | Same as v2 baseline |
| G6 | 10/11 batched test tiers pass (RAG flake acceptable) | Same as v2 baseline |
| G7 | Remove the __getattr__ shim from src/models.py as consumers migrate to direct imports | __getattr__ function removed; 30+ consumer sites updated |
| G8 | Move DEFAULT_TOOL_CATEGORIES to src/ai_client.py | DEFAULT_TOOL_CATEGORIES removed from src/models.py; from src.ai_client import DEFAULT_TOOL_CATEGORIES works |
| G9 | Move Pydantic proxies to src/api_hooks.py | _create_generate_request, _create_confirm_request moved; from src.api_hooks import GenerateRequest, ConfirmRequest works |
| G10 | Refactor ImGui usage in markdown_helper.py, theme_2.py, theme_nerv.py, theme_nerv_fx.py to use the imgui_scopes.py context manager pattern uniformly | All imgui.begin_/imgui.end_ calls go through imgui_scopes.py |
| G11 | src/models.py reduced to 20 lines (just docstring + imports) | After G7+G8+G9, models.py is essentially empty |
## Non-Goals
- The 4-criteria rule itself (established in v2)
- The data/view/ops split (established in v2)
- The __getattr__ legacy migration shim back from subsystem files (the shim is being REMOVED)
- Refactoring aggregate.py (513 lines), app_controller.py (4869 lines), gui_2.py (7773 lines)
- The RAG test pre-existing flake
- The v2 spec rewriting (it was a track artifact, not a commit in the v2 branch)
## Functional Requirements
### FR1: Fix the NameError: LEGACY_NAMES bug
The bug is in scripts/generate_type_registry.py. The LEGACY_NAMES variable is referenced but not defined. The fix is to either:
- Define the variable before it's referenced
- Remove the reference if it's not needed
- Import it from the correct module
**Action:**
1. Use git log -p --all -S LEGACY_NAMES to find the original definition
2. Add the missing definition or remove the reference
3. Re-run generate_type_registry.py --check to verify
### FR2: Create the latest symlink
The audit_code_path_audit_coverage.py script expects a latest symlink in docs/reports/code_path_audit/. The symlink should point to the most recent audit output (e.g., 2026-06-22).
**Action:**
1. Identify the most recent audit output directory
2. Create the symlink pointing to the most recent
3. Re-run audit_code_path_audit_coverage.py --input-dir docs/reports/code_path_audit/latest --strict
### FR3: Update VC2 in the v2 spec
The current VC2 says 5 ImGui LEAK files deleted. The v2 spec didn't account for patch_modal.py being a data module. Update VC2 to acknowledge that patch_modal.py is a data module, not a LEAK.
**Action:** edit the v2 spec to update the VC2 line to:
```
VC2: 4 ImGui LEAK files deleted (bg_shader, shaders, command_palette, diff_viewer).
patch_modal.py is NOT a LEAK — it's a data module (DiffHunk/DiffFile/PendingPatch)
per the data/view/ops split rule. The diff_viewer classes were moved INTO it
during the cruft_elimination track's split; deleting it would violate the
data module's integrity.
```
### FR4: Update VC10 in the v2 spec
The current VC10 says src/models.py reduced to 30 lines. Tier 2 hit 162 lines because of backward compat. Update VC10 to accept the trade-off.
**Action:** edit the spec to:
```
VC10: src/models.py reduced from 1044 to 200 lines (achieves backward compat
for 30+ legacy imports via __getattr__ lazy-load shim). The 30-line target
was unrealistic given the legacy import surface; 162 lines is the accepted
trade-off. Full migration to direct imports is FR7 in the
post_module_taxonomy_de_cruft_20260627 follow-up track.
```
### FR5: Remove the __getattr__ shim (de-cruft)
The __getattr__ in src/models.py lazy-loads moved classes on first access. To remove it, update the ~30 consumer sites to import directly from subsystem files.
**Consumer sites:** tests/test_*.py and src/app_controller.py, src/aggregate.py, etc.
**Migration pattern:**
```python
# OLD:
from src.models import Ticket
# NEW:
from src.mma import Ticket
```
### FR6: Move DEFAULT_TOOL_CATEGORIES to src/ai_client.py
DEFAULT_TOOL_CATEGORIES is a categorization of MCP tools, which is the AI client's domain. Move it from src/models.py to src/ai_client.py.
**Consumer site:** src/app_controller.py uses DEFAULT_TOOL_CATEGORIES.
### FR7: Move Pydantic proxies to src/api_hooks.py
The Pydantic proxies (_create_generate_request, _create_confirm_request, the Pydantic-specific __getattr__) are API-specific. Move them from src/models.py to src/api_hooks.py.
**Consumer sites:** src/api_hooks.py, src/api_hook_client.py
### FR8: Standardize ImGui usage on imgui_scopes.py context managers
The files src/markdown_helper.py, src/theme_2.py, src/theme_nerv.py, src/theme_nerv_fx.py all use ImGui directly. Standardize on the imgui_scopes.py context manager pattern.
**Pattern:**
```python
# OLD (direct):
imgui.begin("My Window")
# ... content ...
imgui.end()
# NEW (via imgui_scopes):
with imgui.begin("My Window"):
# ... content ...
```
## Non-Functional Requirements
- NFR1: 1-space indentation
- NFR2: CRLF line endings on Windows
- NFR3: 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
## Architecture Reference
- module_taxonomy_refactor_20260627 spec (the v2 4-criteria rule, data/view/ops split)
- module_taxonomy_refactor_20260627 plan (the v2 16-commit plan)
- module_taxonomy_refactor_20260627 TRACK_COMPLETION (Tier 2's report)
- FOLLOWUP_module_taxonomy_v2_review (the review identifying these 2 critical bugs + 4 de-cruft tasks)
- FOLLOWUP_module_taxonomy_refactor_20260627_recoverable (data is NOT lost)
- scripts/generate_type_registry.py (the NameError bug)
- scripts/audit_code_path_audit_coverage.py (the missing latest symlink)
- src/models.py (the file being cleaned up)
- src/imgui_scopes.py (the context manager module for FR8)
## Out of Scope
- The 4-criteria rule itself (established in v2)
- The data/view/ops split (established in v2)
- Merging consumer files into the taxonomy moves (that's the v2 track)
- The RAG test pre-existing flake
- New ImGui-using files (only standardize existing)
- Anything in src/aggregate.py (513 lines), src/app_controller.py (4869 lines), src/gui_2.py (7773 lines)
- The cruft_elimination_20260627 track's work (already SHIPPED)
## Verification Criteria (Definition of Done)
| # | Criterion | Verification |
|---|---|---|
| VC1 | generate_type_registry.py --check exits 0 | $? = 0 after running |
| VC2 | audit_code_path_audit_coverage.py --input-dir docs/reports/code_path_audit/latest --strict exits 0 | $? = 0 after running |
| VC3 | All 7 audit gates pass --strict | 7 gates verified |
| VC4 | 10/11 batched test tiers pass (RAG flake acceptable) | scripts/run_tests_batched.py |
| VC5 | __getattr__ shim removed from src/models.py | grep __getattr__ src/models.py returns 0 hits |
| VC6 | DEFAULT_TOOL_CATEGORIES moved to src/ai_client.py | grep DEFAULT_TOOL_CATEGORIES src/models.py returns 0 hits; grep DEFAULT_TOOL_CATEGORIES src/ai_client.py returns 1 hit |
| VC7 | Pydantic proxies moved to src/api_hooks.py | grep _create_generate_request src/models.py returns 0 hits; grep _create_generate_request src/api_hooks.py returns 1 hit |
| VC8 | ImGui usage standardized in markdown_helper.py, theme_2.py, theme_nerv.py, theme_nerv_fx.py | grep imgui. those files | grep -v "from imgui" returns only context-manager usage |
| VC9 | src/models.py reduced to 20 lines | wc -l src/models.py returns 20 |
| VC10 | All consumer sites updated to direct imports (no from src.models import X for moved classes) | grep "from src.models import" -- src/*.py tests/*.py | grep -v Metadata returns 0 hits for the moved classes |
| VC11 | v2 spec updated to reflect VC2 + VC10 corrections | grep "patch_modal\|backward compat" conductor/tracks/module_taxonomy_refactor_20260627/spec.md returns hits |
| VC12 | All 7 audit gates pass --strict (re-verify after de-cruft) | same as VC3 |
| VC13 | 10/11 batched test tiers pass (re-verify after de-cruft) | same as VC4 |
## Risks
| # | Risk | Likelihood | Mitigation |
|---|---|---|---|
| R1 | Fixing the NameError: LEGACY_NAMES bug breaks other things | low | Run the type registry generation after fix; if it fails, investigate the original definition |
| R2 | The latest symlink doesn't work on Windows (symlink restrictions) | medium | Use a .latest marker file instead of a symlink; update the audit script to read the marker |
| R3 | Removing the __getattr__ shim breaks 30+ consumer sites | high | Per-file migration; run regression tests after each consumer-site update |
| R4 | Moving DEFAULT_TOOL_CATEGORIES breaks app_controller.py | low | Single consumer; update + verify |
| R5 | Moving Pydantic proxies breaks api_hooks.py and api_hook_client.py | low | 2 consumer sites; update + verify |
| R6 | Standardizing ImGui usage in theme/markdown files breaks their tests | medium | Per-file refactor; run theme/markdown tests after each |
| R7 | The v2 spec update is itself a "rewriting commits" pattern | low | The v2 spec is a TRACK ARTIFACT, not a commit in the v2 branch; updates to v2 spec are normal |
## See also
- module_taxonomy_refactor_20260627 spec (the v2 4-criteria rule)
- module_taxonomy_refactor_20260627 plan (16 atomic commits)
- module_taxonomy_refactor_20260627 TRACK_COMPLETION
- FOLLOWUP_module_taxonomy_v2_review (the review identifying these 2 critical bugs)
- FOLLOWUP_module_taxonomy_refactor_20260627_recoverable
- AGENTS.md (File Size and Naming Convention HARD RULE)
@@ -0,0 +1,54 @@
# Track state for post_module_taxonomy_de_cruft_20260627
# Updated by Tier 2 Tech Lead as tasks complete
[meta]
track_id = "post_module_taxonomy_de_cruft_20260627"
name = "Post Module Taxonomy De-Cruft (Fix 2 Critical Bugs + 4 De-Cruft Tasks)"
status = "active"
current_phase = 0
last_updated = "2026-06-27"
[blocked_by]
module_taxonomy_refactor_20260627 = "shipped (v2 was the prerequisite; this track is the followup)"
[blocks]
[phases]
phase_0 = { status = "pending", checkpointsha = "", name = "Fix critical bugs (2 commits: LEGACY_NAMES + latest symlink)" }
phase_1 = { status = "pending", checkpointsha = "", name = "Update v2 spec (1 commit: VC2 + VC10 corrections)" }
phase_2 = { status = "pending", checkpointsha = "", name = "Remove __getattr__ shim (1-2 commits: 30+ consumer sites updated)" }
phase_3 = { status = "pending", checkpointsha = "", name = "Move DEFAULT_TOOL_CATEGORIES to ai_client.py (1 commit)" }
phase_4 = { status = "pending", checkpointsha = "", name = "Move Pydantic proxies to api_hooks.py (1 commit)" }
phase_5 = { status = "pending", checkpointsha = "", name = "Standardize ImGui usage (4 commits: 1 per file)" }
phase_6 = { status = "pending", checkpointsha = "", name = "Verification + end-of-track report" }
[tasks]
t0_1 = { status = "pending", commit_sha = "", description = "Fix the NameError: LEGACY_NAMES bug in scripts/generate_type_registry.py" }
t0_2 = { status = "pending", commit_sha = "", description = "Create the latest symlink for audit_code_path_audit_coverage.py" }
t1_1 = { status = "pending", commit_sha = "", description = "Update VC2 + VC10 in module_taxonomy_refactor_20260627 spec" }
t2_1 = { status = "pending", commit_sha = "", description = "Inventory all from src.models import X for moved classes (Ticket, Track, etc.)" }
t2_2 = { status = "pending", commit_sha = "", description = "Update consumer sites to use direct imports (per class, migrate to right subsystem file)" }
t2_3 = { status = "pending", commit_sha = "", description = "Remove the __getattr__ shim from src/models.py" }
t3_1 = { status = "pending", commit_sha = "", description = "Move DEFAULT_TOOL_CATEGORIES from src/models.py to src/ai_client.py" }
t4_1 = { status = "pending", commit_sha = "", description = "Move Pydantic proxies from src/models.py to src/api_hooks.py" }
t5_1 = { status = "pending", commit_sha = "", description = "Refactor src/markdown_helper.py to use imgui_scopes.py context managers" }
t5_2 = { status = "pending", commit_sha = "", description = "Refactor src/theme_2.py to use imgui_scopes.py context managers" }
t5_3 = { status = "pending", commit_sha = "", description = "Refactor src/theme_nerv.py to use imgui_scopes.py context managers" }
t5_4 = { status = "pending", commit_sha = "", description = "Refactor src/theme_nerv_fx.py to use imgui_scopes.py context managers" }
t6_1 = { status = "pending", commit_sha = "", description = "Run all 13 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
phase_6_complete = false
[track_specific]
critical_bugs_count = 2
decruft_tasks_count = 4
files_to_modify = 9
symlinks_to_create = 1
estimated_commits = 12