From cbc3b075a0091e6bd310886d8f9f89d93bd21ac4 Mon Sep 17 00:00:00 2001 From: Ed_ Date: Sat, 6 Jun 2026 16:58:22 -0400 Subject: [PATCH] conductor(track): Initialize data_oriented_error_handling_20260606 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Track + metadata + state + tracks.md registration for the Fleury-pattern error handling refactor. Key design decisions (per user approval): - Option A for _send_() handling: rename to _send__result() and change return type to Result[str] (contained to internal callers). - send() is marked @typing_extensions.deprecated; send_result() is the new public API. - ProviderError exception is FULLY REPLACED by ErrorInfo dataclass (a value, not an exception). - 5 phases: foundation, mcp_client, ai_client, rag_engine, deprecation+archive. - Post-tracks baseline check (Phase 1 Task 1.1) verifies the 3 pending tracks have merged before proceeding. - 9 Open Questions, 7 Risks, 5 verification criteria, follow-up track public_api_migration_20260606 planned in spec §12.1. Blocked by: startup_speedup_20260606, test_batching_refactor_20260606, qwen_llama_grok_integration_20260606. Blocks: public_api_migration_20260606. --- conductor/tracks.md | 5 + .../metadata.json | 151 ++++++++++++++++++ .../state.toml | 146 +++++++++++++++++ 3 files changed, 302 insertions(+) create mode 100644 conductor/tracks/data_oriented_error_handling_20260606/metadata.json create mode 100644 conductor/tracks/data_oriented_error_handling_20260606/state.toml diff --git a/conductor/tracks.md b/conductor/tracks.md index 65d119e3..a78f6c2c 100644 --- a/conductor/tracks.md +++ b/conductor/tracks.md @@ -161,6 +161,11 @@ User review surfaced five outstanding UI issues, each previously attempted witho *Link: [./tracks/qwen_llama_grok_integration_20260606/](./tracks/qwen_llama_grok_integration_20260606/), Spec: [./tracks/qwen_llama_grok_integration_20260606/spec.md](./tracks/qwen_llama_grok_integration_20260606/spec.md), Plan: [./tracks/qwen_llama_grok_integration_20260606/plan.md](./tracks/qwen_llama_grok_integration_20260606/plan.md) (to be authored by writing-plans skill)* *Goal: Add first-class support for Qwen (DashScope native SDK), Llama (Ollama local + OpenRouter cloud + custom URL), and Grok (xAI OpenAI-compatible). Introduce a **Vendor Capability Matrix** (7 v1 capabilities: vision, tool_calling, caching, streaming, model_discovery, context_window, cost_tracking; audio and server-side code_execution deferred) declared per-(vendor, model) in `src/vendor_capabilities.py`. GUI reads the matrix to enable/disable 9 UI elements (screenshot button, tools toggle, cache panel, stream progress, fetch models, token budget, cost panel) instead of hard-coding per-vendor branches. Extract a shared `send_openai_compatible()` helper in `src/openai_compatible.py` that operates on a normalized request/response data structure; each `_send_()` is a thin boundary adapter (data-oriented design per Fleury/Acton/Lottes). Refactor `_send_minimax()` to use the helper (~250 lines → ~50). **Out of scope** (separate follow-up track): Anthropic/Gemini/DeepSeek migration to the matrix. 6 phases: matrix+helper, Qwen, Grok+Llama, MiniMax refactor, UX adaptation, docs+archive.* +0e. [ ] **Track: Data-Oriented Error Handling (Fleury Pattern)** `[track-created: 494f68f9]` + *Link: [./tracks/data_oriented_error_handling_20260606/](./tracks/data_oriented_error_handling_20260606/), Spec: [./tracks/data_oriented_error_handling_20260606/spec.md](./tracks/data_oriented_error_handling_20260606/spec.md), Plan: [./tracks/data_oriented_error_handling_20260606/plan.md](./tracks/data_oriented_error_handling_20260606/plan.md) (to be authored by writing-plans skill)* + *Goal: Introduce Ryan Fleury's "errors are just cases" framework as a project convention. New `src/result_types.py` (ErrorKind enum, ErrorInfo dataclass, `Result[T]` with data + side-channel errors list, NilPath + NilRAGState sentinel singletons) and new `conductor/code_styleguides/error_handling.md` canonical reference. Refactor `src/mcp_client.py` ((p, err) tuples → Result; 30+ `assert p is not None` → nil-sentinel paths), `src/ai_client.py` (ProviderError exception → ErrorInfo dataclass; `_send_()` → `_send__result()` returning `Result[str]`; `send()` marked `@deprecated`; new `send_result()` public API), and `src/rag_engine.py` (RAGEngine methods → Result returns). Update `conductor/product-guidelines.md` + `workflow.md` + `docs/guide_*.md` so the convention is documented and future plans can incrementally migrate the remaining `src/` files. **Blocked by** startup_speedup, test_batching_refactor, and qwen_llama_grok tracks. 5 phases: foundation+styleguide, mcp_client refactor, ai_client refactor (highest risk; ProviderError removal), rag_engine refactor, deprecation+docs+archive.* + *Follow-up: [./tracks/public_api_migration_20260606/](./tracks/public_api_migration_20260606/) (planned; not yet specced) — removes the deprecated `ai_client.send()` and migrates all callers.* + 0b. [x] **Track: rag_phase4_stress_test_flake_20260606** — fixed 16412ad5 *Status: 2026-06-06 — Surfaced during post-v2 verification. Resolved: real bug, NOT a test flake. Root cause: ChromaDB collection dimension mismatch across test runs. The persistent on-disk collection (`tests/artifacts/live_gui_workspace/.slop_cache/chroma_test_stress/`) was created by a previous run with Gemini embeddings (3072-dim); the current run uses local SentenceTransformers (384-dim). `index_file()` upserts silently corrupt the collection, then `search()` fails with `Collection expecting embedding with dimension of 3072, got 384` and the AI request never reaches 'done' status, timing out the 50*0.5s = 25s poll loop. Fix: `RAGEngine._init_vector_store` now calls `_validate_collection_dim` which inspects the first existing vector's dim, compares to the current provider's output, and recreates the collection on mismatch (with a stderr warning). Regression tests added: `test_rag_collection_dim_mismatch_recreates_collection` and `test_rag_collection_dim_match_preserves_collection` in `tests/test_rag_engine.py`. This also fixes a real user-facing bug: switching embedding providers in the GUI previously caused silent corruption. Commit 16412ad5.* 0a. [ ] **Track: prior_session_test_harden_20260605** [superseded by live_gui_test_hardening_v2_20260605] diff --git a/conductor/tracks/data_oriented_error_handling_20260606/metadata.json b/conductor/tracks/data_oriented_error_handling_20260606/metadata.json new file mode 100644 index 00000000..e3cac49c --- /dev/null +++ b/conductor/tracks/data_oriented_error_handling_20260606/metadata.json @@ -0,0 +1,151 @@ +{ + "track_id": "data_oriented_error_handling_20260606", + "name": "Data-Oriented Error Handling (Fleury Pattern)", + "initialized": "2026-06-06", + "owner": "tier2-tech-lead", + "priority": "high", + "status": "active", + "type": "refactor + convention + documentation", + "scope": { + "new_files": [ + "src/result_types.py", + "conductor/code_styleguides/error_handling.md", + "tests/test_result_types.py", + "tests/test_mcp_client_paths.py", + "tests/test_ai_client_result.py", + "tests/test_rag_engine_result.py", + "tests/test_deprecation_warnings.py" + ], + "modified_files": [ + "src/mcp_client.py", + "src/ai_client.py", + "src/rag_engine.py", + "conductor/product-guidelines.md", + "conductor/workflow.md", + "docs/guide_ai_client.md", + "docs/guide_mcp_client.md", + "pyproject.toml", + "tests/conftest.py" + ] + }, + "blocked_by": ["startup_speedup_20260606", "test_batching_refactor_20260606", "qwen_llama_grok_integration_20260606"], + "blocks": ["public_api_migration_20260606"], + "estimated_phases": 5, + "spec": "spec.md", + "plan": "plan.md", + "priority_order": "A (foundation patterns + 3-file refactor) > B (deprecation + Result API) > C (convention docs) > D (plan follow-up)", + "fleury_patterns_applied": [ + "Nil struct pointer (Python: frozen dataclass singleton + nil-sentinel methods)", + "Zero-initialization (Python: @dataclass field defaults)", + "Fail early (Python: same principle; assert + early return)", + "AND over OR (Python: Result dataclass with data + side-channel errors list)", + "Error info as side-channel (Python: list[ErrorInfo] in Result, accumulates per call)" + ], + "python_mappings": { + "nil_struct_pointer": "@dataclass(frozen=True) class Nil: pass; NIL = Nil() (module-level singleton); frozen=True prevents runtime mutation", + "zero_initialization": "@dataclass with field defaults; field(default_factory=list) for mutables", + "fail_early": "assert + early return at entry points; try/finally as Python's analog to goto defer", + "and_over_or": "Result[T] = Result(data: T, errors: list[ErrorInfo]) where data is the happy-path value and errors is a side-channel list (zero-initialized = success)", + "error_side_channel": "list[ErrorInfo] in Result struct accumulates all errors per call (richer than C's single errno slot)" + }, + "result_data_model": { + "ErrorInfo": "@dataclass(frozen=True) class ErrorInfo: kind: ErrorKind; message: str; source: str; original: BaseException | None", + "ErrorKind": "@enum.Enum: NETWORK, AUTH, QUOTA, RATE_LIMIT, BALANCE, PERMISSION, NOT_FOUND, INVALID_INPUT, UNKNOWN, CONFIG, INTERNAL", + "Result": "@dataclass(frozen=True) class Result(Generic[T]): data: T; errors: list[ErrorInfo] = field(default_factory=list); @property ok(self) -> bool; with_error(); with_data()", + "NilPath": "@dataclass(frozen=True) singleton with exists=False, read_text='', errors=[]", + "NilRAGState": "@dataclass(frozen=True) singleton with enabled=False, is_empty_result=True, errors=[]" + }, + "refactor_targets": { + "src/mcp_client.py": { + "pattern_replaced": "(p, err) tuple returns + 'if err or p is None: return err' (~30 sites) + 'assert p is not None' chain (~30+ sites)", + "new_pattern": "Result[Path] + Result[str] with nil-sentinel Path; read_file() returns Result[str]", + "test_impact": "tests/test_mcp_client.py passes unchanged; new test_mcp_client_paths.py covers the new return types" + }, + "src/ai_client.py": { + "pattern_replaced": "ProviderError exception + _classify_*_error() raises + _send_() returns str (8 vendors post-qwen_track)", + "new_pattern": "ErrorInfo dataclass + _classify_*_error() returns ErrorInfo (value) + _send__result() returns Result[str]; ProviderError removed entirely", + "breaking_changes": "All _send_() renamed to _send__result() with new return type; send() marked @deprecated; send_result() added", + "test_impact": "Most tests call send() and pass unchanged (with deprecation warning); _send_* direct callers (rare) need update" + }, + "src/rag_engine.py": { + "pattern_replaced": "RAGEngine methods raise ImportError/ValueError or set self.collection=None on failure", + "new_pattern": "RAGEngine methods return Result[None] or Result[T] with side-channel ErrorInfo; NilRAGState sentinel for unconfigured state", + "test_impact": "tests/test_rag_engine.py passes unchanged; new test_rag_engine_result.py covers the new return types" + } + }, + "deprecation_strategy": { + "marked_deprecated": "ai_client.send() (public API returning str)", + "new_api": "ai_client.send_result() (returns Result[str, ErrorInfo])", + "mechanism": "typing_extensions.deprecated decorator (Python 3.11+ backport of @warnings.deprecated); emits DeprecationWarning at first call per site (cached)", + "removal_timeline": "Removed in follow-up track public_api_migration_20260606 (planned in this spec's §12.1)" + }, + "inter_track_coordination": { + "post_startup_speedup_state": "src/ai_client.py has lazy SDK imports via _require_warmed; src/app_controller.py has _io_pool; scripts/audit_main_thread_imports.py is a CI gate", + "post_test_batching_state": "tests/test_categories.toml populated; conftest.py registers pytest_collection_order plugin; new tests auto-classified by the categorizer", + "post_qwen_track_state": "src/vendor_capabilities.py + src/openai_compatible.py + src/qwen_adapter.py exist; 8 _send_() functions all return str (Qwen, Llama, Grok, MiniMax, Gemini, Anthropic, DeepSeek, Gemini CLI); MiniMax uses the shared helper; send_openai_compatible raises ProviderError at the SDK boundary", + "phase_1_baseline_check": "Verify all 3 pending tracks merged before starting the data-oriented refactor (git log + file existence check)" + }, + "documentation_strategy": { + "new_file": "conductor/code_styleguides/error_handling.md (~400 lines; the canonical reference)", + "modified_files": [ + "conductor/product-guidelines.md (new 'Data-Oriented Error Handling' section)", + "conductor/workflow.md (note in Code Style section linking to the new styleguide)", + "docs/guide_ai_client.md (new section on Result API + deprecation note)", + "docs/guide_mcp_client.md (new section on Result return types)" + ], + "rationale": "Establish the convention in the canonical styleguide so future plans can incrementally migrate the remaining src/ files" + }, + "architectural_invariant": "All new code uses Result dataclasses (not Optional/exceptions) for recoverable errors. The Result generic is over the success data T (not over the error type E); errors are always list[ErrorInfo]. Exceptions are reserved for the SDK boundary (where they're caught and converted to ErrorInfo). Nil-sentinel dataclasses are used instead of None for missing data.", + "threading_constraint": "Same as existing pattern: Result dataclasses are frozen and thread-safe (immutable). The error list is built via `with_error()` which produces a new Result (no mutation). The deprecation warning uses Python's `warnings.warn` which is thread-safe.", + "verification_criteria": [ + "src/result_types.py:Result and ErrorInfo exist with the documented fields; NilPath and NilRAGState are module-level singletons", + "src/result_types.py:Result is generic over T (Python 3.11+ Generic syntax)", + "src/result_types.py:Result.with_error() and with_data() produce modified copies (frozen semantics)", + "src/mcp_client.py:_resolve_and_check returns Result[Path] (not tuple); no 'assert p is not None' chain", + "src/mcp_client.py:read_file, list_directory, search_files, get_file_summary, etc. return Result[str]", + "src/ai_client.py:ProviderError class is removed (no longer raised; ErrorInfo replaces it)", + "src/ai_client.py:_classify_*_error() functions return ErrorInfo (not raise)", + "src/ai_client.py:_send_() functions are renamed to _send__result() and return Result[str]", + "src/ai_client.py:send() is decorated with @typing_extensions.deprecated", + "src/ai_client.py:send_result() is the new public API returning Result[str, ErrorInfo]", + "src/rag_engine.py:RAGEngine methods return Result (not raise ImportError/ValueError)", + "src/rag_engine.py:NilRAGState is used for unconfigured state", + "tests/test_result_types.py:8+ tests pass (Result construction, with_error, with_data, NilPath singleton, ErrorKind enum)", + "tests/test_mcp_client_paths.py:6+ tests pass (new Result return types)", + "tests/test_ai_client_result.py:8+ tests pass (new Result API, deprecation warning)", + "tests/test_rag_engine_result.py:4+ tests pass (new Result return types)", + "tests/test_deprecation_warnings.py:send() emits exactly one DeprecationWarning per call site (cached)", + "tests/test_mcp_client.py (existing): no regressions", + "tests/test_ai_client.py (existing): no regressions", + "tests/test_minimax_provider.py, test_qwen_provider.py, test_llama_provider.py, test_grok_provider.py (existing): no regressions", + "tests/test_rag_engine.py (existing): no regressions", + "conductor/code_styleguides/error_handling.md: documented with the 5 patterns, Python mappings, decision tree, examples", + "conductor/product-guidelines.md: new 'Data-Oriented Error Handling' section added", + "conductor/workflow.md: new note in Code Style section", + "docs/guide_ai_client.md: updated with Result API + deprecation note", + "docs/guide_mcp_client.md: updated with Result return types", + "conductor/tracks.md: data_oriented_error_handling_20260606 entry added; public_api_migration_20260606 placeholder added", + "pyproject.toml: typing_extensions>=4.5.0 dependency added", + "import src.result_types < 50ms (no heavy imports at top level; verified by scripts/audit_main_thread_imports.py)", + "No new threading.Thread calls in src/ (per project invariant)", + "No new Optional[X] in the 3 refactored files (verified by ripgrep)" + ], + "links": { + "backlog_entry": "conductor/tracks.md (to be added)", + "code_styleguide": "conductor/code_styleguides/error_handling.md (to be created in Phase 1)", + "testing_guide": "docs/guide_testing.md", + "ai_client_guide": "docs/guide_ai_client.md", + "mcp_client_guide": "docs/guide_mcp_client.md", + "workflow_pitfalls": "conductor/workflow.md#known-pitfalls-2026-06-05", + "related_tracks": [ + "conductor/tracks/startup_speedup_20260606/", + "conductor/tracks/test_batching_refactor_20260606/", + "conductor/tracks/qwen_llama_grok_integration_20260606/", + "conductor/tracks/regression_fixes_20260605/", + "conductor/tracks/live_gui_test_hardening_v2_20260605/" + ], + "external_docs": [ + "https://www.dgtlgrove.com/p/the-easiest-way-to-handle-errors (Fleury article)" + ] + } +} diff --git a/conductor/tracks/data_oriented_error_handling_20260606/state.toml b/conductor/tracks/data_oriented_error_handling_20260606/state.toml new file mode 100644 index 00000000..a3f6d10c --- /dev/null +++ b/conductor/tracks/data_oriented_error_handling_20260606/state.toml @@ -0,0 +1,146 @@ +# Track state for data_oriented_error_handling_20260606 +# Updated by Tier 2 Tech Lead as tasks complete + +[meta] +track_id = "data_oriented_error_handling_20260606" +name = "Data-Oriented Error Handling (Fleury Pattern)" +status = "active" +current_phase = 0 +last_updated = "2026-06-06" + +[blocked_by] +startup_speedup_20260606 = "merged" +test_batching_refactor_20260606 = "merged" +qwen_llama_grok_integration_20260606 = "merged" + +[blocks] +public_api_migration_20260606 = "planned in spec §12.1" + +[phases] +# Phase 1: Foundation (no user-facing changes; sets up the convention) +phase_1 = { status = "pending", checkpoint_sha = "", name = "Foundation: result_types module + style guide + baseline check" } +# Phase 2: mcp_client.py refactor +phase_2 = { status = "pending", checkpoint_sha = "", name = "mcp_client.py refactor (Result + nil-sentinel)" } +# Phase 3: ai_client.py refactor (highest risk; ProviderError removal) +phase_3 = { status = "pending", checkpoint_sha = "", name = "ai_client.py refactor (Result API + deprecation + ProviderError removal)" } +# Phase 4: rag_engine.py refactor +phase_4 = { status = "pending", checkpoint_sha = "", name = "rag_engine.py refactor (Result + NilRAGState)" } +# Phase 5: Deprecation wiring + docs + integration +phase_5 = { status = "pending", checkpoint_sha = "", name = "Deprecation wiring + docs + integration + archive" } + +[tasks] +# Phase 1: Foundation +t1_1 = { status = "pending", commit_sha = "", description = "Baseline verification: confirm startup_speedup, test_batching_refactor, qwen_llama_grok tracks merged; vendor_capabilities.py, openai_compatible.py, qwen_adapter.py exist" } +t1_2 = { status = "pending", commit_sha = "", description = "Add typing_extensions>=4.5.0,<5.0.0 to pyproject.toml dependencies" } +t1_3 = { status = "pending", commit_sha = "", description = "Red: tests/test_result_types.py (8+ tests: Result construction, with_error, with_data, NilPath, ErrorKind, frozen semantics)" } +t1_4 = { status = "pending", commit_sha = "", description = "Green: implement src/result_types.py with ErrorKind, ErrorInfo, Result[T], NilPath, NilRAGState" } +t1_5 = { status = "pending", commit_sha = "", description = "Create conductor/code_styleguides/error_handling.md (canonical reference; ~400 lines covering the 5 patterns + Python mappings + decision tree + examples)" } +t1_6 = { status = "pending", commit_sha = "", description = "Add 'Data-Oriented Error Handling' section to conductor/product-guidelines.md (referencing the new styleguide)" } +t1_7 = { status = "pending", commit_sha = "", description = "Add note to conductor/workflow.md Code Style section referencing the new styleguide" } +t1_8 = { status = "pending", commit_sha = "", description = "Verify src/result_types.py is import-time-safe (< 50ms; passes scripts/audit_main_thread_imports.py)" } +t1_9 = { status = "pending", commit_sha = "", description = "Phase 1 checkpoint commit + git note" } +# Phase 2: mcp_client.py refactor +t2_1 = { status = "pending", commit_sha = "", description = "Red: tests/test_mcp_client_paths.py (verify _resolve_and_check returns Result; verify read_file returns Result[str])" } +t2_2 = { status = "pending", commit_sha = "", description = "Green: refactor _resolve_and_check in src/mcp_client.py to return Result[Path]" } +t2_3 = { status = "pending", commit_sha = "", description = "Refactor read_file to return Result[str] (no more (p, err) tuple)" } +t2_4 = { status = "pending", commit_sha = "", description = "Refactor list_directory to return Result[str]" } +t2_5 = { status = "pending", commit_sha = "", description = "Refactor search_files to return Result[str]" } +t2_6 = { status = "pending", commit_sha = "", description = "Refactor get_file_summary, py_get_skeleton, py_get_code_outline, py_get_definition, py_get_imports, py_find_usages, etc. (all MCP tool functions) to return Result[str]" } +t2_7 = { status = "pending", commit_sha = "", description = "Remove the 30+ 'assert p is not None' chain (lines 304-794); the Result pattern makes them unnecessary" } +t2_8 = { status = "pending", commit_sha = "", description = "Update the tool dispatch internals (mcp_client.async_dispatch) to extract result.data and log result.errors via comms log" } +t2_9 = { status = "pending", commit_sha = "", description = "Run full test suite; ensure no regressions in tests/test_mcp_client.py" } +t2_10 = { status = "pending", commit_sha = "", description = "Phase 2 checkpoint commit + git note" } +# Phase 3: ai_client.py refactor (HIGHEST RISK) +t3_1 = { status = "pending", commit_sha = "", description = "Red: tests/test_ai_client_result.py (verify _send__result returns Result[str]; verify send_result public API; verify ProviderError is removed)" } +t3_2 = { status = "pending", commit_sha = "", description = "Red: tests/test_deprecation_warnings.py (verify send() emits DeprecationWarning)" } +t3_3 = { status = "pending", commit_sha = "", description = "Refactor _classify__error() to return ErrorInfo (not raise ProviderError); remove the raise statement" } +t3_4 = { status = "pending", commit_sha = "", description = "Refactor _send_() -> _send__result() for all 8 vendors (Gemini, Anthropic, DeepSeek, MiniMax, Gemini CLI, Qwen, Llama, Grok); new return type is Result[str]" } +t3_5 = { status = "pending", commit_sha = "", description = "Remove the ProviderError class from src/ai_client.py" } +t3_6 = { status = "pending", commit_sha = "", description = "Remove the now-dead 'except ProviderError' clause (line 1338)" } +t3_7 = { status = "pending", commit_sha = "", description = "Add send_result() public API to src/ai_client.py; returns Result[str]" } +t3_8 = { status = "pending", commit_sha = "", description = "Add @typing_extensions.deprecated decorator to send(); verify it emits DeprecationWarning at first call per site" } +t3_9 = { status = "pending", commit_sha = "", description = "Run full test suite; check for deprecation warning spam in test output; add filterwarnings to tests/conftest.py if needed" } +t3_10 = { status = "pending", commit_sha = "", description = "Run all 8 vendor test files (test_minimax_provider, test_qwen_provider, test_llama_provider, test_grok_provider, test_ai_client_cli, test_deepseek_provider, etc.); ensure no regressions" } +t3_11 = { status = "pending", commit_sha = "", description = "Phase 3 checkpoint commit + git note" } +# Phase 4: rag_engine.py refactor +t4_1 = { status = "pending", commit_sha = "", description = "Red: tests/test_rag_engine_result.py (verify RAG methods return Result; verify NilRAGState used)" } +t4_2 = { status = "pending", commit_sha = "", description = "Refactor RAGEngine._init_vector_store to return Result[None] (replaces raise ImportError / ValueError)" } +t4_3 = { status = "pending", commit_sha = "", description = "Refactor RAGEngine._validate_collection_dim to return Result[None] (replaces broad except Exception)" } +t4_4 = { status = "pending", commit_sha = "", description = "Refactor RAGEngine.is_empty, add_documents, search, index_file to return Result where appropriate" } +t4_5 = { status = "pending", commit_sha = "", description = "Verify tests/test_rag_engine.py still passes (no regressions)" } +t4_6 = { status = "pending", commit_sha = "", description = "Phase 4 checkpoint commit + git note" } +# Phase 5: Deprecation wiring + docs + integration +t5_1 = { status = "pending", commit_sha = "", description = "Add filterwarnings('ignore::DeprecationWarning:src.ai_client') to tests/conftest.py to silence the send() deprecation in existing tests" } +t5_2 = { status = "pending", commit_sha = "", description = "Update docs/guide_ai_client.md: new 'Data-Oriented Error Handling (Fleury Pattern)' section; document the Result API; document the deprecation" } +t5_3 = { status = "pending", commit_sha = "", description = "Update docs/guide_mcp_client.md: document the new Result return types; explain the nil-sentinel pattern" } +t5_4 = { status = "pending", commit_sha = "", description = "Add public_api_migration_20260606 placeholder to conductor/tracks.md (in the Remaining Backlog section)" } +t5_5 = { status = "pending", commit_sha = "", description = "Manual smoke test: launch GUI; send a message; verify Result path works end-to-end; verify deprecation warning fires once when send() is called" } +t5_6 = { status = "pending", commit_sha = "", description = "Phase 5 checkpoint commit + git note (TRACK COMPLETE)" } +t5_7 = { status = "pending", commit_sha = "", description = "git mv conductor/tracks/data_oriented_error_handling_20260606 to conductor/tracks/archive/" } +t5_8 = { status = "pending", commit_sha = "", description = "Update conductor/tracks.md: move data_oriented_error_handling_20260606 entry to Recently Completed" } +t5_9 = { status = "pending", commit_sha = "", description = "Final state.toml update: mark all phases completed; add final note" } + +[verification] +# Filled as phases complete +phase_1_foundation_complete = false +phase_1_baseline_verified = false +phase_1_styleguide_written = false +phase_2_mcp_client_refactored = false +phase_3_ai_client_refactored = false +phase_3_provider_error_removed = false +phase_3_send_deprecated = false +phase_3_send_result_added = false +phase_4_rag_engine_refactored = false +phase_5_docs_updated = false +phase_5_smoke_test_passed = false +phase_5_track_archived = false +full_test_suite_passes = false +no_new_optional_in_3_files = false +no_new_threading_thread_calls = false +import_src_result_types_fast = false + +[result_types_coverage] +# Filled as tasks complete +result_construction = false +result_with_error = false +result_with_data = false +result_ok_property = false +result_frozen = false +nil_path_singleton = false +nil_rag_state_singleton = false +error_kind_enum = false +error_info_ui_message = false + +[mcp_client_refactor_stats] +# Filled in Phase 2 +functions_refactored = 0 +asserts_removed = 0 +tests_pass_before = 0 +tests_pass_after = 0 + +[ai_client_refactor_stats] +# Filled in Phase 3 +send_renamed_to_send_result = false +provider_error_removed = false +_send_renamed_to_result = 0 +of_total = 0 +classify_error_returns_error_info = 0 +of_total = 0 +deprecation_warning_emitted = false +tests_pass_before = 0 +tests_pass_after = 0 + +[rag_engine_refactor_stats] +# Filled in Phase 4 +methods_refactored = 0 +imports_removed = 0 +value_errors_removed = 0 +tests_pass_before = 0 +tests_pass_after = 0 + +[public_api_migration_followup] +# Placeholder for the follow-up track +track_id = "public_api_migration_20260606" +status = "planned_in_data_oriented_error_handling_20260606" +removes = ["ai_client.send()"] +migrates = ["multi_agent_conductor.py", "app_controller.py", "tests/*"]