From 55ff733df5dd230949123d09b10d878cfb508fc3 Mon Sep 17 00:00:00 2001 From: Ed_ Date: Mon, 15 Jun 2026 15:24:46 -0400 Subject: [PATCH] conductor(track): metadata.json for public_api_migration_and_ui_polish_20260615 --- .../metadata.json | 445 ++++++++++++++++++ 1 file changed, 445 insertions(+) create mode 100644 conductor/tracks/public_api_migration_and_ui_polish_20260615/metadata.json diff --git a/conductor/tracks/public_api_migration_and_ui_polish_20260615/metadata.json b/conductor/tracks/public_api_migration_and_ui_polish_20260615/metadata.json new file mode 100644 index 00000000..4e0bce51 --- /dev/null +++ b/conductor/tracks/public_api_migration_and_ui_polish_20260615/metadata.json @@ -0,0 +1,445 @@ +{ + "track_id": "public_api_migration_and_ui_polish_20260615", + "name": "Public API Migration + UI Polish Test Cleanup", + "initialized": "2026-06-15", + "owner": "tier2-tech-lead", + "priority": "A", + "status": "active", + "type": "refactor + bugfix + test_cleanup + documentation", + "scope": { + "new_files": [], + "modified_files": [ + "src/ai_client.py", + "src/conductor_tech_lead.py", + "src/orchestrator_pm.py", + "src/multi_agent_conductor.py", + "tests/test_ai_client_cli.py", + "tests/test_ai_cache_tracking.py", + "tests/test_ai_client_result.py", + "tests/test_api_events.py", + "tests/test_deepseek_provider.py", + "tests/test_gemini_cli_edge_cases.py", + "tests/test_gemini_cli_integration.py", + "tests/test_gemini_cli_parity_regression.py", + "tests/test_gui2_mcp.py", + "tests/test_tier4_interceptor.py", + "tests/test_token_usage.py", + "tests/test_symbol_parsing.py", + "tests/test_qwen_provider.py", + "tests/test_discussion_truncate_layout.py", + "tests/test_log_management_refresh.py", + "pyproject.toml", + "docs/guide_ai_client.md", + "conductor/product-guidelines.md" + ], + "deleted_files": [ + "tests/test_deprecation_warnings.py" + ] + }, + "blocked_by": [], + "blocks": [ + "data_structure_strengthening_20260606", + "mcp_architecture_refactor_20260606 (transitively)" + ], + "estimated_phases": 7, + "spec": "spec.md", + "plan": "plan.md", + + "regressions_and_pre_existing_failures": [ + { + "id": "G1_conductor_tech_lead_send", + "severity": "high", + "category": "production_deprecation", + "introduced_by": "data_oriented_error_handling_20260606 commit 73cf321c (marked send() @deprecated)", + "file_line": "src/conductor_tech_lead.py:68", + "symptom": "Production code uses deprecated ai_client.send() (emits DeprecationWarning at runtime)", + "fix_phase": 1, + "fix": "Migrate to ai_client.send_result() with Result handling (log to comms on error, return None)" + }, + { + "id": "G2_orchestrator_pm_send", + "severity": "high", + "category": "production_deprecation", + "introduced_by": "data_oriented_error_handling_20260606 commit 73cf321c", + "file_line": "src/orchestrator_pm.py:86", + "symptom": "Production code uses deprecated ai_client.send()", + "fix_phase": 1, + "fix": "Migrate to ai_client.send_result() with Result handling (log to comms on error, return None)" + }, + { + "id": "G3_multi_agent_conductor_send", + "severity": "high", + "category": "production_deprecation", + "introduced_by": "data_oriented_error_handling_20260606 commit 73cf321c", + "file_line": "src/multi_agent_conductor.py:591", + "symptom": "Production code uses deprecated ai_client.send() (8-arg call with 5 callbacks)", + "fix_phase": 1, + "fix": "Migrate to ai_client.send_result() with per-ticket Result handling (log to worker_comms_callback on error, return sentinel value so worker exits with non-zero status)" + }, + { + "id": "G4_test_ai_client_cli", + "severity": "medium", + "category": "test_deprecation", + "file_line": "tests/test_ai_client_cli.py:22", + "fix_phase": 2, + "fix": "Migrate to send_result() + assert result.ok" + }, + { + "id": "G5_test_ai_cache_tracking", + "severity": "medium", + "category": "test_deprecation", + "file_line": "tests/test_ai_cache_tracking.py:47", + "fix_phase": 2, + "fix": "Migrate to send_result() + assert result.ok" + }, + { + "id": "G6_test_ai_client_result", + "severity": "medium", + "category": "test_deprecation", + "file_line": "tests/test_ai_client_result.py:10-25 (3 sites; 1 to delete, 2 to migrate)", + "fix_phase": 2, + "fix": "Delete test_send_deprecated_emits_warning (obsolete after Phase 6); migrate the other 2 send() tests to send_result(); keep test_send_result_does_not_emit_deprecation as regression test" + }, + { + "id": "G7_test_api_events", + "severity": "medium", + "category": "test_deprecation", + "file_line": "tests/test_api_events.py:63,106", + "fix_phase": 2, + "fix": "Migrate 2 sites to send_result()" + }, + { + "id": "G8_test_deepseek_provider", + "severity": "medium", + "category": "test_deprecation", + "file_line": "tests/test_deepseek_provider.py:31,54,96,122,142,171 (6 sites)", + "fix_phase": 2, + "fix": "Migrate 6 sites to send_result() (1 atomic commit for the file)" + }, + { + "id": "G9_test_gemini_cli_edge_cases", + "severity": "medium", + "category": "test_deprecation", + "file_line": "tests/test_gemini_cli_edge_cases.py:38", + "fix_phase": 2, + "fix": "Migrate to send_result()" + }, + { + "id": "G10_test_gemini_cli_integration", + "severity": "medium", + "category": "test_deprecation", + "file_line": "tests/test_gemini_cli_integration.py:15,29", + "fix_phase": 2, + "fix": "Migrate 2 sites to send_result()" + }, + { + "id": "G11_test_gemini_cli_parity_regression", + "severity": "medium", + "category": "test_deprecation", + "file_line": "tests/test_gemini_cli_parity_regression.py:12", + "fix_phase": 2, + "fix": "Migrate to send_result()" + }, + { + "id": "G12_test_gui2_mcp", + "severity": "medium", + "category": "test_deprecation", + "file_line": "tests/test_gui2_mcp.py:47", + "fix_phase": 2, + "fix": "Migrate to send_result()" + }, + { + "id": "G13_test_tier4_interceptor", + "severity": "medium", + "category": "test_deprecation", + "file_line": "tests/test_tier4_interceptor.py:83", + "fix_phase": 2, + "fix": "Migrate to send_result() (with Result(data=...) wrapper for the qa_callback mock)" + }, + { + "id": "G14_test_token_usage", + "severity": "medium", + "category": "test_deprecation", + "file_line": "tests/test_token_usage.py:34", + "fix_phase": 2, + "fix": "Migrate to send_result()" + }, + { + "id": "G15_test_symbol_parsing", + "severity": "high", + "category": "test_mock_bug", + "file_line": "tests/test_symbol_parsing.py:45,74", + "symptom": "Mocks src.ai_client.send but production now uses send_result; mock receives 0 calls; test fails with 'send was called 0 times'", + "fix_phase": 4, + "fix": "Change patch('src.ai_client.send') to patch('src.ai_client.send_result') with return_value=Result(data='mocked response')" + }, + { + "id": "G16_test_qwen_provider", + "severity": "high", + "category": "test_mock_bug", + "file_line": "tests/test_qwen_provider.py:17,27", + "symptom": "_send_qwen() now returns Result[str] (per data_oriented_error_handling refactor); tests assert against raw str", + "fix_phase": 3, + "fix": "Change 'assert result == x' to 'assert result.ok and result.data == x' (same pattern as doeh_test_thinking_cleanup used for grok/llama/llama_native)" + }, + { + "id": "G17_test_discussion_truncate_layout", + "severity": "high", + "category": "ui_polish_test_bug", + "file_line": "tests/test_discussion_truncate_layout.py:7", + "symptom": "Test uses find() which locates the comment block at src/gui_2.py:5113; the 200-char snippet doesn't reach the actual code at line 5130. Production code (set_next_item_width(140) + drag_int) is already correct (user commit d0b06575)", + "fix_phase": 5, + "fix": "Change src.find(marker) to src.rfind(marker) to locate the actual code, not the comment" + }, + { + "id": "G18_test_log_management_refresh", + "severity": "high", + "category": "ui_polish_test_bug", + "file_line": "tests/test_log_management_refresh.py:6", + "symptom": "Test uses find() which locates the comment block at src/gui_2.py:2090; the 400-char snippet doesn't reach the actual code at line 2111. Production code (in-place load_registry()) is already correct (user commit df7bda6e)", + "fix_phase": 5, + "fix": "Change src.find(marker) to src.rfind(marker) to locate the actual code, not the comment" + }, + { + "id": "G19_deprecated_send_function", + "severity": "high", + "category": "deprecation_removal", + "file_line": "src/ai_client.py:2939-3040", + "symptom": "Legacy send() function still exists; emits DeprecationWarning at runtime; filterwarnings in pyproject.toml silences it", + "fix_phase": 6, + "fix": "Remove the @deprecated decorator + the entire send() function body; remove the filterwarnings entry in pyproject.toml:46-47; delete tests/test_deprecation_warnings.py (both tests are obsolete)" + } + ], + + "pre_existing_failures_fixed": [ + { + "id": "PE_1", + "test": "tests/test_qwen_provider.py::test_send_qwen_routes_to_dashscope", + "fix_phase": 3, + "root_cause": "_send_qwen() returns Result[str]; test asserts against raw str" + }, + { + "id": "PE_2", + "test": "tests/test_qwen_provider.py::test_qwen_vision_vl_model_accepts_image", + "fix_phase": 3, + "root_cause": "Same as PE_1" + }, + { + "id": "PE_3", + "test": "tests/test_symbol_parsing.py::test_handle_request_event_appends_definitions", + "fix_phase": 4, + "root_cause": "Mocks src.ai_client.send but production uses send_result" + }, + { + "id": "PE_4", + "test": "tests/test_symbol_parsing.py::test_handle_request_event_no_symbols", + "fix_phase": 4, + "root_cause": "Same as PE_3" + }, + { + "id": "PE_5", + "test": "tests/test_discussion_truncate_layout.py::test_keep_pairs_input_uses_adequate_width", + "fix_phase": 5, + "root_cause": "Test uses find() which locates the comment block, not the actual code at line 5130" + }, + { + "id": "PE_6", + "test": "tests/test_log_management_refresh.py::test_refresh_registry_button_calls_load_registry", + "fix_phase": 5, + "root_cause": "Test uses find() which locates the comment block, not the actual code at line 2111" + } + ], + + "pre_existing_failures_remaining": [ + { + "id": "PR_1", + "test": "tests/test_rag_integration.py::test_rag_integration", + "root_cause": "Pre-existing RAG subsystem issue (NoneType.get error in RAG config lookup code)", + "defer_to": "RAG subsystem track (planned; not yet specced)" + }, + { + "id": "PR_2", + "test": "tests/test_rag_phase4_final_verify.py::test_phase4_final_verify", + "root_cause": "Same as PR_1", + "defer_to": "RAG subsystem track" + }, + { + "id": "PR_3", + "test": "tests/test_rag_phase4_stress.py::test_rag_large_codebase_verification_sim", + "root_cause": "Same as PR_1", + "defer_to": "RAG subsystem track" + }, + { + "id": "PR_4", + "test": "tests/test_rag_visual_sim.py::test_rag_full_lifecycle_sim", + "root_cause": "Same as PR_1", + "defer_to": "RAG subsystem track" + } + ], + + "deferred_to_followup_tracks": [ + { + "id": "rag_test_failures", + "title": "RAG Subsystem Test Fixes", + "description": "Fix the 4 pre-existing RAG test failures (test_rag_integration, test_rag_phase4_final_verify, test_rag_phase4_stress, test_rag_visual_sim). The error is in RAG config lookup code, not AI client code. A partial fix was attempted in commit 16412ad5 (RAG Phase 4 dim-mismatch recovery).", + "track_status": "recommended; not yet specced" + }, + { + "id": "private_api_rename", + "title": "Private API Rename (_send_ -> _send__result)", + "description": "Per data_oriented_error_handling_20260606 spec ยง3.5 line 611, the original plan was to rename the private _send_() functions to _send__result() to match their Result return type. The rename was NOT done in the data_oriented_error_handling track; the tests work with the current names. A future track could do the rename if needed.", + "track_status": "not needed for now; tests work with current names" + }, + { + "id": "data_structure_strengthening_20260606", + "title": "Data Structure Strengthening (Type Aliases + NamedTuples)", + "description": "Introduce 6 TypeAlias definitions in src/type_aliases.py; replace 370+ anonymous dict[str, Any] sites in 6 high-traffic files (src/ai_client.py, src/app_controller.py, src/models.py, src/api_hook_client.py, src/project_manager.py, src/aggregate.py). The 23 lower-impact files remain. Spec already exists; plan pending.", + "track_status": "ready to start; blocked by this track (cleaner Result API usage makes type-alias replacement easier)" + }, + { + "id": "live_gui_mock_injection_20260615", + "title": "Live GUI Mock Injection Infrastructure", + "description": "Infrastructure for mock injection into the live_gui subprocess. Unblocks proper end-to-end live_gui + AI client tests.", + "track_status": "recommended; not yet specced" + } + ], + + "verification_criteria": { + "g1_three_production_call_sites_migrated": "uv run rg 'ai_client\\.send\\(' src/ returns 0 hits", + "g2_twelve_test_files_migrated": "uv run rg 'ai_client\\.send\\(' tests/ returns 0 hits", + "g3_qwen_test_passes": "uv run pytest tests/test_qwen_provider.py -v passes 5/5 (was 3/5; fixes 2 pre-existing failures)", + "g4_symbol_parsing_test_passes": "uv run pytest tests/test_symbol_parsing.py -v passes 2/2 (fixes 2 pre-existing failures)", + "g5_truncate_layout_test_passes": "uv run pytest tests/test_discussion_truncate_layout.py -v passes 1/1 (fixes 1 pre-existing failure)", + "g6_log_management_refresh_test_passes": "uv run pytest tests/test_log_management_refresh.py -v passes 1/1 (fixes 1 pre-existing failure)", + "g7_deprecated_send_removed": "uv run rg 'def send\\(' src/ai_client.py returns 0 hits (only def send_result() should remain)", + "g8_test_deprecation_warnings_deleted": "tests/test_deprecation_warnings.py does not exist", + "g9_filterwarnings_removed": "uv run rg 'ignore:Use ai_client.send_result' pyproject.toml returns 0 hits", + "g10_guide_ai_client_deprecation_removed": "uv run rg -i 'deprecat' docs/guide_ai_client.md | grep -i send returns 0 hits", + "g11_product_guidelines_deprecation_removed": "uv run rg -i 'send.*deprecat|deprecat.*send' conductor/product-guidelines.md returns 0 hits", + "g12_no_new_regressions": "uv run pytest tests/ shows 4 fewer failures than the pre-track baseline (10 - 6 = 4 RAG failures remain); no new failures", + "g13_per_task_atomic_commits": "~28 git commits; each commit is buildable + testable", + "g14_per_commit_git_notes": "All ~28 commits have git notes summarizing the task", + "g15_style_preserved": "1-space indentation, no comments, type hints in all changed code; uv run python -c 'import ast; ast.parse(open(\"src/ai_client.py\").read())' succeeds" + }, + + "fr_to_phase_mapping": { + "G1_conductor_tech_lead_send": { + "phase": 1, + "fix_files": ["src/conductor_tech_lead.py:60-90"], + "test_files": ["tests/test_conductor_tech_lead.py (if exists)"] + }, + "G2_orchestrator_pm_send": { + "phase": 1, + "fix_files": ["src/orchestrator_pm.py:80-100"], + "test_files": ["tests/test_orchestrator_pm.py (if exists)"] + }, + "G3_multi_agent_conductor_send": { + "phase": 1, + "fix_files": ["src/multi_agent_conductor.py:580-605"], + "test_files": ["tests/test_mma_concurrent_tracks_sim.py", "tests/test_mma_step_mode_sim.py", "tests/test_undo_redo_sim.py", "30+ MMA live_gui tests"] + }, + "G4-G14_test_migration": { + "phase": 2, + "fix_files": ["tests/test_ai_client_cli.py", "tests/test_ai_cache_tracking.py", "tests/test_ai_client_result.py", "tests/test_api_events.py", "tests/test_deepseek_provider.py", "tests/test_gemini_cli_edge_cases.py", "tests/test_gemini_cli_integration.py", "tests/test_gemini_cli_parity_regression.py", "tests/test_gui2_mcp.py", "tests/test_tier4_interceptor.py", "tests/test_token_usage.py"], + "min_test_count": 12 + }, + "G15_symbol_parsing_fix": { + "phase": 4, + "fix_files": ["tests/test_symbol_parsing.py:45,74"], + "min_test_count": 2 + }, + "G16_qwen_test_fix": { + "phase": 3, + "fix_files": ["tests/test_qwen_provider.py:13-20, 22-31"], + "min_test_count": 2 + }, + "G17_G18_ui_polish_test_fixes": { + "phase": 5, + "fix_files": ["tests/test_discussion_truncate_layout.py:7", "tests/test_log_management_refresh.py:6"], + "min_test_count": 2 + }, + "G19_deprecation_removal": { + "phase": 6, + "fix_files": ["src/ai_client.py:2939-3040", "pyproject.toml:46-47"], + "deleted_files": ["tests/test_deprecation_warnings.py"], + "min_test_count": 0 + }, + "G20_doc_updates": { + "phase": 7, + "fix_files": ["docs/guide_ai_client.md", "conductor/product-guidelines.md"], + "min_test_count": 0 + } + }, + + "estimated_effort": { + "phase_1": "1 day - 3 production call sites migrated (1 hardest with 5 callbacks)", + "phase_2": "1 day - 12 test files migrated to send_result() (mechanical)", + "phase_3": "1 hour - 2 Qwen tests fixed", + "phase_4": "30 min - 2 symbol_parsing tests fixed", + "phase_5": "30 min - 2 UI Polish test bugs fixed (find -> rfind)", + "phase_6": "30 min - deprecation removed (send() function + filterwarnings + test_deprecation_warnings.py deleted)", + "phase_7": "1 hour - docs updated + full suite sweep + metadata + tracks.md", + "total": "2-3 days Tier 2 work (16-24 hours)" + }, + + "risk_register": { + "R1_multi_agent_conductor_migration_breaks_MMA": { + "likelihood": "medium", + "impact": "high", + "mitigation": "TDD red first; verify a known MMA test fails before the fix; verify it passes after. Use the doeh_test_thinking_cleanup_20260615 G1 fix pattern (adapted for MMA's comms log instead of HTTPException)." + }, + "R2_send_removal_breaks_indirect_imports": { + "likelihood": "low", + "impact": "medium", + "mitigation": "Run 'rg ai_client\\.send\\( src/ tests/' before AND after Phase 6 to confirm 0 hits." + }, + "R3_filterwarnings_removal_causes_test_failures": { + "likelihood": "low", + "impact": "low", + "mitigation": "The filter was added in data_oriented_error_handling_20260606 specifically to silence send() deprecation; no other deprecation in the codebase is silenced by it. Verified by checking the rg history." + }, + "R4_ui_polish_test_fixes_mask_real_production_bug": { + "likelihood": "low", + "impact": "medium", + "mitigation": "The production code at src/gui_2.py:5130-5131 and :2111-2112 was already verified to have the correct values. The test bug is just the search logic." + }, + "R5_qwen_test_fix_uses_different_pattern": { + "likelihood": "low", + "impact": "low", + "mitigation": "Plan uses the same 'assert result.ok and result.data == x' pattern as doeh_test_thinking_cleanup_20260615 (commits d7e42a4a, 439a0ac0, dbdf9ba9)." + }, + "R6_test_deprecation_warnings_deletion_misinterpreted": { + "likelihood": "low", + "impact": "low", + "mitigation": "Both tests in the file are obsolete after send() removal. The first test cannot run without send(). The second test is trivially true. Document in the commit message." + }, + "R7_rag_failures_regress_during_track": { + "likelihood": "low", + "impact": "medium", + "mitigation": "Run full test suite in Phase 7 and compare to the pre-track baseline. The 4 RAG failures are documented as pre-existing with their defer-to track recorded." + } + }, + + "critical_audit_findings": { + "ui_polish_status": { + "phase_1_markdown_tables": "SHIPPED (commit 79ac9210); src/markdown_table.py exists", + "phase_2_keep_pairs": "Code SHIPPED (user commit d0b06575, src/gui_2.py:5130-5131); test FAILING (find() locates comment block, not code)", + "phase_3_refresh_registry": "Code SHIPPED (user commit df7bda6e, src/gui_2.py:2111-2112); test FAILING (find() locates comment block, not code)", + "phase_4_vendor_state": "SHIPPED (commit 3a864076); src/vendor_state.py exists", + "phase_5_files_directory_tree": "SHIPPED (commit 74e02485); src/gui_2.py:render_files_and_media uses directory grouping" + }, + "send_state": { + "production_call_sites_remaining": 3, + "production_call_sites_migrated_by_doeh_track": 2, + "test_files_using_send_directly": 12, + "test_files_using_send_directly_in_parent_spec": 63, + "discrepancy_reason": "Parent spec (data_oriented_error_handling_20260606) verified 63 test files on 2026-06-11; since then, doeh_test_thinking_cleanup_20260615 migrated 11 of them (Phase 2 of that track), leaving 12 today. The current count is verified via rg 2026-06-15." + }, + "deprecated_send_function_state": { + "decorator": "src/ai_client.py:2939 (@deprecated from typing_extensions)", + "function_body_lines": "src/ai_client.py:2940-3040", + "filterwarnings_entry": "pyproject.toml:46-47 (filterwarnings = [\"ignore:Use ai_client.send_result.*:DeprecationWarning\"])", + "obsolete_test_file": "tests/test_deprecation_warnings.py (2 tests; both will be deleted in Phase 6)" + } + } +}