From ba1dbd326fb894d55fe83a11bad9ae5f98b38ed4 Mon Sep 17 00:00:00 2001 From: Ed_ Date: Sun, 5 Jul 2026 19:33:20 -0400 Subject: [PATCH] =?UTF-8?q?conductor(track):=20init=20test=5Fsuite=5Fclean?= =?UTF-8?q?up=5Fgemini=5Fcli=5Fremoval=5F20260705=20=E2=80=94=203-front=20?= =?UTF-8?q?cleanup=20track?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 3 fronts, 3 phases, 31 tasks, 12 verification criteria. Based on 3 parallel explore-agent audits of the live codebase. Front A — Gemini CLI Adapter Removal: delete src/gemini_cli_adapter.py + 7 test files; edit ai_client.py (3 functions + 8 dispatch branches + PROVIDERS 8->7); edit app_controller.py (~11 sites) + gui_2.py (2 blocks) + project_manager.py + api_hooks.py; introduce a mock provider that routes to tests/mock_gemini_cli.py so the 9 live_gui sim tests switch from gemini_cli to mock without losing their mock-LLM mechanism; update 7 docs + 5 conductor docs. Front B — Test Suite Cleanup (410 files, 2,133 tests, ~45-60 files downsizable): delete 2 guaranteed-broken chronology tests (import from deleted scripts.audit.*); consolidate 7 test_scavenge_*.py tautologies into 1 test_directive_structure.py; review deprecated-module tests; consolidate ~15 test_*_phase*.py one-offs; migrate 27 src.models shim importers to direct subsystem imports; extract shared mock_controller fixture from ~8 boilerplate-patch files; fix 3 fix-not-skip candidates (Gemini 503 in summarize.summarise_file); audit the 120KB test_gui_2_result.py (9.4% of suite line count in one file). Front C — Metadata-Type Reduction: flip the 38-site MCP dispatch inversion (dispatch()+22 consumers still call str wrappers, not the _result variants); migrate app_controller.py's ~40 in-memory Metadata state sites to typed per-aggregate dataclasses; fix aggregate.py file_items: list[Metadata] -> list[FileItem]; delete dead code (openai_schemas.to_legacy_dict, app_controller._push_mma_state_update). Out of scope: GEMINI_CLI_HOOK_CONTEXT env var + cli_tool_bridge.py + mma_exec.py (meta-tooling, not the provider — separate follow-up if user wants to purge naming). --- .../metadata.json | 127 +++++++++++ .../plan.md | 207 ++++++++++++++++++ .../spec.md | 164 ++++++++++++++ .../state.toml | 105 +++++++++ 4 files changed, 603 insertions(+) create mode 100644 conductor/tracks/test_suite_cleanup_gemini_cli_removal_20260705/metadata.json create mode 100644 conductor/tracks/test_suite_cleanup_gemini_cli_removal_20260705/plan.md create mode 100644 conductor/tracks/test_suite_cleanup_gemini_cli_removal_20260705/spec.md create mode 100644 conductor/tracks/test_suite_cleanup_gemini_cli_removal_20260705/state.toml diff --git a/conductor/tracks/test_suite_cleanup_gemini_cli_removal_20260705/metadata.json b/conductor/tracks/test_suite_cleanup_gemini_cli_removal_20260705/metadata.json new file mode 100644 index 00000000..53290fe0 --- /dev/null +++ b/conductor/tracks/test_suite_cleanup_gemini_cli_removal_20260705/metadata.json @@ -0,0 +1,127 @@ +{ + "track_id": "test_suite_cleanup_gemini_cli_removal_20260705", + "name": "Test Suite Cleanup + Gemini CLI Adapter Removal + Metadata-Type Reduction", + "status": "active", + "branch": "master", + "created": "2026-07-05", + "owner": "Tier 1 (initialized); implementation delegated to Tier 2/3.", + "blocked_by": [], + "blocks": [], + "scope": { + "new_files": [ + "src/ai_client.py (mock provider _send_mock added — not a new file; in-place edit)", + "tests/test_directive_structure.py (consolidation of the 7 scavenge files)", + "tests/fixtures/mock_controller.py or conftest.py fixture (consolidation of the boilerplate patch block)", + "docs/reports/TRACK_COMPLETION_test_suite_cleanup_gemini_cli_removal_20260705.md" + ], + "modified_files": [ + "src/ai_client.py (gemini_cli removal + mock provider + dispatch branches)", + "src/app_controller.py (gemini_cli removal + Metadata in-memory state migration)", + "src/gui_2.py (gemini_cli panel removal)", + "src/project_manager.py (gemini_cli default config removal)", + "src/api_hooks.py (gemini_cli auto-start simplification)", + "src/mcp_client.py (38 str wrappers deleted; dispatch() flipped to _result)", + "src/aggregate.py (list[Metadata] -> list[FileItem])", + "src/personas.py, src/workspace_manager.py, src/orchestrator_pm.py (scattered Metadata field triage)", + "src/openai_schemas.py (to_legacy_dict deleted)", + "tests/ (~45-60 files deleted/consolidated/migrated)", + "docs/guide_ai_client.md, guide_architecture.md, guide_simulations.md, guide_models.md, guide_context_aggregation.md, guide_tools.md, Readme.md", + "conductor/tech-stack.md, product.md, product-guidelines.md, workflow.md, code_styleguides/error_handling.md" + ], + "deleted_files": [ + "src/gemini_cli_adapter.py", + "tests/test_gemini_cli_adapter.py", + "tests/test_gemini_cli_adapter_parity.py", + "tests/test_gemini_cli_integration.py", + "tests/test_gemini_cli_parity_regression.py", + "tests/test_gemini_cli_edge_cases.py", + "tests/test_mock_gemini_cli.py", + "tests/test_ai_client_cli.py", + "tests/test_generate_chronology.py", + "tests/test_chronology_quality_gate.py", + "tests/test_scavenge_batch_1.py through test_scavenge_batch_5.py", + "tests/test_scavenge_directives_lift.py", + "tests/test_scavenge_superpowers.py", + "tests/test_ai_client_list_models.py (if the only test is the gemini_cli one)" + ] + }, + "estimated_effort": { + "method": "scope (per workflow.md Tier 1 Track Initialization Rules. NO day estimates.)", + "phase_1": "11 tasks: gemini_cli removal (src + tests + docs) + mock provider + 9 sim test rewrites + checkpoint", + "phase_2": "9 tasks: chronology test deletion + scavenge consolidation + deprecated-module review + phase-named consolidation + shim migration + mock_controller fixture + fix-not-skip + gui_2_result audit + checkpoint", + "phase_3": "11 tasks: MCP dispatch flip + app_controller state migration + aggregate.py FileItem + scattered Metadata triage + dead code deletion + test fixture migration + docs + audits + batch + completion report + user verification + chronology row" + }, + "verification_criteria": [ + "VC1: src/gemini_cli_adapter.py does not exist; grep -r 'gemini_cli' src/ returns only meta-tooling env-var references (or nothing)", + "VC2: PROVIDERS in src/ai_client.py has 7 entries (no gemini_cli)", + "VC3: tests/test_generate_chronology.py + tests/test_chronology_quality_gate.py do not exist", + "VC4: the 7 test_scavenge_*.py files do not exist; tests/test_directive_structure.py exists and checks the general invariant", + "VC5: grep -r 'from src.models import' tests/ returns only the 2 self-test files (test_models_no_top_level_*.py)", + "VC6: grep -r 'list\\[Metadata\\]' src/app_controller.py returns nothing", + "VC7: src/mcp_client.py has no str-returning wrappers (the 38 are deleted; dispatch() returns Result)", + "VC8: src/aggregate.py uses list[FileItem], not list[Metadata]", + "VC9: the 3 fix-not-skip tests are fixed (no @pytest.mark.skip for the Gemini 503 reason)", + "VC10: the 4 audit scripts pass", + "VC11: the full test suite batch run passes (or pre-existing failures documented)", + "VC12: src/openai_schemas.py:108 to_legacy_dict() is deleted" + ], + "regressions_and_pre_existing_failures": [], + "pre_existing_failures_remaining": [], + "deferred_to_followup_tracks": [ + { + "title": "Meta-tooling GEMINI_CLI_HOOK_CONTEXT env var purge", + "description": "The GEMINI_CLI_HOOK_CONTEXT env var + scripts/cli_tool_bridge.py + scripts/mma_exec.py + docs/guide_meta_boundary.md are meta-tooling (external agent bridge), NOT the provider. If the user wants to purge the naming, that's a separate track.", + "track_status": "not yet initialized; depends on user decision" + }, + { + "title": "Full mock provider implementation", + "description": "This track introduces just enough of a mock provider to keep the 9 sim tests working. A full mock-provider implementation (configurable responses, error injection, latency simulation) is a future track.", + "track_status": "future; depends on user demand" + }, + { + "title": "RAG return type follow-up (typed_rag_return_type_followup)", + "description": "From the archive review: rag_engine.search() returns List[Dict[str, Any]]; RAGChunk exists but consumers read dict keys. Adjacent to GAP-C2 but not bundled (RAG boundary is its own scope).", + "track_status": "future; from ARCHIVE_REVIEW_20260705.md item #1" + }, + { + "title": "Typed tool builders follow-up (typed_tool_builders_followup)", + "description": "From the archive review: per-vendor tool builders construct wire-format dicts directly; ToolDefinition exists but isn't used. Adjacent to GAP-C2 but not bundled.", + "track_status": "future; from ARCHIVE_REVIEW_20260705.md item #2" + } + ], + "risk_register": [ + { + "id": "R1", + "description": "The 9 sim test rewrites (gemini_cli -> mock) break the live_gui fixture's session-scoped state", + "likelihood": "medium", + "impact": "the batch run fails on the sim tests", + "mitigation": "the mock provider uses the same mock_gemini_cli.py script; the only change is the provider name. Test in isolation first, then in the full batch per the Isolated-Pass Verification Fallacy rule." + }, + { + "id": "R2", + "description": "The MCP dispatch flip (Task 3.1) breaks 22 consumer call sites", + "likelihood": "medium", + "impact": "the batch run fails on aggregate.py/gui_2.py/app_controller.py tests", + "mitigation": "do it in sub-commits (aggregate.py first, then gui_2.py, then delete the wrappers); test after each sub-commit" + }, + { + "id": "R3", + "description": "The app_controller.py state migration (Task 3.2) breaks tests that construct Metadata({...}) fixtures", + "likelihood": "high", + "impact": "the tests fail at fixture construction", + "mitigation": "Task 3.6 migrates the test fixtures; do it immediately after Task 3.2, not at the end" + }, + { + "id": "R4", + "description": "test_gui_2_result.py (120KB) audit reveals it's all current behavior — no deletion possible", + "likelihood": "low", + "impact": "the file stays large; Front B's downsizing target is reduced", + "mitigation": "the audit is the task; even if no deletion is possible, the split into per-feature files is still a win for navigability" + } + ], + "research_artifacts": { + "gemini_cli_audit": "The explore-agent inventory of all gemini_cli references (file:line, grouped by file) — attached as track research.", + "test_suite_audit": "The explore-agent cruft map (410 files, 2,133 tests, top 20 largest, 7 skips, 74 Metadata refs, 35 src.models importers, 100+ mock.patch sites, duplicates) — attached as track research.", + "legacy_api_audit": "The explore-agent legacy-debt audit (send() current signature, the 38 str wrappers, the 27 src.models importers, the 69 dict[str, Any] sites, the 380 Metadata refs across 22 files, the dead code) — attached as track research." + } +} \ No newline at end of file diff --git a/conductor/tracks/test_suite_cleanup_gemini_cli_removal_20260705/plan.md b/conductor/tracks/test_suite_cleanup_gemini_cli_removal_20260705/plan.md new file mode 100644 index 00000000..b2cfc15e --- /dev/null +++ b/conductor/tracks/test_suite_cleanup_gemini_cli_removal_20260705/plan.md @@ -0,0 +1,207 @@ +# Plan: Test Suite Cleanup + Gemini CLI Adapter Removal + Metadata-Type Reduction + +Track: `test_suite_cleanup_gemini_cli_removal_20260705` +Branch: master +Spec: `conductor/tracks/test_suite_cleanup_gemini_cli_removal_20260705/spec.md` + +3 fronts, 3 phases. Front A (Gemini CLI removal) first because it deletes test files + rewrites 9 more — the entry point for Front B (test cleanup). Front C (metadata reduction) last because it's the largest production-code change + the test cleanup needs to reflect the typed-dataclass migration. + +--- + +## Phase 1: Front A — Gemini CLI Adapter Removal + +Focus: delete the adapter module + the provider registration + the GUI panel + the test files. Introduce the `mock` provider for the 9 sim tests that used `gemini_cli` + `mock_gemini_cli.py`. + +- [ ] **Task 1.1: Delete `src/gemini_cli_adapter.py`** + +WHERE: `src/gemini_cli_adapter.py` (193 lines, entire file). +WHAT: `git rm src/gemini_cli_adapter.py`. +VERIFY: `Test-Path src/gemini_cli_adapter.py` returns False. + +- [ ] **Task 1.2: Edit `src/ai_client.py` — remove the import, PROVIDERS entry, module state, 3 functions, 8 dispatch branches** + +WHERE: `src/ai_client.py` lines 49, 62, 164, 1727-1735, 2130-2241, 1857-1877, 556-561, 629, 914, 3302, 3306, 3394-3398, 3505-3509, 3556-3559. +WHAT: Per the audit inventory (GAP-A2). Carefully distinguish `_gemini_cli_adapter` (REMOVE) from `_gemini_client` / `_ensure_gemini_client` (KEEP — direct Gemini SDK). +HOW: Use `manual-slop_py_update_definition` for the 3 function removals; `manual-slop_edit_file` for the dispatch branches + import + PROVIDERS + module state. +VERIFY: `python -c "from src.ai_client import PROVIDERS; print(PROVIDERS)"` prints 7 entries (no `gemini_cli`). + +- [ ] **Task 1.3: Edit `src/app_controller.py` — remove the ~11 gemini_cli sites** + +WHERE: `src/app_controller.py` lines 574-575, 1084, 1124, 1316, 1836-1840, 2022-2023, 2725-2729, 2932, 3215, 4124. +WHAT: Per GAP-A3 — remove `ui_gemini_cli_path` state field, settable/gettable map entries, `_update_gcli_adapter()` method, project load/save, init. +VERIFY: `grep "gemini_cli" src/app_controller.py` returns nothing. + +- [ ] **Task 1.4: Edit `src/gui_2.py` — remove the 2 gemini_cli blocks** + +WHERE: `src/gui_2.py` lines 2940-2947 (ASCII comment) + 3008-3025 (provider panel block). +WHAT: Delete both blocks. +VERIFY: `grep "gemini_cli" src/gui_2.py` returns nothing. + +- [ ] **Task 1.5: Edit `src/project_manager.py:126` + `src/api_hooks.py:88, 941-942`** + +WHERE: `src/project_manager.py:126` (delete the default config entry) + `src/api_hooks.py:88` (delete the docstring line) + `src/api_hooks.py:941-942` (simplify the HookServer auto-start — the `is_gemini_cli` special case becomes dead). +VERIFY: `grep "gemini_cli" src/project_manager.py src/api_hooks.py` returns nothing. + +- [ ] **Task 1.6: Delete the 7 gemini_cli test files** + +WHERE: `tests/test_gemini_cli_adapter.py`, `tests/test_gemini_cli_adapter_parity.py`, `tests/test_gemini_cli_integration.py`, `tests/test_gemini_cli_parity_regression.py`, `tests/test_gemini_cli_edge_cases.py`, `tests/test_mock_gemini_cli.py`, `tests/test_ai_client_cli.py`. +WHAT: `git rm` all 7. +VERIFY: `Test-Path` returns False for all 7. + +- [ ] **Task 1.7: Introduce the `mock` provider in `src/ai_client.py`** + +WHERE: `src/ai_client.py` — add a `_send_mock()` function + the `"mock"` entry in PROVIDERS (replacing `"gemini_cli"`) + the dispatch branch. +WHAT: The `mock` provider routes to `tests/mock_gemini_cli.py` (the same script the sim tests already use). It returns `Result[str]` like every other provider. It reads the binary path from the same `gcli_path` settable field (renamed to `mock_cli_path` if the user prefers, but keeping `gcli_path` minimizes test churn). +HOW: Mirror the `_send_gemini_cli()` structure but name it `_send_mock()`. The provider name is `"mock"`. +VERIFY: `python -c "from src.ai_client import PROVIDERS; print('mock' in PROVIDERS)"` prints True. + +- [ ] **Task 1.8: Rewrite the 9 sim test files to use `mock` instead of `gemini_cli`** + +WHERE: `tests/test_extended_sims.py`, `tests/test_live_workflow.py`, `tests/test_mma_concurrent_tracks_sim.py`, `tests/test_mma_concurrent_tracks_stress_sim.py`, `tests/test_mma_step_mode_sim.py`, `tests/test_rag_phase4_final_verify.py`, `tests/test_rag_phase4_stress.py`, `tests/test_sim_ai_settings.py`, `tests/test_process_pending_gui_tasks.py`. +WHAT: Replace `set_value('current_provider', 'gemini_cli')` with `set_value('current_provider', 'mock')`. Replace `gcli_path` references if renamed. Keep `mock_gemini_cli.py` + `mock_gcli.bat` (they're now the mock provider's backend). +VERIFY: `grep "gemini_cli" tests/test_extended_sims.py ...` returns nothing across all 9 files. + +- [ ] **Task 1.9: Minor edits in the 6+ gemini_cli-reference test files** + +WHERE: `test_providers_source_of_truth.py` (remove from EXPECTED_PROVIDERS), `test_provider_curation.py` (remove from expected_providers), `test_ai_client_tool_loop_send_func.py` (update comment), `test_mma_tier_usage_reset_fix.py` (remove `ctrl.ui_gemini_cli_path = ""`), `test_rag_integration.py` (remove `app.ui_gemini_cli_path = "gemini"`), `test_ai_loop_regressions_20260614.py` (remove the 3 `_update_gcli_adapter` monkeypatches), `test_live_gui_integration_v2.py` (remove the 2 `_update_gcli_adapter` patches), `test_lazymodule_filedialog_fallback.py` (update comment), `test_discussion_compression.py` (delete the `test_discussion_compression_gemini_cli` test function), `test_ai_client_list_models.py` (delete the `test_list_models_gemini_cli` test function; if it's the only test, delete the file), `test_mock_concurrent_mma.py` (update comments). +VERIFY: `grep -r "gemini_cli" tests/ | grep -v mock_gemini_cli.py | grep -v test_mock` returns nothing (the mock script + its self-test keep the name; everything else is gone). + +- [ ] **Task 1.10: Update the docs + conductor docs** + +WHERE: 7 guide files (`guide_ai_client.md`, `guide_architecture.md`, `guide_simulations.md`, `guide_models.md`, `guide_context_aggregation.md`, `guide_tools.md`, `Readme.md`) + 5 conductor docs (`tech-stack.md`, `product.md`, `product-guidelines.md`, `workflow.md`, `code_styleguides/error_handling.md`). +WHAT: Per GAP-A11 — remove `gemini_cli` from provider lists, delete the Gemini CLI subsections, update the provider count from 8 to 7. Update `guide_simulations.md` to reference the `mock` provider instead of `gemini_cli`. +VERIFY: `grep -r "gemini_cli" docs/guide_*.md docs/Readme.md conductor/tech-stack.md conductor/product.md conductor/workflow.md` returns only the meta-tooling references (or nothing if the user purged those). + +- [ ] **Task 1.11: Phase 1 checkpoint + batch run** + +WHAT: Run the affected test files in batch: `uv run python scripts/run_tests_batched.py --filter test_extended_sims --filter test_live_workflow --filter test_mma_concurrent --filter test_rag_phase4 --filter test_sim_ai_settings --filter test_process_pending --filter test_providers_source --filter test_provider_curation`. +VERIFY: batch green. Commit the Phase 1 checkpoint. + +--- + +## Phase 2: Front B — Test Suite Cleanup + +Focus: delete the guaranteed-broken cruft, consolidate the one-time-verification cruft, review the phase-named one-offs, migrate the legacy shim importers, fix the fix-not-skip candidates. + +- [ ] **Task 2.1: Delete the 2 guaranteed-broken chronology test files** + +WHERE: `tests/test_generate_chronology.py` (205 lines, 20 tests) + `tests/test_chronology_quality_gate.py` (76 lines, 5 tests). +WHAT: `git rm` both. They import from deleted `scripts.audit.*` modules. +VERIFY: `Test-Path` returns False for both. + +- [ ] **Task 2.2: Consolidate the 7 `test_scavenge_*.py` files into one `test_directive_structure.py`** + +WHERE: `tests/test_scavenge_batch_1.py` through `test_scavenge_batch_5.py` + `test_scavenge_directives_lift.py` + `test_scavenge_superpowers.py`. +WHAT: Delete the 7 files. Write `tests/test_directive_structure.py` that checks the general invariant: every directive in `conductor/directives/current_baseline.md` has a `v1.md` + `meta.md` in its directory. This is the ongoing behavioral contract; the per-batch lists were one-time verifications. +VERIFY: `Test-Path tests/test_directive_structure.py` returns True; the 7 scavenge files return False. + +- [ ] **Task 2.3: Review + delete or rewrite the deprecated-module test files** + +WHERE: `tests/test_mma_skeleton.py` (imports from deprecated `scripts/mma_exec`), `tests/test_arch_boundary_phase1.py` (tests deprecated `scripts/mma_exec.py` / `claude_mma_exec.py` hardcoded paths). +WHAT: Review each. If the assertions are still relevant, rewrite to use the OpenCode Task tool (the replacement per workflow.md). If not, delete. +VERIFY: per-file review note in the commit message. + +- [ ] **Task 2.4: Review + consolidate the ~15 `test_*_phase*.py` files** + +WHERE: `test_arch_boundary_phase1/2/3.py`, `test_context_composition_phase3/4/6.py`, `test_gui_phase3/4.py`, `test_mma_agent_focus_phase1/3.py`, `test_code_path_audit_phase78/89.py`, `test_metadata_promotion_phase1.py`, `test_rag_phase4_final_verify.py`, `test_rag_phase4_stress.py`. +WHAT: Review each. Merge still-relevant assertions into the general test file (e.g., `test_code_path_audit.py`). Delete the trivially-green + redundant ones. +VERIFY: per-file review note in the commit message; the general files still pass. + +- [ ] **Task 2.5: Migrate the 27 `src.models` test importers to direct subsystem imports** + +WHERE: 27 test files (per GAP-B5). 3 use `Metadata` (→ `from src.mma import TrackMetadata`). 3 use `PROVIDERS` (→ `from src.ai_client import PROVIDERS`). 20 use `from src import models` bare (→ direct subsystem imports). 2 self-test files remain. +WHAT: Per-file migration. Each is a small edit (change the import line + update the `models.X` references to `X`). +VERIFY: `grep -r "from src.models import" tests/ | grep -v test_models_no_top_level` returns nothing. + +- [ ] **Task 2.6: Extract the shared `mock_controller` fixture from the ~8 boilerplate-patch files** + +WHERE: `test_app_controller_result.py`, `test_discussion_takes_gui.py`, `test_gui_events_v2.py`, `test_gui_synthesis.py`, `test_auto_slices.py`, `test_arch_boundary_phase2.py`, `test_api_hook_extensions.py`, `test_api_events.py` (the 8 files with the `patch('...load_config') + patch('..._init_ai_and_hooks') + patch('..._fetch_models')` block). +WHAT: Extract the boilerplate into a `tests/conftest.py` fixture `mock_controller` (or a `tests/fixtures/mock_controller.py`). Each test file drops the boilerplate + uses the fixture. +VERIFY: the boilerplate block appears in 0 test files (only in the fixture). + +- [ ] **Task 2.7: Fix the 3 fix-not-skip candidates (mock the Gemini 503)** + +WHERE: `tests/test_context_composition_phase6.py` (3 skips) + `tests/test_aggregate_flags.py` (1 skip) — all share the root cause: live Gemini 503 in `summarize.summarise_file`. +WHAT: Mock the Gemini call (patch `summarize.summarise_file` or the underlying `ai_client.send`) to return a canned response. Remove the `@pytest.mark.skip` markers. +VERIFY: `grep -r "Gemini 503" tests/` returns nothing. + +- [ ] **Task 2.8: Audit + split `test_gui_2_result.py` (120KB, 2,329 lines, 101 tests)** + +WHERE: `tests/test_gui_2_result.py` — 9.4% of the suite's line count in one file. +WHAT: Audit whether it's testing current behavior or accumulated GUI regression snapshots. Split into per-feature files (e.g., `test_gui_2_result_rendering.py`, `test_gui_2_result_events.py`, `test_gui_2_result_state.py`). Delete the obsolete snapshots. +VERIFY: the resulting files are each <500 lines; the behavioral assertions still pass. + +- [ ] **Task 2.9: Phase 2 checkpoint + batch run** + +WHAT: Run the full suite batch (per the Isolated-Pass Verification Fallacy — batch green is the only verification that matters): `uv run python scripts/run_tests_batched.py`. +VERIFY: batch green (or pre-existing failures documented). Commit the Phase 2 checkpoint. + +--- + +## Phase 3: Front C — Metadata-Type Reduction + +Focus: flip the MCP dispatch inversion, migrate `app_controller.py` in-memory state to typed dataclasses, fix `aggregate.py` FileItem slippage, delete dead code. + +- [ ] **Task 3.1: Flip the MCP dispatch inversion (38 str wrappers → 39 _result variants)** + +WHERE: `src/mcp_client.py` — the 38 str-returning wrappers (lines ~291-560) + the `dispatch()` function (line 1869) + `async_dispatch()` + 22 external call sites in `aggregate.py` (×12), `gui_2.py` (×9), `app_controller.py` (×1). +WHAT: Update `dispatch()` + `async_dispatch()` to call the `_result` variants directly + return `Result`. Update the 22 consumer call sites to consume `Result` (check `.ok`, use `.data`, handle `.errors`). Delete the 38 str wrappers. +HOW: This is the single largest production-code change in the track. Do it in sub-commits: (a) flip `dispatch()` + the `aggregate.py` call sites; (b) flip `async_dispatch()` + the `gui_2.py` call sites; (c) delete the str wrappers. +VERIFY: `grep -r "def search_files\|def read_file\|def write_file" src/mcp_client.py` returns only the `_result` variants; the str wrappers are gone. `grep "; ".join(e.ui_message()" src/mcp_client.py` returns nothing. + +- [ ] **Task 3.2: Migrate `app_controller.py` in-memory state to typed dataclasses** + +WHERE: `src/app_controller.py` — the ~40 `Metadata`-typed in-memory state collections (GAP-C2): `_pending_gui_tasks`, `_tool_log`, `_tool_stats`, `_cached_cache_stats`, `_token_history`, `_comms_log`, `_pending_comms`, `_pending_tool_calls`, `_pending_history_adds`, `_ask_tool_data`, `_pending_mma_approvals`, `_pending_mma_spawns`, `_token_stats`, `vendor_quota`. Plus `Metadata()` construction at lines 2774, 2778, 3443. +WHAT: Replace each `list[Metadata]` / `Dict[str, Metadata]` / `Metadata = {}` with the corresponding typed per-aggregate dataclass from `type_aliases.py` (`CommsLogEntry`, `HistoryMessage`, `ToolCall`, etc.). If a needed dataclass doesn't exist, add it to `type_aliases.py` (NOT a new `src/.py` per AGENTS.md). +HOW: Per-collection migration in sub-commits. Each collection is its own commit (e.g., "refactor(app_controller): _comms_log: list[Metadata] → list[CommsLogEntry]"). +VERIFY: `grep -r "list\[Metadata\]" src/app_controller.py` returns nothing. `grep -r "Metadata()" src/app_controller.py` returns nothing. + +- [ ] **Task 3.3: Fix `aggregate.py` FileItem slippage** + +WHERE: `src/aggregate.py` — `file_items: list[Metadata]` throughout (`build_file_items`, `_build_files_section_from_items`, `build_markdown_from_items`, `build_tier3_context`, `build_markdown`, `run`) + `NIL_METADATA: Metadata = {}` sentinel at line 50. +WHAT: Change to `list[FileItem]` (the `FileItem` dataclass exists in `src/project_files.py`, aliased in `type_aliases.py:149`). Replace `NIL_METADATA: Metadata = {}` with `NIL_FILE_ITEMS: tuple[FileItem, ...] = ()` (or similar typed empty sentinel). +VERIFY: `grep "list\[Metadata\]" src/aggregate.py` returns nothing. `grep "NIL_METADATA" src/aggregate.py` returns nothing. + +- [ ] **Task 3.4: Triage the scattered non-boundary `Metadata` fields** + +WHERE: `src/personas.py:22` (`preferred_models: list[Metadata]`), `src/workspace_manager.py:16` (`panel_states: Metadata`), `src/orchestrator_pm.py:57` (`generate_tracks(project_config: Metadata) -> list[Metadata]`). +WHAT: Per-site triage. `preferred_models` → `list[ModelEntry]` (define `ModelEntry` in `type_aliases.py` if needed). `panel_states` → a typed panel-state dataclass. `generate_tracks` → typed config + track-entry dataclasses. +VERIFY: per-site commit message documents the chosen type. + +- [ ] **Task 3.5: Delete the dead/deprecated code** + +WHERE: `src/openai_schemas.py:108` (`to_legacy_dict()` — zero callers) + `src/app_controller.py:4973` (`_push_mma_state_update` — DEPRECATED; verify no callers first via `grep -r "_push_mma_state_update[^_]" src/ tests/`). +WHAT: Delete both. +VERIFY: `grep "to_legacy_dict" src/openai_schemas.py` returns nothing. `grep "_push_mma_state_update[^_]" src/ tests/` returns nothing. + +- [ ] **Task 3.6: Migrate the test fixtures that construct `Metadata({...})` to the new typed dataclasses** + +WHERE: any test file that constructs `Metadata({...})` for the collections migrated in Task 3.2. +WHAT: Replace `Metadata({"path": ..., "content": ...})` with the corresponding typed dataclass constructor (`FileItem(path=..., content=...)`, `CommsLogEntry(...)`, etc.). +VERIFY: the tests pass with the new constructors. + +- [ ] **Task 3.7: Update the docs to reflect the Metadata reduction** + +WHERE: `docs/guide_app_controller.md` (the in-memory state section), `docs/guide_mcp_client.md` (the dispatch surface), `docs/guide_models.md` (the Metadata boundary scope), `conductor/code_styleguides/type_aliases.md` (the new typed dataclasses). +WHAT: Document the reduced Metadata scope (TOML/JSON boundary only) + the new typed in-memory state. +VERIFY: the docs reflect the post-migration state. + +- [ ] **Task 3.8: Run the 4 audit scripts + the full test suite batch** + +WHAT: `uv run python scripts/audit_main_thread_imports.py`, `uv run python scripts/audit_no_models_config_io.py`, `uv run python scripts/audit_weak_types.py --strict`, `uv run python scripts/audit_exception_handling.py --strict`. Then `uv run python scripts/run_tests_batched.py`. +VERIFY: all 4 audits pass; the batch is green (or pre-existing failures documented). + +- [ ] **Task 3.9: Phase 3 checkpoint + TRACK_COMPLETION report** + +WHERE: `docs/reports/TRACK_COMPLETION_test_suite_cleanup_gemini_cli_removal_20260705.md`. +WHAT: Per the `tier2_autonomous_sandbox_20260616` precedent — what was done, files deleted/modified, test counts before/after, audit results, deferred items. +VERIFY: report committed + `state.toml` updated to `status = "completed"`. + +- [ ] **Task 3.10: Conductor — User Manual Verification (Protocol in workflow.md)** + +Present the verification results to the user. PAUSE for user confirmation before marking the track complete. + +- [ ] **Task 3.11: Add the chronology row + archive the track** + +WHERE: `conductor/chronology.md` (add a row at the top) + `git mv conductor/tracks/test_suite_cleanup_gemini_cli_removal_20260705/ conductor/archive/`. +WHAT: Per the manual chronology maintenance protocol (no scripts). \ No newline at end of file diff --git a/conductor/tracks/test_suite_cleanup_gemini_cli_removal_20260705/spec.md b/conductor/tracks/test_suite_cleanup_gemini_cli_removal_20260705/spec.md new file mode 100644 index 00000000..f467f653 --- /dev/null +++ b/conductor/tracks/test_suite_cleanup_gemini_cli_removal_20260705/spec.md @@ -0,0 +1,164 @@ +# Track Specification: Test Suite Cleanup + Gemini CLI Adapter Removal + Metadata-Type Reduction + +## Overview + +A three-front cleanup track that downsizes the test suite without losing testing integrity, removes the now-graveyarded Gemini CLI adapter implementation from the codebase, and continues the metadata-type reduction beyond TOML boundaries. The three fronts are tightly coupled: removing the Gemini CLI provider deletes 7 test files + rewrites 9 more, which is the natural entry point for the broader test-suite pruning; the metadata-type reduction is the unfinished migration work the test cleanup needs to reflect. + +**Why these three are bundled:** the user explicitly framed them as one effort — "help me get this test suite downsized without losing testing integrity or coverage" + "the gemini cli adapter impl needs to be removed" + "reduction of metadata type usage beyond toml boundaries." The Gemini CLI removal alone touches ~30 files; the test-suite pruning touches ~45-60 files; the metadata-type reduction touches `app_controller.py`, `aggregate.py`, and ~27 test files. Doing them in one track avoids three rounds of overlapping churn on `tests/` and `src/ai_client.py`. + +## Current State Audit (as of master `0908f8fa`) + +### Already Implemented (DO NOT re-implement) + +- **The Result[T] migration is complete at the public API.** `ai_client.send() -> Result[str]` is canonical; all 9 `_send_` helpers return `Result[str]`; all external callers consume `result.ok`/`result.data`/`result.errors` correctly. (Verified by audit #3.) +- **`Optional[T]` return types are fully banned in `src/mcp_client.py`, `src/ai_client.py`, `src/rag_engine.py`.** Zero violations across all 67 `src/` files. The ban holds. +- **`src/` no longer imports from `src/models.py`** — the production-side migration to per-system files (`src/mma.py`, `src/type_aliases.py`, `src/mcp_tool_specs.py`, `src/result_types.py`) is complete per `module_taxonomy_refactor_20260627`. +- **`scripts/audit/generate_chronology.py` + `chronology_quality_gate.py` were deleted 2026-07-05** (this session, commit `4c9fc99c`). The chronology is now manually maintained. +- **The `scripts/video_analysis/` pipeline** is the standalone-tooling precedent (unrelated to this track but referenced as the pattern for `scripts/twitter_threads/` which is a separate in-flight track). + +### Gaps to Fill (This Track's Scope) + +**Front A — Gemini CLI Adapter Removal (8 files to delete, ~30 files to edit):** + +- **GAP-A1:** `src/gemini_cli_adapter.py` (193 lines) — the standalone adapter module. Delete entirely. +- **GAP-A2:** `src/ai_client.py` — 3 functions to delete (`_list_gemini_cli_models`, `_send_gemini_cli`, `_send_cli_round_result`) + ~8 dispatch branches to remove (lines 556, 629, 914, 3302, 3306, 3394, 3505, 3556) + the import on line 49 + the `PROVIDERS` entry on line 62 + the module state on line 164. **Carefully distinguish `_gemini_cli_adapter` (REMOVE) from `_gemini_client` / `_ensure_gemini_client` (KEEP — that's the direct Gemini SDK provider).** +- **GAP-A3:** `src/app_controller.py` — ~11 sites to remove (state field `ui_gemini_cli_path`, settable/gettable maps, `_update_gcli_adapter()` method, project load/save, init). +- **GAP-A4:** `src/gui_2.py` — 2 blocks to remove (ASCII layout comment lines 2940-2947 + the provider-panel block lines 3008-3025). +- **GAP-A5:** `src/project_manager.py:126` — delete the `"gemini_cli": {"binary_path": "gemini"}` default. +- **GAP-A6:** `src/api_hooks.py:88, 941-942` — delete the docstring line + simplify the HookServer auto-start condition (the `is_gemini_cli` special case becomes dead). +- **GAP-A7:** 7 test files to DELETE entirely: `test_gemini_cli_adapter.py`, `test_gemini_cli_adapter_parity.py`, `test_gemini_cli_integration.py`, `test_gemini_cli_parity_regression.py`, `test_gemini_cli_edge_cases.py`, `test_mock_gemini_cli.py`, `test_ai_client_cli.py`. +- **GAP-A8:** `tests/mock_gemini_cli.py` + `tests/mock_gcli.bat` — **DO NOT DELETE.** Repurpose: 9 live_gui simulation tests use `mock_gemini_cli.py` as a generic mock LLM provider. The track introduces a `mock` provider in `ai_client.py` (or repurposes the existing `"mock"` model-name special case at line 558) that routes to this same script. The 9 sim tests switch from `set_value('current_provider', 'gemini_cli')` to `set_value('current_provider', 'mock')`. This preserves the test infrastructure. +- **GAP-A9:** 9 sim test files to REWRITE (the mock-provider switch): `test_extended_sims.py`, `test_live_workflow.py`, `test_mma_concurrent_tracks_sim.py`, `test_mma_concurrent_tracks_stress_sim.py`, `test_mma_step_mode_sim.py`, `test_rag_phase4_final_verify.py`, `test_rag_phase4_stress.py`, `test_sim_ai_settings.py`, `test_process_pending_gui_tasks.py`. +- **GAP-A10:** 6 test files with minor edits (remove `gemini_cli` from provider lists, remove monkeypatches/patches): `test_providers_source_of_truth.py`, `test_provider_curation.py`, `test_ai_client_tool_loop_send_func.py`, `test_mma_tier_usage_reset_fix.py`, `test_rag_integration.py`, `test_ai_loop_regressions_20260614.py`, `test_live_gui_integration_v2.py`, `test_lazymodule_filedialog_fallback.py`, `test_discussion_compression.py`, `test_ai_client_list_models.py` (delete the single test function; if it's the only one, delete the file). +- **GAP-A11:** Docs: 7 guide files + Readme to update (`guide_ai_client.md`, `guide_architecture.md`, `guide_simulations.md`, `guide_models.md`, `guide_context_aggregation.md`, `guide_tools.md`, `Readme.md`). Conductor docs: 5 files (`tech-stack.md`, `product.md`, `product-guidelines.md`, `workflow.md`, `code_styleguides/error_handling.md`). +- **GAP-A12 (DECISION POINT — out of scope unless user confirms):** `GEMINI_CLI_HOOK_CONTEXT` env var + `scripts/cli_tool_bridge.py` + `scripts/mma_exec.py` + `docs/guide_meta_boundary.md` — these are **meta-tooling** references (the external AI agent bridge), NOT the provider. Recommend: leave as-is. If the user wants to purge the meta-tooling naming too, that's a separate follow-up track. + +**Front B — Test Suite Cleanup (Tier 1-4 cruft, ~45-60 files, ~300-400 tests):** + +- **GAP-B1 (Tier 1 — guaranteed-broken cruft, DELETE):** `tests/test_generate_chronology.py` (205 lines, 20 tests) + `tests/test_chronology_quality_gate.py` (76 lines, 5 tests). Both import from `scripts.audit.generate_chronology` + `chronology_quality_gate` which were DELETED 2026-07-05. These tests are guaranteed `ImportError` at collection time. +- **GAP-B2 (Tier 2 — one-time verification cruft, CONSOLIDATE):** 7 `test_scavenge_*.py` files (~44KB, ~40 tests) verify that the 2026-07-02/03 directive-lift happened (specific directive names exist with v1.md/meta.md). Once the lift shipped, these are permanently-green tautologies with zero ongoing behavioral value. Consolidate into one `test_directive_structure.py` that checks the general invariant (all directives in `current_baseline.md` have v1.md + meta.md), not per-batch lists. +- **GAP-B3 (Tier 3 — deprecated-module references, REVIEW):** `test_mma_skeleton.py` imports from `scripts/mma_exec` (DEPRECATED). `test_arch_boundary_phase1.py` tests hardcoded paths in `scripts/mma_exec.py` / `scripts/claude_mma_exec.py` (DEPRECATED per workflow.md). Review + delete or rewrite. +- **GAP-B4 (Tier 4 — phase-named one-off tests, REVIEW + CONSOLIDATE):** ~15 `test_*_phase*.py` files pin track-phase outputs. Many are now redundant with the general test file (e.g., `test_code_path_audit_phase78.py` + `test_code_path_audit_phase89.py` vs `test_code_path_audit.py`). Some are trivially green (e.g., `test_phase_3_final_verify.py` = 7 lines). Review each; merge the still-relevant assertions into the general file; delete the rest. +- **GAP-B5 (Tier 5 — legacy `src.models` shim imports, MIGRATE):** 27 test files import from `src.models`. 3 use `Metadata` (→ `from src.mma import TrackMetadata`). 3 use `PROVIDERS` (→ `from src.ai_client import PROVIDERS`). 20 use `from src import models` bare (→ direct subsystem imports). 2 self-test files (`test_models_no_top_level_*.py`) remain. +- **GAP-B6 (Tier 6 — heavy mock-patch boilerplate, CONSOLIDATE):** the `patch('src.app_controller.AppController.load_config'...) + patch('..._init_ai_and_hooks') + patch('..._fetch_models')` block repeats across ~8 test files as boilerplate. Extract a shared `mock_controller` fixture or migrate to `live_gui` where feasible. +- **GAP-B7 (Tier 7 — fix-not-skip, FIX):** 3 skips in `test_context_composition_phase6.py` + `test_aggregate_flags.py` share one root cause (live Gemini 503 in `summarize.summarise_file`). Per project skip-marker policy, these should be fixed by mocking the Gemini call, not skipped. +- **GAP-B8:** `test_gui_2_result.py` (120KB, 2,329 lines, 101 tests) — the single largest test file (9.4% of the suite's line count). Audit whether it's testing current behavior or accumulated GUI regression snapshots. If the latter, split into per-feature files + delete the obsolete snapshots. + +**Front C — Metadata-Type Reduction Beyond TOML Boundaries:** + +- **GAP-C1 (Layer 1 — the MCP tool dispatch inversion, 38 sites):** `src/mcp_client.py` has 38 legacy str-returning wrappers that remain the **actual public surface** — `dispatch()` (line 1869) and all 22 external call sites in `aggregate.py`/`gui_2.py`/`app_controller.py` call the str wrappers, NOT the 39 `_result` variants. The Result-migration created the new surface but never flipped the dispatch table or the consumers. **Fix:** update `dispatch()` + `async_dispatch()` + 22 consumer call sites to use the `_result` variants, then delete the 38 str wrappers. +- **GAP-C2 (Layer 2 — `app_controller.py` in-memory state, 40 sites of 81 Metadata refs):** in-memory state collections typed as `list[Metadata]`/`Dict[str, Metadata]`/`Metadata = {}` — `_pending_gui_tasks`, `_tool_log`, `_tool_stats`, `_cached_cache_stats`, `_token_history`, `_comms_log`, `_pending_comms`, `_pending_tool_calls`, `_pending_history_adds`, `_ask_tool_data`, `_pending_mma_approvals`, `_pending_mma_spawns`, `_token_stats`, `vendor_quota`. Plus `Metadata()` construction at lines 2774, 2778, 3443. **Fix:** replace with typed per-aggregate dataclasses (`CommsLogEntry`, `HistoryMessage`, `ToolCall`, etc. — most already exist in `type_aliases.py`). +- **GAP-C3 (Layer 3 — `aggregate.py` FileItem slippage, 10 sites):** `file_items: list[Metadata]` throughout + `NIL_METADATA: Metadata = {}` sentinel at line 50. **Fix:** change to `list[FileItem]` (the `FileItem` dataclass exists in `src/project_files.py`, aliased in `type_aliases.py:149`). +- **GAP-C4 (scattered non-boundary `Metadata` fields):** `personas.py:22` `preferred_models: list[Metadata]`, `workspace_manager.py:16` `panel_states: Metadata`, `orchestrator_pm.py:57` `generate_tracks(project_config: Metadata) -> list[Metadata]`. Triage per-site. +- **GAP-C5 (dead/deprecated code to delete):** `src/openai_schemas.py:108` `to_legacy_dict()` — zero callers, dead code. `src/app_controller.py:4973` `_push_mma_state_update` — marked DEPRECATED, delegates to `_result` variant; verify no callers, then delete. +- **GAP-C6 (test-side migration, 27 files):** the 27 test files in GAP-B5 migrate as part of Front B, but the typed-dataclass migration in GAP-C2/C3 may break tests that construct `Metadata({...})` fixtures — those tests need to construct the new typed dataclasses instead. + +## Goals + +- **G1.** Gemini CLI adapter implementation fully removed from `src/` + `tests/` + docs. The `gemini_cli` provider no longer exists; PROVIDERS has 7 entries (down from 8). The 9 sim tests that used `gemini_cli` + `mock_gemini_cli.py` now use a `mock` provider + the same script. +- **G2.** Test suite downsized by ~45-60 files / ~300-400 tests without losing ongoing behavioral coverage. Tier 1-4 cruft deleted or consolidated; the suite is leaner and the green tautologies are gone. +- **G3.** `Metadata` type usage reduced to TOML/JSON boundary functions only. The 38-site MCP dispatch inversion is flipped. `app_controller.py` in-memory state uses typed per-aggregate dataclasses. `aggregate.py` uses `list[FileItem]`. +- **G4.** The 3 fix-not-skip candidates are fixed (Gemini 503 calls mocked, not skipped). +- **G5.** `src/models.py` shim callers in tests reduced to the 2 self-test files (which test the shim itself). All other test imports migrate to direct subsystem imports. +- **G6.** Docs + conductor docs updated to reflect the 7-provider surface + the Metadata-reduction. + +## Functional Requirements + +### FR1: Gemini CLI Removal (Front A) + +- Delete `src/gemini_cli_adapter.py`. +- Edit `src/ai_client.py`: remove the import (line 49), the PROVIDERS entry (line 62), the module state (line 164), the 3 functions (`_list_gemini_cli_models`, `_send_gemini_cli`, `_send_cli_round_result`), and the ~8 dispatch branches. +- Edit `src/app_controller.py`: remove the ~11 sites (state field, settable/gettable maps, `_update_gcli_adapter()`, project load/save, init). +- Edit `src/gui_2.py`: remove the 2 blocks. +- Edit `src/project_manager.py:126`: delete the default config entry. +- Edit `src/api_hooks.py:88, 941-942`: delete the docstring line + simplify the HookServer auto-start. +- Delete 7 test files (the gemini_cli-specific tests). +- Introduce a `mock` provider in `ai_client.py` (or repurpose the existing `"mock"` model special case at line 558) that routes to `tests/mock_gemini_cli.py`. Rewrite the 9 sim tests to use `mock` instead of `gemini_cli`. +- Update 7 docs + 5 conductor docs. + +### FR2: Test Suite Cleanup (Front B) + +- Delete `tests/test_generate_chronology.py` + `tests/test_chronology_quality_gate.py` (guaranteed-broken). +- Consolidate the 7 `test_scavenge_*.py` into one `test_directive_structure.py`. +- Review + delete or rewrite the deprecated-module test files (`test_mma_skeleton.py`, `test_arch_boundary_phase1.py`). +- Review the ~15 `test_*_phase*.py` files; merge still-relevant assertions into the general files; delete the rest. +- Migrate the 27 `src.models` test importers to direct subsystem imports. +- Extract a shared `mock_controller` fixture from the ~8 files with the boilerplate patch block. +- Fix the 3 fix-not-skip candidates by mocking `summarize.summarise_file`'s Gemini call. +- Audit `test_gui_2_result.py` (120KB); split into per-feature files + delete obsolete snapshots. + +### FR3: Metadata-Type Reduction (Front C) + +- Flip the MCP dispatch inversion: update `dispatch()` + `async_dispatch()` + 22 consumer call sites to use the `_result` variants; delete the 38 str wrappers. +- Replace `app_controller.py` in-memory `Metadata` state with typed per-aggregate dataclasses. +- Change `aggregate.py` `file_items: list[Metadata]` → `list[FileItem]`; update `NIL_METADATA` sentinel. +- Triage + fix the scattered non-boundary `Metadata` fields (`personas.py`, `workspace_manager.py`, `orchestrator_pm.py`). +- Delete `src/openai_schemas.py:108` `to_legacy_dict()` (dead code). +- Verify + delete `src/app_controller.py:4973` `_push_mma_state_update` (DEPRECATED). +- Migrate the test fixtures that construct `Metadata({...})` to construct the new typed dataclasses. + +### FR4: Verification + +- The 4 audit scripts (`audit_main_thread_imports.py`, `audit_no_models_config_io.py`, `audit_weak_types.py --strict`, `audit_exception_handling.py --strict`) pass. +- The full test suite batch run passes (per the Isolated-Pass Verification Fallacy rule — batch green is the only verification that matters). +- `grep -r "gemini_cli" src/` returns only the `GEMINI_CLI_HOOK_CONTEXT` env-var references in `api_hooks.py` (if the user chose to keep the meta-tooling naming) or nothing (if the user chose to purge). +- `grep -r "from src.models import" tests/` returns only the 2 self-test files. +- `grep -r "list\[Metadata\]" src/app_controller.py` returns nothing (in-memory state migrated). + +## Non-Functional Requirements + +- **No testing-integrity loss:** every behavioral assertion that's still relevant must survive the cleanup. The deletion criteria are: (a) guaranteed-broken (imports from deleted modules), (b) permanently-green tautology (one-time verification that shipped), (c) redundant (covered by a general test file), (d) deprecated-module reference (the module is gone/deprecated). Behavioral assertions that are still catching real regressions stay. +- **Per-file atomic commits** per workflow.md. Each Front-A file deletion + each Front-B test consolidation + each Front-C migration is its own commit. +- **1-space indentation** per `conductor/code_styleguides/python.md` §1. +- **Result[T, ErrorInfo]** return types per `conductor/code_styleguides/error_handling.md`. The Front-C dispatch flip is the largest application of this convention. +- **Typed `@dataclass(frozen=True, slots=True)`** for the new in-memory state types per `conductor/code_styleguides/data_oriented_design.md` §8.5. +- **CRLF line endings** on Windows. +- **No new `src/.py` files** per AGENTS.md "File Size and Naming Convention" — the new typed dataclasses (if any) go in `src/type_aliases.py` or `src/mma.py` (the per-system files that already own the typed aggregates). +- **No diagnostic noise in production code** per workflow.md "Process Anti-Patterns" §5. + +## Architecture Reference + +- **`conductor/code_styleguides/data_oriented_design.md`** §8.5 — the Python Type Promotion Mandate (the canonical rule this track advances). +- **`conductor/code_styleguides/error_handling.md`** — the Result[T] + NIL_T sentinel pattern (the convention the Front-C dispatch flip applies). +- **`conductor/code_styleguides/python.md`** §17 — the LLM Default Anti-Patterns (the banned patterns this track eliminates more of). +- **`docs/guide_ai_client.md`** — the per-source-file guide that needs the Gemini CLI sections removed. +- **`docs/guide_app_controller.md`** — the per-source-file guide for `app_controller.py` (the Front-C in-memory state migration). +- **`docs/guide_mcp_client.md`** — the per-source-file guide for `mcp_client.py` (the Front-C dispatch flip). +- **The 3 audit reports** from this track's research phase (the explore-agent outputs documenting the Gemini CLI inventory, the test-suite cruft map, and the legacy-API audit) — attached as track research artifacts. + +## Out of Scope + +- **Meta-tooling `GEMINI_CLI_HOOK_CONTEXT` env var + `scripts/cli_tool_bridge.py` + `scripts/mma_exec.py` + `docs/guide_meta_boundary.md`.** These are external-agent-toolchain references, NOT the provider. Recommend a separate follow-up track if the user wants to purge the naming. +- **The `twitter_threads_extraction_20260705` track** (separate, in-flight) — unrelated to this cleanup. +- **The RAG subsystem** — the `rag_engine.py` Optional[T] ban already holds; the `dict[str, Any]` sites in rag_engine.py are all ChromaDB/JSON boundary (legitimate). +- **The `vendor_capabilities.py` inlining** — already done per `docs/guide_models.md`; `test_vendor_capabilities.py` already imports from `src.ai_client` (correct). +- **Historical/conductor archive content** — per workflow.md, `conductor/archive/` + `docs/reports/` + `docs/transcripts/` are not updated retroactively. +- **GUI feature work** — no new GUI features; only removal of the gemini_cli provider panel. +- **The `mock` provider's full capability surface** — the track introduces just enough of a `mock` provider to keep the 9 sim tests working; a full mock-provider implementation (with configurable responses, error injection, etc.) is a future track. + +## Track Structure + +Single track, 3 phases (one per front). The fronts are sequenced: Front A (Gemini CLI removal) first because it deletes test files + rewrites 9 more, which is the entry point for Front B (test cleanup). Front C (metadata reduction) is last because it's the largest production-code change and the test cleanup in Front B needs to reflect the typed-dataclass migration. + +The track is large. If the user wants to split it, the natural split points are: Front A as one track (Gemini CLI removal + sim-test rewrite), Front B+C as a second track (test cleanup + metadata reduction). But the user framed them as one effort, so this spec keeps them bundled. + +## Verification + +- **VC1:** `src/gemini_cli_adapter.py` does not exist. `grep -r "gemini_cli" src/` returns only the meta-tooling env-var references (or nothing if the user purged those too). +- **VC2:** `PROVIDERS` in `src/ai_client.py` has 7 entries (no `gemini_cli`). +- **VC3:** `tests/test_generate_chronology.py` + `tests/test_chronology_quality_gate.py` do not exist. +- **VC4:** The 7 `test_scavenge_*.py` files do not exist; `tests/test_directive_structure.py` exists and checks the general invariant. +- **VC5:** `grep -r "from src.models import" tests/` returns only the 2 self-test files (`test_models_no_top_level_*.py`). +- **VC6:** `grep -r "list\[Metadata\]" src/app_controller.py` returns nothing. +- **VC7:** `src/mcp_client.py` has no str-returning wrappers (the 38 are deleted; `dispatch()` returns `Result`). +- **VC8:** `src/aggregate.py` uses `list[FileItem]`, not `list[Metadata]`. +- **VC9:** The 3 fix-not-skip tests are fixed (no `@pytest.mark.skip` for the Gemini 503 reason). +- **VC10:** The 4 audit scripts pass. +- **VC11:** The full test suite batch run passes. +- **VC12:** `src/openai_schemas.py:108` `to_legacy_dict()` is deleted. + +## See Also + +- **`conductor/tracks/twitter_threads_extraction_20260705/spec.md`** — the sibling in-flight track (unrelated; referenced only because it's the other active track). +- **`docs/reports/ARCHIVE_REVIEW_20260705.md`** — the archive review (this track advances several of its ranked follow-up items: #1 typed_rag_return_type is adjacent to GAP-C2; #6 mcp_client_tool_surface_assert_removal is GAP-C1; #7 gui_2_hasattr_removal is adjacent to Front C). +- **The 3 audit reports** from this track's research (attached as research artifacts in the track folder). \ No newline at end of file diff --git a/conductor/tracks/test_suite_cleanup_gemini_cli_removal_20260705/state.toml b/conductor/tracks/test_suite_cleanup_gemini_cli_removal_20260705/state.toml new file mode 100644 index 00000000..a0c40a2f --- /dev/null +++ b/conductor/tracks/test_suite_cleanup_gemini_cli_removal_20260705/state.toml @@ -0,0 +1,105 @@ +# Track state for test_suite_cleanup_gemini_cli_removal_20260705 +# Initialized by Tier 1 Orchestrator on 2026-07-05. +# 3 fronts: Gemini CLI removal + test suite cleanup + metadata-type reduction. + +[meta] +track_id = "test_suite_cleanup_gemini_cli_removal_20260705" +name = "Test Suite Cleanup + Gemini CLI Adapter Removal + Metadata-Type Reduction" +status = "active" +current_phase = 0 +last_updated = "2026-07-05" + +[blocked_by] +# None. The Gemini CLI removal is independent; the test cleanup is independent; the metadata reduction is independent. + +[blocks] +# None. The track advances the ARCHIVE_REVIEW_20260705.md follow-up items (#1, #2, #6) but doesn't block them. + +[phases] +phase_1 = { status = "pending", checkpointsha = "", name = "Front A — Gemini CLI Adapter Removal (src + tests + docs + mock provider)" } +phase_2 = { status = "pending", checkpointsha = "", name = "Front B — Test Suite Cleanup (delete broken + consolidate tautologies + migrate shims + fix-not-skip)" } +phase_3 = { status = "pending", checkpointsha = "", name = "Front C — Metadata-Type Reduction (MCP dispatch flip + app_controller state + aggregate FileItem + dead code)" } + +[tasks] +# Phase 1 — Gemini CLI Removal +t1_1 = { status = "pending", commit_sha = "", description = "Delete src/gemini_cli_adapter.py" } +t1_2 = { status = "pending", commit_sha = "", description = "Edit src/ai_client.py — remove import + PROVIDERS entry + module state + 3 functions + 8 dispatch branches" } +t1_3 = { status = "pending", commit_sha = "", description = "Edit src/app_controller.py — remove ~11 gemini_cli sites" } +t1_4 = { status = "pending", commit_sha = "", description = "Edit src/gui_2.py — remove 2 gemini_cli blocks" } +t1_5 = { status = "pending", commit_sha = "", description = "Edit src/project_manager.py:126 + src/api_hooks.py:88,941-942" } +t1_6 = { status = "pending", commit_sha = "", description = "Delete 7 gemini_cli test files" } +t1_7 = { status = "pending", commit_sha = "", description = "Introduce mock provider in src/ai_client.py (routes to tests/mock_gemini_cli.py)" } +t1_8 = { status = "pending", commit_sha = "", description = "Rewrite 9 sim test files: gemini_cli -> mock" } +t1_9 = { status = "pending", commit_sha = "", description = "Minor edits in 6+ gemini_cli-reference test files (provider lists, monkeypatches, comments)" } +t1_10 = { status = "pending", commit_sha = "", description = "Update 7 docs + 5 conductor docs (remove gemini_cli, update provider count 8->7)" } +t1_11 = { status = "pending", commit_sha = "", description = "Phase 1 checkpoint + batch run" } + +# Phase 2 — Test Suite Cleanup +t2_1 = { status = "pending", commit_sha = "", description = "Delete 2 guaranteed-broken chronology test files (import from deleted scripts.audit.*)" } +t2_2 = { status = "pending", commit_sha = "", description = "Consolidate 7 test_scavenge_*.py into 1 test_directive_structure.py" } +t2_3 = { status = "pending", commit_sha = "", description = "Review + delete/rewrite deprecated-module test files (test_mma_skeleton, test_arch_boundary_phase1)" } +t2_4 = { status = "pending", commit_sha = "", description = "Review + consolidate ~15 test_*_phase*.py files" } +t2_5 = { status = "pending", commit_sha = "", description = "Migrate 27 src.models test importers to direct subsystem imports" } +t2_6 = { status = "pending", commit_sha = "", description = "Extract shared mock_controller fixture from ~8 boilerplate-patch files" } +t2_7 = { status = "pending", commit_sha = "", description = "Fix 3 fix-not-skip candidates (mock Gemini 503 in summarize.summarise_file)" } +t2_8 = { status = "pending", commit_sha = "", description = "Audit + split test_gui_2_result.py (120KB, 101 tests) into per-feature files" } +t2_9 = { status = "pending", commit_sha = "", description = "Phase 2 checkpoint + full suite batch run" } + +# Phase 3 — Metadata-Type Reduction +t3_1 = { status = "pending", commit_sha = "", description = "Flip MCP dispatch inversion: dispatch()+async_dispatch()+22 consumers -> _result variants; delete 38 str wrappers" } +t3_2 = { status = "pending", commit_sha = "", description = "Migrate app_controller.py ~40 Metadata in-memory state sites to typed per-aggregate dataclasses" } +t3_3 = { status = "pending", commit_sha = "", description = "Fix aggregate.py file_items: list[Metadata] -> list[FileItem]; NIL_METADATA -> typed empty sentinel" } +t3_4 = { status = "pending", commit_sha = "", description = "Triage scattered non-boundary Metadata fields (personas.py, workspace_manager.py, orchestrator_pm.py)" } +t3_5 = { status = "pending", commit_sha = "", description = "Delete dead code: openai_schemas.py:108 to_legacy_dict() + app_controller.py:4973 _push_mma_state_update" } +t3_6 = { status = "pending", commit_sha = "", description = "Migrate test fixtures that construct Metadata({...}) to typed dataclass constructors" } +t3_7 = { status = "pending", commit_sha = "", description = "Update docs (guide_app_controller, guide_mcp_client, guide_models, type_aliases styleguide)" } +t3_8 = { status = "pending", commit_sha = "", description = "Run 4 audit scripts + full test suite batch" } +t3_9 = { status = "pending", commit_sha = "", description = "Phase 3 checkpoint + TRACK_COMPLETION report" } +t3_10 = { status = "pending", commit_sha = "", description = "Conductor — User Manual Verification (PAUSE for user confirmation)" } +t3_11 = { status = "pending", commit_sha = "", description = "Add chronology row + archive the track" } + +[verification] +vc1_gemini_cli_removed = false +vc2_providers_7_entries = false +vc3_chronology_tests_deleted = false +vc4_scavenge_consolidated = false +vc5_models_shim_migrated = false +vc6_app_controller_no_list_metadata = false +vc7_mcp_dispatch_flipped = false +vc8_aggregate_uses_fileitem = false +vc9_fix_not_skip_fixed = false +vc10_audit_scripts_pass = false +vc11_batch_green = false +vc12_to_legacy_dict_deleted = false + +[front_a_summary] +gemini_cli_adapter_py_deleted = false +ai_client_functions_removed = 0 +ai_client_dispatch_branches_removed = 0 +app_controller_sites_removed = 0 +gui_2_blocks_removed = 0 +test_files_deleted = 0 +sim_tests_rewritten = 0 +mock_provider_introduced = false +docs_updated = 0 + +[front_b_summary] +chronology_tests_deleted = false +scavenge_files_consolidated = false +deprecated_module_tests_reviewed = 0 +phase_named_tests_consolidated = 0 +shim_importers_migrated = 0 +mock_controller_fixture_extracted = false +fix_not_skip_fixed = 0 +gui_2_result_audited = false +test_count_before = 2133 +test_count_after = 0 + +[front_c_summary] +mcp_str_wrappers_deleted = 0 +mcp_dispatch_flipped = false +app_controller_metadata_sites_migrated = 0 +aggregate_fileitem_migrated = false +scattered_metadata_triaged = 0 +dead_code_deleted = 0 +test_fixtures_migrated = 0 \ No newline at end of file