From a160b753bb712ab14b276c8a79f7238bda0d422d Mon Sep 17 00:00:00 2001 From: Ed_ Date: Wed, 17 Jun 2026 22:14:59 -0400 Subject: [PATCH] =?UTF-8?q?conductor(track):=20add=20Phase=2010=20?= =?UTF-8?q?=E2=80=94=20full=20Result[T]=20migration=20for=2027=20SILENT=5F?= =?UTF-8?q?SWALLOW=20+=2014=20new=20UNCLEAR=20sites?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../tracks/result_migration_20260616/spec.md | 16 +- .../metadata.json | 65 +++++-- .../plan.md | 162 +++++++++++++++++- .../state.toml | 47 ++++- 4 files changed, 256 insertions(+), 34 deletions(-) diff --git a/conductor/tracks/result_migration_20260616/spec.md b/conductor/tracks/result_migration_20260616/spec.md index accb543c..5b6eeb02 100644 --- a/conductor/tracks/result_migration_20260616/spec.md +++ b/conductor/tracks/result_migration_20260616/spec.md @@ -37,7 +37,7 @@ sites** across the codebase. **5 sub-tracks with consistent `result_migration_*` prefix:** 1. `result_migration_review_pass` (T-shirt: S) — 57 sites (32 UNCLEAR + 25 INTERNAL_RETHROW); updates the audit's heuristics -2. `result_migration_small_files` (T-shirt: L) — 37 files (35 SMALL + 2 MEDIUM); **shipped 2026-06-17** with documented G4 deviation: 76 sites (62V + 10S + 4 UNCLEAR) → 49 migrated (6 full `Result[T]` + 43 exception narrowing) + 13 already compliant + 27 silent-swallow sites remain (follow-up sub-track planned) +2. `result_migration_small_files` (T-shirt: L) — 37 files (35 SMALL + 2 MEDIUM); **shipped 2026-06-17** with documented G4 deviation: 76 sites (62V + 10S + 4 UNCLEAR) → 49 migrated (6 full `Result[T]` + 43 exception narrowing) + 13 already compliant + 27 silent-swallow sites remain; **Phase 10 in progress** (full Result[T] migration for the 27 sites + 2-3 new audit heuristics for the 14 new UNCLEAR sites) 3. `result_migration_app_controller` (T-shirt: XL) — 56 sites (35 V + 3 S + 2 ? + 16 C; 13 FastAPI boundary stay as-is) 4. `result_migration_gui_2` (T-shirt: XL) — **55 sites** (37 V + 2 S + **14 ?** + 2 C; the 14 ? includes the +1 site from the review pass: `src/gui_2.py:1349`) 5. `result_migration_baseline_cleanup` (T-shirt: L) — 112 sites (77 V + 10 S + 6 ? + 19 C in the 3 refactored files) @@ -57,11 +57,11 @@ sites** across the codebase. > the audit script is now correct (3 bugs fixed in Phase 1 of that sub-track), > and the 37 SMALL+MEDIUM files have been processed: > - **49/76 sites migrated** (6 full `Result[T]` + 43 exception narrowing) + 13 already compliant -> - **27 sites remain `INTERNAL_SILENT_SWALLOW`** (narrow-catch + pass); follow-up sub-track planned -> - **Audit's UNCLEAR count: 7 → 21** (+14 sites) — the narrowing created patterns the audit's heuristics don't recognize; follow-up sub-track will add 2-3 new heuristics +> - **27 sites remain `INTERNAL_SILENT_SWALLOW`** (narrow-catch + pass); **Phase 10 in progress** (full Result[T] migration; not narrowing, not logging-only, not silent recovery) +> - **Audit's UNCLEAR count: 7 → 21** (+14 sites) - the narrowing created patterns the audit's heuristics don't recognize; **Phase 10 in progress** (2-3 new heuristics) > - **Bonus defensive fix:** `try/except (OSError, tomllib.TOMLDecodeError)` in `load_track_state` unblocked 7+ tests > - **Test result:** all 11 test tiers PASS (tier-1-unit-comms, tier-1-unit-core, tier-1-unit-gui, tier-1-unit-headless, tier-1-unit-mma, tier-2-mock_app-comms, tier-2-mock_app-core, tier-2-mock_app-gui, tier-2-mock_app-headless, tier-2-mock_app-mma, tier-3-live_gui) -> - **Documented G4 deviation:** 27 silent-swallow sites remain. A follow-up sub-track `result_migration_silent_swallow_followup_` is planned (TBD; see "Recommended Sequence" below for the new ordering) +> - **Documented G4 deviation:** 27 silent-swallow sites remain. **Phase 10 of this sub-track** (not a separate sub-track) does the full Result[T] migration; the user has directed that Result[T] is mandatory, not optional, given the project's heavy use of multi-threaded `io_pool` dispatch (Python has no wave-based preemptive thread pipelining, so every soft/hard failure point needs full context). --- @@ -127,7 +127,7 @@ applied. Both feed into all later sub-tracks. **Scope:** 37 files (the 35 SMALL + 2 MEDIUM from the `--by-size` bucket); **76 sites (62V + 10S + 4 UNCLEAR) → 49 migrated + 13 already compliant + 27 silent-swallow remain.** **T-shirt size:** L (batched; ~750 lines changed across 37 files + 1 audit script + 1 new test file). -**Status:** **shipped 2026-06-17** with documented G4 deviation (27 sites remain `INTERNAL_SILENT_SWALLOW`; follow-up sub-track planned). +**Status:** **shipped 2026-06-17** with documented G4 deviation (27 sites remain `INTERNAL_SILENT_SWALLOW`; **Phase 10 of this sub-track** does the full Result[T] migration per the user's explicit direction). **Why second:** the small files are quick wins; they don't depend on the orchestrator (app_controller) or the GUI. Some of them DO depend on @@ -153,8 +153,8 @@ Phase 1 of this sub-track (audit-script bug fixes) unblocks sub-tracks public API changes may be acceptable. Tier 2 chose narrowing for 43 sites to avoid ~100+ caller updates. **Caveat:** narrowing without `logging.warning(...)` is **silent recovery** (no trace). The 27 sites that remain `INTERNAL_SILENT_SWALLOW` - are documented in the track completion report; a follow-up sub-track is - planned to add logging or full Result migration to them. + are documented in the track completion report; **Phase 10 of this sub-track** is + planned to do the full Result[T] migration for them. - **Phase 9: Verification** — all 11 test tiers PASS; per-site report + track completion report written; state.toml + metadata.json marked completed. - **Bonus defensive fix:** `try/except (OSError, tomllib.TOMLDecodeError)` in @@ -174,7 +174,7 @@ pass or narrow-catch + return None). These are categorized as: **Migration-target sites introduced by the narrowing:** the audit's UNCLEAR count went **7 → 21** (+14 sites) because the narrowing created patterns the audit's -heuristics don't recognize. A follow-up sub-track is planned to add 2-3 new heuristics +heuristics don't recognize. **Phase 10 of this sub-track** adds 2-3 new heuristics (heavily-narrowed `except` without logging; `except` returning Result in non-`*_result` function) that reclassify these. diff --git a/conductor/tracks/result_migration_small_files_20260617/metadata.json b/conductor/tracks/result_migration_small_files_20260617/metadata.json index 32f38a8f..5a648d8c 100644 --- a/conductor/tracks/result_migration_small_files_20260617/metadata.json +++ b/conductor/tracks/result_migration_small_files_20260617/metadata.json @@ -1,8 +1,8 @@ { "id": "result_migration_small_files_20260617", - "title": "Result Migration Sub-Track 2 (Small Files + Audit-Script Bug Fixes)", + "title": "Result Migration Sub-Track 2 (Small Files + Audit-Script Bug Fixes + Phase 10 Result[T] Follow-up)", "type": "refactor + audit-script maintenance", - "status": "completed", + "status": "active", "priority": "A", "created": "2026-06-17", "owner": "tier2-tech-lead", @@ -17,13 +17,18 @@ "small_files": 35, "medium_files": 2, "sites_to_migrate": 76, + "sites_migrated_phase_3_to_8": 49, + "sites_migrated_phase_10": 0, "violation_sites": 62, "suspicious_sites": 10, "unclear_sites": 4, "unclear_sites_outside_review_scope": 4, - "audit_script_lines_changed": "~60 (3 bug fixes; one per commit)", - "audit_script_heuristics_added": "0-2 (conditional on the 4 UNCLEAR patterns)", - "report_lines": "~200-300 (per-site decisions for 4 UNCLEAR + per-file summary + audit-script fix summary)" + "silent_swallow_sites_remaining_after_phase_8": 27, + "new_unclear_sites_from_narrowing": 14, + "io_pool_callback_sites_to_thread_result": 4, + "audit_script_lines_changed": "~60 (3 bug fixes; one per commit) + ~30 (2-3 new heuristics in Phase 10)", + "audit_script_heuristics_added": "0-2 (conditional on the 4 UNCLEAR patterns) + 2-3 (Phase 10)", + "report_lines": "~200-300 (per-site decisions for 4 UNCLEAR + per-file summary + audit-script fix summary) + ~100 (Phase 10 addendum)" }, "depends_on": [ "result_migration_20260616 (umbrella)", @@ -43,17 +48,21 @@ "scripts/audit_exception_handling.py has the 3 documented bugs fixed (visit_Try walker, render_json filter, render_json truncation)", "Re-running the audit post-Phase-1: src/rag_engine.py:31 is in the findings; per-file list is complete; per-file list is not truncated to top 15", "The 4 UNCLEAR sites in SMALL files are classified (compliant or migration-target); decisions recorded in the report", - "All 37 files (35 SMALL + 2 MEDIUM) are migrated to the convention", - "Re-running the audit post-Phase-9: 0 migration-target sites in the 37-file scope", + "All 37 files (35 SMALL + 2 MEDIUM) are migrated to the convention (49 sites in Phase 3-8 + 27 sites in Phase 10)", + "Phase 10: full Result[T] migration for the 27 INTERNAL_SILENT_SWALLOW sites; no narrowing, no logging-only, no silent recovery. Every site returns Result[T] with structured ErrorInfo. Callers check result.ok and result.errors", + "Phase 10: 2-3 new audit heuristics that reclassify the 14 new UNCLEAR sites (created by the narrowing in Phase 3-8) as INTERNAL_COMPLIANT or BOUNDARY_*", + "Phase 10: the 4 io_pool callback sites (warmup.py:139/215/249 + hot_reloader.py:58) thread the Result through the io_pool completion handler; the completion handler checks result.ok", + "Re-running the audit post-Phase-10: 0 INTERNAL_SILENT_SWALLOW + 0 UNCLEAR + 0 migration-target sites in the 37-file scope (G4 deviation resolved)", "Full test pass count: all 11 test tiers PASS", - "Atomic commits per batch: spec, plan, metadata, state, 3 audit-script fix commits, 4 UNCLEAR classification commits, 35 SMALL migration commits (5-7 files per commit), 2 MEDIUM migration commits, completion commits" + "Atomic commits per batch: spec, plan, metadata, state, 3 audit-script fix commits, 4 UNCLEAR classification commits, 35 SMALL migration commits (5-7 files per commit), 2 MEDIUM migration commits, Phase 10 commits (27 Result[T] migrations + 2-3 new heuristics + verification + completion), completion commits" ], "out_of_scope": [ "Migrating the 3 BASELINE files (mcp_client, ai_client, rag_engine) - sub-track 5", "Migrating src/gui_2.py or src/app_controller.py - sub-tracks 4 and 3", "The send_result -> send mass rename - separate work after this phase", - "Refactoring the audit script's overall architecture - Phase 1 fixes 3 specific bugs only", - "Adding new Result patterns to areas that don't have any - this track migrates EXISTING sites only" + "Refactoring the audit script's overall architecture - Phase 1 fixes 3 specific bugs only; Phase 10 adds 2-3 new heuristics only", + "Adding new Result patterns to areas that don't have any - this track migrates EXISTING sites only", + "The 'public API' concern - this is a 20K LOC Python project, not enterprise. The convention requires Result[T] everywhere it can fail; callers are updated to check result.ok" ], "risks": [ { @@ -85,19 +94,43 @@ "id": "R6", "description": "The MEDIUM files (session_logger, warmup) have complex migrations that don't fit the Result pattern", "mitigation": "Per the styleguide, some sites are legitimately BOUNDARY_*; those stay as-is; decision is documented" + }, + { + "id": "R7 (Phase 10)", + "description": "A SILENT_SWALLOW site is actually a conditional capture that needs to inspect the exception (e.g., 'if e.specific_field == X: handle_gracefully()')", + "mitigation": "Full Result migration preserves the exception in result.errors[0].exception; the caller can inspect it. The Result migration is not destructive of the original logic" + }, + { + "id": "R8 (Phase 10)", + "description": "Migrating Result[T] through io_pool callbacks (warmup.py) requires the io_pool's API to accept Result returns", + "mitigation": "The io_pool already uses callback-based dispatch; the Result is delivered to the completion handler as a parameter. No io_pool change needed; the caller is updated to check result.ok" + }, + { + "id": "R9 (Phase 10)", + "description": "The 2-3 new audit heuristics misclassify sites that should be INTERNAL_BROAD_CATCH or INTERNAL_SILENT_SWALLOW", + "mitigation": "TDD: each heuristic has a failing test first; the test suite covers the canonical patterns. If a heuristic is too broad, narrow the conditions and re-test" } ], "estimated_effort": { - "method": "Scope + T-shirt size (per conductor/workflow.md section Tier 1 Track Initialization Rules). NO day estimates. The user / Tier 2 agent decides the actual pacing.", - "scope": "37 files (35 SMALL + 2 MEDIUM); 76 sites; 3 audit-script bug fixes; ~200-300 lines of report", - "tshirt_size": "L" + "method": "Scope (per conductor/workflow.md section Tier 1 Track Initialization Rules). NO day estimates. The user / Tier 2 agent decides the actual pacing.", + "scope": "37 files (35 SMALL + 2 MEDIUM); 76 sites total (49 migrated in Phase 3-8 + 27 to migrate in Phase 10); 3 audit-script bug fixes in Phase 1; 2-3 new audit heuristics in Phase 10; ~200-300 lines of report + ~100 lines of Phase 10 addendum" }, "deferred_to_followup_tracks": [ { "id": "result_migration_subsequent_subtracks", "title": "Result Migration Sub-Tracks 3-5", - "description": "After this sub-track ships, sub-tracks 3 (app_controller), 4 (gui_2), and 5 (baseline_cleanup) pick up the migration work. Sub-track 3 and 4 depend on the audit being correct (Phase 1 of this sub-track fixes the 3 bugs).", - "track_status": "blocked by this sub-track" + "description": "After this sub-track's Phase 10 ships, sub-tracks 3 (app_controller), 4 (gui_2), and 5 (baseline_cleanup) pick up the migration work. Sub-tracks 3 and 4 depend on the audit being correct (Phase 1 of this sub-track fixes the 3 bugs; Phase 10 adds 2-3 new heuristics).", + "track_status": "blocked by this sub-track (after Phase 10 ships)" } - ] + ], + "outcomes": { + "phase_3_to_8_sites_migrated": 49, + "phase_10_sites_migrated": 0, + "phase_10_pending": true, + "silent_swallow_sites_remaining_pre_phase_10": 27, + "new_unclear_sites_from_narrowing": 14, + "phase_10_heuristics_added": 0, + "phase_10_io_pool_callbacks_threaded": 0, + "phase_10_status": "pending; user-directed follow-up to resolve the G4 deviation (27 SILENT_SWALLOW + 14 new UNCLEAR sites)" + } } diff --git a/conductor/tracks/result_migration_small_files_20260617/plan.md b/conductor/tracks/result_migration_small_files_20260617/plan.md index b752e20c..d23b6fbe 100644 --- a/conductor/tracks/result_migration_small_files_20260617/plan.md +++ b/conductor/tracks/result_migration_small_files_20260617/plan.md @@ -318,6 +318,156 @@ The 35 SMALL files are batched 5-7 per commit (per the umbrella spec). The 2 MED --- +## Phase 10: Complete the Result[T] Migration (the 27 SILENT_SWALLOW + 14 new UNCLEAR sites) + +Sub-track 2 shipped with a documented G4 deviation: 27 sites remain `INTERNAL_SILENT_SWALLOW` (narrow-catch + pass) and 14 new `UNCLEAR` sites emerged from the narrowing strategy. The user has directed that **all 27 must be fully migrated to `Result[T]`** — not narrowed, not logged-and-returned, not narrowed-with-log. The `Result[T]` convention is mandatory: every `try/except` site that can fail returns `Result[T]` with structured `ErrorInfo`, and the caller decides what to do. The 14 new UNCLEAR sites are addressed by 2-3 new audit heuristics that recognize the post-migration patterns. + +This is a codebase-hardening phase. The project uses `io_pool` for multi-threaded dispatch; Python has no wave-based preemptive thread pipelining, so every soft/hard failure point needs full context (category, message, source, exception) — not silent recovery. + +### 10.1 — Enumerate the remaining sites + +- [ ] **Task 10.1.1: Run the audit and extract the 27 SILENT_SWALLOW + 14 new UNCLEAR sites** + - WHERE: `scripts/audit_exception_handling.py` (already on the branch from Phase 1) + - WHAT: `uv run python scripts/audit_exception_handling.py --json > audit_pre_phase10.json`; parse the per-file findings; for each file in the 37-file scope, list the SILENT_SWALLOW and new-UNCLEAR sites with file:line + - HOW: read the JSON; filter by category and by file + - OUTPUT: per-site list with file:line + current snippet + context function name + - COMMIT: `docs(track): enumerate Phase 10 target sites (27 SILENT_SWALLOW + 14 UNCLEAR)` + - GIT NOTE: Per-site enumeration; file:line; the 5 known sites (startup_profiler.py:40, file_cache.py:98, outline_tool.py:90, warmup.py:139/215/249, hot_reloader.py:58) plus the others to be enumerated + +### 10.2 — Per-file full Result[T] migration + +For each of the 27 SILENT_SWALLOW sites: + +1. Read the function's current signature and behavior +2. Change the return type to `Result[T]` (or `Result[None]` if the function returns `None`) +3. Add `Result` import if needed (from `src/result_types.py`) +4. In the except body, capture the exception and convert to `ErrorInfo`: + ```python + except SomeError as e: + return Result(data=NIL_T, errors=[ErrorInfo( + category="", + message=str(e), + source=".", + exception=e, + )]) + ``` + - If the function has a sensible fallback value (e.g., `default_value`), use `Result(data=default_value, errors=[...])` instead of `NIL_T`. The caller still sees the error in `.errors` and decides what to do. +5. Update **all** callers to check `.ok` and `.errors`. The caller decides what to do (log, fall back, surface to UI, re-raise as a thread-pipeline failure). No caller should ignore `.errors` silently. +6. Add a test for the new Result-based API. Tests must cover: + - The success path: `assert result.ok and result.data == ` + - The error path: `assert not result.ok and result.errors[0].category == and result.errors[0].exception is SomeError` + - Callers that previously ignored the return value must be updated to check `result.ok` + +The migration is per-file. Group files into atomic commits (1-2 sites per commit, or all sites in a file in one commit if the file is small). The 5 known sites to start with (from the track completion report): + +- [ ] **Task 10.2.1: Migrate `src/startup_profiler.py:40` to `Result[T]`** (remove the `stderr.write` log; return Result with the profile data and the captured exception) +- [ ] **Task 10.2.2: Migrate `src/file_cache.py:98` to `Result[T]`** (the mtime cache fallback; return Result with the default cache value and the captured exception) +- [ ] **Task 10.2.3: Migrate `src/outline_tool.py:90` to `Result[T]`** (the ast.unparse fallback; return Result with the empty outline and the captured exception) +- [ ] **Task 10.2.4: Migrate `src/warmup.py:139` (on_complete callback) to `Result[T]`** (the user-callback error path; the callback now returns Result; the warmup manager threads the Result to the io_pool completion handler) +- [ ] **Task 10.2.5: Migrate `src/warmup.py:215` (_record_success callback) to `Result[T]`** +- [ ] **Task 10.2.6: Migrate `src/warmup.py:249` (_record_failure callback) to `Result[T]`** +- [ ] **Task 10.2.7: Migrate `src/hot_reloader.py:58` (module reload) to `Result[T]`** (the reload error path; the hot-reloader manager threads the Result to the module-reload completion handler) + +The other 20 sites: tier-2 enumerates from the audit JSON (Task 10.1.1) and migrates each. Each site gets its own task in this phase; the plan's per-task list is updated as sites are enumerated. + +### 10.3 — Audit heuristics for the 14 new UNCLEAR sites + +The narrowing in sub-track 2 created 14 new UNCLEAR sites that the audit doesn't recognize. After the full Result migration in 10.2: +- Some of these will be reclassified automatically by existing heuristics (e.g., `Result`-returning code triggers `BOUNDARY_SDK` or heuristic #19 patterns) +- The remaining need 2-3 new heuristics in `scripts/audit_exception_handling.py`: + - **Heuristic A**: `try/except SomeError: return Result(data=NIL_T, errors=[ErrorInfo(...)])` in a non-`*_result` function → `INTERNAL_COMPLIANT` (the canonical Result-based recovery pattern, even when the function name doesn't end in `_result`) + - **Heuristic B**: `try/except SomeError: return Result(data=default_value, errors=[ErrorInfo(...)])` where the function's success path returns `Result(data=...)` → `INTERNAL_COMPLIANT` (the Result-based fallback pattern) + - **Heuristic C** (if needed): `try/except SomeError: return default_value` where the function's annotated return type is `Result[T]` → `INTERNAL_COMPLIANT` (the Result-typed fallback) + +- [ ] **Task 10.3.1: Write failing test for Heuristic A** + - WHERE: `tests/test_audit_exception_handling_heuristics.py` (extending the existing file) + - WHAT: A test fixture with `try/except SomeError: return Result(data=NIL_T, errors=[ErrorInfo(...)])` in a function whose name doesn't end in `_result`. Assert the audit classifies the except as `INTERNAL_COMPLIANT`. + - HOW: same `subprocess` + fixture pattern as the existing tests + +- [ ] **Task 10.3.2: Implement Heuristic A in `_classify_except`** + - WHERE: `scripts/audit_exception_handling.py` (the `_try_compliant_pattern` helper or `_classify_except` directly) + - WHAT: Detect the pattern; return `INTERNAL_COMPLIANT` + - HOW: AST inspection of the except body's `Return` statement; check that it returns a `Call` to `Result(...)` with `data=` and `errors=` kwargs; check that the enclosing function name does NOT end in `_result` + - COMMIT: `feat(scripts): heuristic A — Result-returning recovery in non-*_result function` + +- [ ] **Task 10.3.3: Write failing test for Heuristic B** + - WHERE: `tests/test_audit_exception_handling_heuristics.py` + - WHAT: A test fixture with `try/except SomeError: return Result(data=default, errors=[...])` where the function's success path also returns `Result(...)`. Assert `INTERNAL_COMPLIANT`. + - HOW: same pattern as 10.3.1 + +- [ ] **Task 10.3.4: Implement Heuristic B in `_classify_except`** + - WHERE: `scripts/audit_exception_handling.py` + - WHAT: Detect the pattern; return `INTERNAL_COMPLIANT` + - HOW: Check the except body's `Return` is a `Result(...)` call with both `data=` and `errors=` kwargs; check the function has a success path that also returns `Result(...)` + - COMMIT: `feat(scripts): heuristic B — Result-typed fallback pattern` + +- [ ] **Task 10.3.5: Add Heuristic C if needed** (conditional on whether A+B cover the 14 sites) + - WHERE: `tests/test_audit_exception_handling_heuristics.py` + `scripts/audit_exception_handling.py` + - WHAT: Detect the pattern; return `INTERNAL_COMPLIANT` + - HOW: Check the function's annotated return type is `Result[T]` and the except body returns a non-Result value (the fallback) + - COMMIT: `feat(scripts): heuristic C — Result-typed return with non-Result fallback` (conditional) + +- [ ] **Task 10.3.6: Verify the new heuristics reclassify the 14 UNCLEAR sites** + - WHERE: `scripts/audit_exception_handling.py` + - WHAT: Re-run the audit; assert the 14 sites are now `INTERNAL_COMPLIANT` or `BOUNDARY_*` + - HOW: parse the JSON; filter by the 14 file:line pairs + - COMMIT: rolled into 10.3.2 / 10.3.4 / 10.3.5 (whichever fires) + +### 10.4 — Update the per-site report + +- [ ] **Task 10.4.1: Extend the per-site report with the Phase 10 changes** + - WHERE: `docs/reports/RESULT_MIGRATION_SMALL_FILES_20260617.md` + - WHAT: Add a "Phase 10" section with: + - The full per-site table for the 27 SILENT_SWALLOW + 14 new UNCLEAR sites + - The new audit heuristics (per-site count delta) + - The Result-based API for each migrated function (what `.data` and `.errors` look like) + - The call-graph impact: which callers were updated; the threading model for warmup callbacks and hot-reloader (the Result now flows through the io_pool completion handler) + - HOW: append to the existing report; preserve the existing Phase 1-9 content + - COMMIT: `docs(report): add Phase 10 results to the per-site report` + - GIT NOTE: 27 SILENT_SWALLOW → 0; 14 new UNCLEAR → 0 (via the 2-3 new heuristics) + +### 10.5 — Verification + +- [ ] **Task 10.5.1: Run the audit post-Phase-10** + - WHERE: `scripts/audit_exception_handling.py` + - WHAT: `uv run python scripts/audit_exception_handling.py --json > audit_post_phase10.json`; verify: + - 0 `INTERNAL_SILENT_SWALLOW` sites in the 37-file scope + - 0 migration-target sites in the 37-file scope (G4 now met) + - 0 new `UNCLEAR` sites (the 14 are reclassified) + - HOW: parse the JSON; assert the 37 files have 0 V+S sites + - COMMIT: `docs(track): verify Phase 10 result migration complete (0 SILENT_SWALLOW; 0 UNCLEAR; 0 migration-target in 37-file scope)` + +- [ ] **Task 10.5.2: Run the full test suite** + - WHERE: `tests/` + - WHAT: `uv run python scripts/run_tests_batched.py`; verify all 11 tiers PASS + - HOW: the batched runner + - COMMIT: rolled into 10.5.1 + +- [ ] **Task 10.5.3: Update the track completion report** + - WHERE: `docs/reports/TRACK_COMPLETION_result_migration_small_files_20260617.md` + - WHAT: Add a "Phase 10 Addendum" section with the per-site count delta, the new heuristics, the threading-model impact (Result flows through io_pool for the 4 callback sites), and the test pass count + - HOW: append to the existing report + - COMMIT: `docs(reports): TRACK_COMPLETION_result_migration_small_files_20260617 addendum (Phase 10)` + - GIT NOTE: G4 deviation now resolved; the 37-file scope has 0 migration-target sites + +### 10.6 — Mark Phase 10 completed + +- [ ] **Task 10.6.1: Update state.toml and metadata.json** + - WHERE: `conductor/tracks/result_migration_small_files_20260617/state.toml` + `metadata.json`, `conductor/tracks.md` + - WHAT: Mark all Phase 10 tasks completed with commit SHAs; update `status: active → completed`; `current_phase: 10 → "complete"`; update `outcomes` in metadata.json + - HOW: edit the files + - COMMIT: `conductor(track): mark result_migration_small_files_20260617 Phase 10 completed (G4 deviation resolved)` + - GIT NOTE: 27 SILENT_SWALLOW sites migrated to Result[T]; 14 new UNCLEAR sites reclassified via 2-3 new audit heuristics; G4 now met + +- [ ] **Task 10.6.2: Update the umbrella spec to remove the follow-up note** + - WHERE: `conductor/tracks/result_migration_20260616/spec.md` + - WHAT: Change the "follow-up sub-track planned" line in the post-sub-track-2 callout to "Phase 10 of sub-track 2 complete; G4 deviation resolved" + - HOW: edit the spec + - COMMIT: `docs(track): update umbrella with sub-track 2 Phase 10 complete` + - GIT NOTE: 1-sentence note + +--- + ## Risks at the Plan Level | Risk | Mitigation | @@ -329,6 +479,9 @@ The 35 SMALL files are batched 5-7 per commit (per the umbrella spec). The 2 MED | New migration-target sites surface after the `visit_Try` fix | Task 1.4.1 verifies the count delta; the per-batch scope adjusts | | The audit-script fix commit is too large (>500 lines) | Each bug gets its own commit (1.1.2, 1.2.2, 1.3.2 are separate) | | The MEDIUM files (session_logger, warmup) have complex migrations that don't fit the Result pattern | Per the styleguide, some sites are legitimately `BOUNDARY_*`; those stay as-is. The decision is documented in the report | +| **Phase 10 R1:** A site that looks like a SILENT_SWALLOW fallback is actually a conditional capture that needs to inspect the exception to decide what to do | The full Result migration preserves the exception in `result.errors[0].exception`; the caller can inspect it. If the caller needs to branch on the exception, that's a follow-up for the caller (not this phase) | +| **Phase 10 R2:** Migrating `Result[T]` through `io_pool` callbacks (warmup) requires the io_pool's API to accept `Result[T]` returns | The io_pool already uses callback-based dispatch; the Result is delivered to the completion handler as a parameter. No io_pool change needed; the caller is updated to check `result.ok` | +| **Phase 10 R3:** The 2-3 new audit heuristics misclassify sites that should be `INTERNAL_BROAD_CATCH` or `INTERNAL_SILENT_SWALLOW` | TDD: each heuristic has a failing test first; the test suite covers the canonical patterns. If a heuristic is too broad, narrow the conditions and re-test | --- @@ -339,8 +492,9 @@ After Phase 9, capture in `docs/reports/RESULT_MIGRATION_SMALL_FILES_20260617.md - Audit pre-Phase-1: 76 sites (62V + 10S + 4?); 3 audit-script bugs documented - Audit post-Phase-1: 0 audit-script bugs (the 3 bugs are fixed) - Audit post-Phase-2: 4 UNCLEAR sites classified (decision count by category) -- Audit post-Phase-9: 0 migration-target sites in the 37-file scope -- Per-file migration summary (76 sites → 0; per-file counts) +- Audit post-Phase-9: 49/76 sites migrated; 27 SILENT_SWALLOW remain; 14 new UNCLEAR sites +- Audit post-Phase-10: 76/76 sites migrated (49 from Phase 3-8 + 27 from Phase 10); 0 SILENT_SWALLOW; 0 UNCLEAR (the 14 reclassified via 2-3 new heuristics) +- Per-file migration summary (76 sites → 0; per-file counts; per-site function signatures + ErrorInfo fields) - Per-site decisions for the 4 UNCLEAR sites -- Audit-script bug-fix summary (3 bugs; per-bug description + fix) -- Test pass count: all 11 tiers PASS; new tests added (6-9 for the audit-script fixes + N for the migrations) +- Audit-script bug-fix summary (3 from Phase 1 + 2-3 from Phase 10; per-bug description + fix) +- Test pass count: all 11 tiers PASS; new tests added (4 for Phase 1 + N for Phase 10 heuristics + M for Phase 10 migrations) diff --git a/conductor/tracks/result_migration_small_files_20260617/state.toml b/conductor/tracks/result_migration_small_files_20260617/state.toml index d6d6dd23..ce48e22d 100644 --- a/conductor/tracks/result_migration_small_files_20260617/state.toml +++ b/conductor/tracks/result_migration_small_files_20260617/state.toml @@ -4,8 +4,8 @@ [meta] track_id = "result_migration_small_files_20260617" name = "Result Migration Sub-Track 2 (Small Files + Audit-Script Bug Fixes)" -status = "completed" -current_phase = "complete" +status = "active" +current_phase = 10 last_updated = "2026-06-17" [parent] @@ -31,6 +31,7 @@ phase_6 = { status = "completed", checkpointsha = "f4a445bd", name = "Migrate Ph phase_7 = { status = "completed", checkpointsha = "a5b40bcf", name = "Migrate Phase 7 Batch: Infrastructure + Hook + Utility (8 files)" } phase_8 = { status = "completed", checkpointsha = "c329c869", name = "Migrate MEDIUM files (session_logger, warmup)" } phase_9 = { status = "completed", checkpointsha = "34387b9f", name = "Verification (audit re-run + test pass count + report + completion)" } +phase_10 = { status = "in_progress", checkpointsha = "", name = "Complete the Result[T] migration (27 SILENT_SWALLOW + 14 new UNCLEAR sites)" } [tasks] # Phase 1: Audit-Script Bug Fixes @@ -110,6 +111,29 @@ t9_4 = { status = "pending", commit_sha = "", description = "Update umbrella spe t9_5 = { status = "pending", commit_sha = "", description = "Mark the track as completed (metadata + state + tracks.md)" } t9_6 = { status = "pending", commit_sha = "", description = "Write docs/reports/TRACK_COMPLETION_result_migration_small_files_20260617.md" } +# Phase 10: Complete the Result[T] migration +t10_1_1 = { status = "pending", commit_sha = "", description = "Enumerate the 27 SILENT_SWALLOW + 14 new UNCLEAR sites from the audit JSON" } +t10_2_1 = { status = "pending", commit_sha = "", description = "Migrate src/startup_profiler.py:40 to Result[T] (remove stderr.write; capture exception in ErrorInfo)" } +t10_2_2 = { status = "pending", commit_sha = "", description = "Migrate src/file_cache.py:98 to Result[T] (mtime cache fallback; return Result with default + errors)" } +t10_2_3 = { status = "pending", commit_sha = "", description = "Migrate src/outline_tool.py:90 to Result[T] (ast.unparse fallback; return Result with empty outline + errors)" } +t10_2_4 = { status = "pending", commit_sha = "", description = "Migrate src/warmup.py:139 (on_complete callback) to Result[T]; update io_pool completion handler to check result.ok" } +t10_2_5 = { status = "pending", commit_sha = "", description = "Migrate src/warmup.py:215 (_record_success callback) to Result[T]" } +t10_2_6 = { status = "pending", commit_sha = "", description = "Migrate src/warmup.py:249 (_record_failure callback) to Result[T]" } +t10_2_7 = { status = "pending", commit_sha = "", description = "Migrate src/hot_reloader.py:58 (module reload) to Result[T]; update reload completion handler to check result.ok" } +# The remaining 20 SILENT_SWALLOW sites are enumerated in Task 10.1.1 and added as t10_2_8 through t10_2_27 +t10_3_1 = { status = "pending", commit_sha = "", description = "Write failing test for audit Heuristic A (Result-returning recovery in non-*_result function)" } +t10_3_2 = { status = "pending", commit_sha = "", description = "Implement audit Heuristic A in _classify_except" } +t10_3_3 = { status = "pending", commit_sha = "", description = "Write failing test for audit Heuristic B (Result-typed fallback pattern)" } +t10_3_4 = { status = "pending", commit_sha = "", description = "Implement audit Heuristic B in _classify_except" } +t10_3_5 = { status = "pending", commit_sha = "", description = "Add audit Heuristic C if needed (Result-typed return with non-Result fallback)" } +t10_3_6 = { status = "pending", commit_sha = "", description = "Verify the new heuristics reclassify the 14 new UNCLEAR sites" } +t10_4_1 = { status = "pending", commit_sha = "", description = "Extend the per-site report with Phase 10 changes (per-site table + heuristics + threading-model impact)" } +t10_5_1 = { status = "pending", commit_sha = "", description = "Run audit post-Phase-10; verify 0 SILENT_SWALLOW + 0 UNCLEAR + 0 migration-target in 37-file scope" } +t10_5_2 = { status = "pending", commit_sha = "", description = "Run full test suite; verify all 11 tiers PASS" } +t10_5_3 = { status = "pending", commit_sha = "", description = "Update track completion report with Phase 10 addendum" } +t10_6_1 = { status = "pending", commit_sha = "", description = "Mark Phase 10 completed (state + metadata + tracks.md)" } +t10_6_2 = { status = "pending", commit_sha = "", description = "Update umbrella spec to remove the follow-up note (Phase 10 complete; G4 resolved)" } + [verification] phase_1_audit_fixes_complete = true phase_2_unclear_classification_complete = true @@ -120,22 +144,33 @@ phase_6_provider_batch_complete = true phase_7_infra_batch_complete = true phase_8_medium_files_complete = true phase_9_verification_complete = true +phase_10_result_migration_complete = false report_exists = true umbrella_spec_updated = true audit_post_migration_zero_migration_target = false test_pass_count_unchanged = true -metadata_json_status_completed = true +metadata_json_status_completed = false # back to false; will be true after Phase 10 +silent_swallow_sites_migrated_to_result = 0 +new_unclear_sites_reclassified = 0 +new_audit_heuristics_added_phase_10 = 0 +io_pool_callback_sites_threaded_result = 0 +test_pass_count_unchanged = true [scope_metrics] files_target = 37 files_migrated = 24 files_audit_decision_only = 13 sites_target = 76 -sites_migrated = 49 +sites_migrated_phase_3_to_8 = 49 +sites_migrated_phase_10 = 0 sites_compliant_no_migration = 13 +sites_remaining_silent_swallow_pre_phase_10 = 27 unclear_sites_target = 4 unclear_sites_compliant = 2 unclear_sites_migration_target = 2 -audit_bugs_fixed = 3 -audit_heuristics_added = 0 +new_unclear_sites_from_narrowing = 14 +audit_bugs_fixed_phase_1 = 3 +audit_heuristics_added_phase_1 = 0 +audit_heuristics_added_phase_10 = 0 new_tests_added = 4 +io_pool_callback_sites = 4 # warmup.py:139, 215, 249 + hot_reloader.py:58