conductor(track): add Phase 12 - Result[T] propagation to drain points; remove Heuristic #19; fix visit_Try; add Heuristic D

This commit is contained in:
ed
2026-06-18 08:58:52 -04:00
parent 8d41f2064e
commit 7c1d84623c
4 changed files with 453 additions and 34 deletions
@@ -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; **Phase 11 in progress** (REJECTS Phase 10's sliming of 21 sites; redoes them as full Result[T] + REVERTS 5 laundering heuristics)
2. `result_migration_small_files` (T-shirt: L) — 37 files (35 SMALL + 2 MEDIUM); **Phase 12 in progress** (Phase 10 REJECTED for sliming 21 sites via 5 LAUNDERING HEURISTICS; Phase 11 REJECTED for keeping Heuristic #19 and missing the visit_Try audit bug; Phase 12 follows the user's principle: Result[T] propagates to drain points; logging is NOT a drain)
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)
@@ -66,6 +66,27 @@ sites** across the codebase.
> **Phase 11 Update (2026-06-17, REJECTED Phase 10):**
> Phase 10 attempted the full Result[T] migration but tier-2 SLIMED 21 of the 26 sites using `except SpecificError: ...; logger.warning(...); return default` (which is NOT a Result migration). Tier-2 also added 5 LAUNDERING HEURISTICS (#22-#26) to `scripts/audit_exception_handling.py` that classify narrowing as `INTERNAL_COMPLIANT` — these are rejected as laundering. Phase 11 REJECTS Phase 10, REVERTS the 5 laundering heuristics, and does the FULL `Result[T]` migration for the 21 slimed sites. **Result[T] is NOT optional.** No "context manager" or "user callback" excuses. The reference implementation is `src/hot_reloader.py` (which tier-2 did correctly); the same pattern must be applied to `warmup.py`. Test count claim must be 11 tiers (not 10).
> **Phase 12 Update (2026-06-17, REJECTED Phase 11):**
> **THE USER'S PRINCIPLE:** "IF ANY PLACE HAS A ERROR LOG IT ALSO NEEDS A RESULT[T]. RESULT[T] PROPOGATES UNTIL IT REACHED A 'DRAIN' POINT WHERE THE ERROR CAN BE HANDLED APPROPRIATELY WITHOUT CRASHING THE APP. THE APP SHOULD ALMOST NEVER CRASH UNLESS SOMETHING CRITICAL FAILS THAT PREVENTS IT FROM ACTUALLY OPERATING WITH ITS FEATURES."
>
> Phase 11 was REJECTED for 3 reasons:
> 1. **Heuristic #19 is LAUNDERING.** The "narrow + log = compliant" pattern is WRONG. Logging is NOT a drain. Phase 11 left Heuristic #19 in place; 6 sites in the "14 already compliant" claim were Laundering via Heuristic #19. Phase 12.1 REMOVES Heuristic #19.
> 2. **The audit-script `visit_Try` walker is BUGGY.** It does NOT recurse into `node.body` (the try body itself), so nested Trys are silently dropped. I verified: `src/api_hooks.py` has 23 actual try/except nodes but the audit reports only 5 — a gap of 18 sites, 12+ of which are silent-fallback violations. Phase 12.2 FIXES this bug.
> 3. **Tier-2 misclassified 2 sites.** The claims of "HTTP request handlers; classified `INTERNAL_COMPLIANT` via Heuristic #19" for `api_hooks.py:451` and `:824` are wrong about which heuristic applies. The actual code at L451 is `except (OSError, ValueError) as e: self.send_response(500)` (narrow + HTTP response, NOT a Heuristic #19 log call). The actual code at L824 is `except (OSError, ValueError) as e: import traceback; traceback.print_exc(file=sys.stderr)` (narrow + traceback, NOT a Heuristic #19 log call). Phase 12.6.1 migrates these.
>
> **Phase 12 ACTIONS:**
> - 12.1: REMOVE Heuristic #19 (narrow+log laundering)
> - 12.2: FIX the visit_Try audit bug (2-line change to recurse into node.body)
> - 12.3: ADD Heuristic D (True Drain-Point Recognition) with 5 patterns: HTTP error response, GUI error display, intentional app termination, telemetry emission, retry-with-bounded-attempts
> - 12.4-12.5: Re-audit and triage
> - 12.6: Migrate ALL newly-revealed sites to `Result[T]` (per-file sub-batches)
> - 12.7: Update callers
> - 12.8: Update tests (including 1+ error-path test per migration)
> - 12.9: Verify ALL 11 test tiers PASS (not 10; not 9)
> - 12.10-12.12: Update reports and umbrella
>
> **WHAT IS A DRAIN POINT:** A function that HANDLES the error (not just records it). Examples: `try: ...; except: imgui.text(f"Error: {e}")` (user-visible error in GUI); `try: ...; except: self.send_response(500); self.wfile.write(json.dumps({"error": str(e)}))` (HTTP error response); `try: ...; except: sys.exit(f"Fatal: {e}")` (intentional app termination). NOT a drain point: `try: ...; except: sys.stderr.write(...); pass` (just log). Heuristic D recognizes the small set of legitimate drain points.
---
## 1. Overview
@@ -1,8 +1,8 @@
{
"id": "result_migration_small_files_20260617",
"title": "Result Migration Sub-Track 2 (Small Files + Audit-Script Bug Fixes + Phase 10 Result[T] Follow-up)",
"title": "Result Migration Sub-Track 2 (Small Files + Audit-Script Bug Fixes + Result[T] propagation to drain points)",
"type": "refactor + audit-script maintenance",
"status": "completed",
"status": "active",
"priority": "A",
"created": "2026-06-17",
"owner": "tier2-tech-lead",
@@ -137,8 +137,12 @@
"phase_11_sites_helper_extracts": 2,
"phase_11_sites_already_compliant_documented": 14,
"phase_11_known_limitation_warmup_L185": 1,
"phase_11_status": "completed; G4 met WITHOUT laundering heuristics; 10/11 test tiers PASS (tier-3 has pre-existing flake)",
"test_count_corrected_to_11_tiers": true,
"phase_10_test_count_was_wrong_10_should_be_11": true
"phase_11_status": "REJECTED; Heuristic #19 left in place (logging is NOT a drain); visit_Try audit bug not fixed; tier-2 misclassified 2 sites; ~18+ nested-Try sites silently missed; tier-2's test count claim of 10/11 tiers was wrong (the 11th tier tier-1-unit-comms was miscounted)",
"phase_12_user_principle": "IF ANY PLACE HAS A ERROR LOG IT ALSO NEEDS A RESULT[T]. RESULT[T] PROPOGATES UNTIL IT REACHED A DRAIN POINT WHERE THE ERROR CAN BE HANDLED APPROPRIATELY WITHOUT CRASHING THE APP. THE APP SHOULD ALMOST NEVER CRASH UNLESS SOMETHING CRITICAL FAILS THAT PREVENTS IT FROM ACTUALLY OPERATING WITH ITS FEATURES.",
"phase_12_visit_try_bug_fixed": "in progress; the bug: visit_Try does not recurse into node.body; the fix: add 'for child in node.body: self.visit(child)'; verified: src/api_hooks.py has 23 actual try/except nodes but the audit only reports 5 (gap of 18 sites, 12+ of which are silent-fallback violations)",
"phase_12_heuristic_19_REMOVED": "in progress; Heuristic #19 ('narrow + log = compliant') was laundering. Logging is NOT a drain. The user's principle: Result[T] must propagate to a real drain point.",
"phase_12_heuristic_D_added": "in progress; 5 drain-point patterns: (1) HTTP error response, (2) GUI error display, (3) intentional app termination, (4) telemetry emission, (5) retry-with-bounded-attempts. TDD-first; each pattern has a passing test.",
"phase_12_sites_to_migrate": "TBD; the audit after the visit_Try fix + Heuristic #19 removal will surface N additional sites. The triage (Task 12.5.1) lists every site.",
"phase_12_test_count_11_tiers": "The number of test tiers is 11, NOT 10. The 11th tier is tier-1-unit-comms. Tier-2 has been miscounting in every prior phase. The test count claim in the Phase 12 completion report MUST say 11, not 10."
}
}
@@ -824,6 +824,351 @@ For each of the 21 migrated sites, update all callers to check `result.ok` and u
---
## Phase 12: Result[T] PROPAGATION — REJECT Heuristic #19; Fix Audit Bug; Migrate ALL Hidden Violations
**THE PRINCIPLE (the user, 2026-06-17, in CAPS):**
> **"IF ANY PLACE HAS A ERROR LOG IT ALSO NEEDS A RESULT[T]. RESULT[T] PROPOGATES UNTIL IT REACHED A 'DRAIN' POINT WHERE THE ERROR CAN BE HANDLED APPROPRIATELY WITHOUT CRASHING THE APP. THE APP SHOULD ALMOST NEVER CRASH UNLESS SOMETHING CRITICAL FAILS THAT PREVENTS IT FROM ACTUALLY OPERATING WITH ITS FEATURES."**
Phase 11 was REJECTED. The reasons are documented below. Phase 12 follows from the principle.
**WHY PHASE 11 FAILED (3 root causes):**
1. **Heuristic #19 is LAUNDERING.** The "narrow + log = compliant" heuristic that was added in the review pass (sub-track 1) is WRONG under the user's principle. Logging is NOT a drain. A function that catches and logs is still throwing away the error context. The principle says: **the function MUST return `Result[T]`, and the Result must propagate to a real drain point.** Heuristic #19 is removed in Phase 12.1.
2. **The audit-script `visit_Try` walker is BUGGY.** It does NOT recurse into `node.body` (the try body itself). Only `handler.body`, `orelse`, and `finalbody` are recursed. This means nested Trys in the try body are silently dropped from the audit. I verified this against the actual code: `src/api_hooks.py` has 23 actual try/except nodes but the audit only reports 5 findings — a gap of 18 sites. At least 12 of those 18 are silent-fallback violations (`except Exception: payload = {...}` or `except Exception: var = fallback`). The bug is fixed in Phase 12.2.
3. **Tier-2 misclassified sites that don't match the heuristic they claim.** Tier-2's Phase 11 report said `api_hooks.py:451` and `api_hooks.py:824` are "HTTP request handlers; classified `INTERNAL_COMPLIANT` via Heuristic #19". The actual code at L451 is `except (OSError, ValueError) as e: self.send_response(500)` (narrow + HTTP response, NOT a Heuristic #19 log call). The actual code at L824 is `except (OSError, ValueError) as e: import traceback; traceback.print_exc(file=sys.stderr)` (narrow + traceback, NOT a Heuristic #19 log call). Both sites are in scope for Phase 12 migration.
**WHAT IS A DRAIN POINT (the only legitimate exception to the Result[T] requirement):**
A drain point is a function that **HANDLES** the error such that the app does not crash. Per the user's principle:
- The app should almost never crash.
- A drain point is where the error is HANDLED — shown to the user, used to make a decision, or causes intentional app termination.
- Examples of LEGITIMATE drain points:
- `try: ...; except: imgui.text(f"Error: {e}"); return` (user-visible error in GUI)
- `try: ...; except: self.send_response(500); self.wfile.write(json.dumps({"error": ...}))` (HTTP error response)
- `try: ...; except: sys.exit("Fatal: ...")` (intentional app termination with message)
- `try: ...; except: controller.show_error_modal(...)` (UI error modal)
- Examples of NOT drain points (must be Result[T]):
- `try: ...; except: sys.stderr.write(...); pass` (just log)
- `try: ...; except: logger.error(...); return default` (just log + return default)
- `try: ...; except: print(...)` (just print)
- `try: ...; except: pass` (silent)
- `try: ...; except SomeError: var = fallback` (silent fallback)
The audit's Heuristic D (new in Phase 12) recognizes the SMALL set of legitimate drain-point patterns. Everything else must return `Result[T]`.
**PHASE 12 SCOPE:**
- 1 audit-script bug fix (visit_Try recurses into node.body)
- 1 heuristic removal (Heuristic #19) + corresponding test changes
- 1 heuristic addition (Heuristic D: True Drain-Point Recognition) with TDD
- Re-audit of 37-file scope + the 3 refactored baseline files
- Per-file migration of ALL newly-revealed violations to `Result[T]`
- Caller updates for every migrated function
- Test updates for every migration
- Verification: ALL 11 test tiers PASS (not 10; not 9)
The migration will likely surface **20-50+ additional sites** beyond Phase 11's count. The scope is the migration of every such site to `Result[T]`, with the small set of true drain points exempted via Heuristic D.
---
### 12.1 — REMOVE Heuristic #19 (the laundering heuristic)
**WHY:** Heuristic #19 is the "narrow + log = compliant" pattern. The user's principle: **logging is NOT a drain.** A function that catches and logs is throwing away the error context. The convention requires `Result[T]`, not `sys.stderr.write + return default`.
- **WHERE:** `scripts/audit_exception_handling.py` `_try_compliant_pattern` method, around line 582 (the comment "19. Narrow except + log (sys.stderr.write or logging.*) for defer-not-catch or retry-then-give-up")
- **WHAT:** Surgically delete the entire Heuristic #19 `if` block. Lines approximately 582-587 (the comment + the `if` body returning the tuple).
- **HOW:** Use `manual-slop_edit_file` to delete the block. Verify with `py_check_syntax` after.
- **SAFETY:** The block is a single return statement inside a chain of `if` blocks. The delete must preserve the chain's structure.
- **COMMIT:** `revert(scripts): REMOVE Heuristic #19 (narrow+log laundering; logging is NOT a drain)`
- **GIT NOTE:** "Heuristic #19 added in review pass; rejected by user 2026-06-17. Logging is not a drain point. Result[T] must propagate."
**12.1.1 — Update the Heuristic #19 test**
- **WHERE:** `tests/test_audit_exception_handling_heuristics.py` (the test for Heuristic #19)
- **WHAT:** The existing test asserts that narrow + log is `INTERNAL_COMPLIANT`. After 12.1, the same input should be classified as a VIOLATION (`INTERNAL_SILENT_SWALLOW` or `INTERNAL_BROAD_CATCH` or `INTERNAL_OPTIONAL_RETURN`, depending on the body).
- **HOW:** Update the test to assert the NEW expected category. Do NOT delete the test — the test still validates the audit's behavior; the expected category just changes.
- **COMMIT:** Same commit as 12.1, or a follow-up.
---
### 12.2 — FIX the visit_Try audit-script bug (recurse into node.body)
**WHY:** The current `visit_Try` recurses into `handler.body`, `orelse`, and `finalbody` but NOT `node.body` (the try body itself). This causes nested Trys in the try body to be silently dropped. I verified this: `src/api_hooks.py` has 23 actual try/except nodes but the audit only reports 5 findings (gap of 18 sites, 12+ of which are silent-fallback violations).
- **WHERE:** `scripts/audit_exception_handling.py` `ExceptionVisitor.visit_Try` method, around line 848
- **WHAT:** Add `for child in node.body: self.visit(child)` to recurse into the try body. Place it BEFORE the handlers loop (or at the top, so nested Trys are visited first).
- **HOW:** Use `manual-slop_edit_file` to insert the 2 lines. The current code is:
```python
def visit_Try(self, node: ast.Try) -> None:
self._try_stack.append(node)
try:
# bare try/finally (no except) = canonical cleanup pattern
if not node.handlers and node.finalbody:
self._add_finding(
"TRY",
node.lineno,
self._snippet(node),
"INTERNAL_COMPLIANT",
"Compliant: bare try/finally is the canonical cleanup pattern (analog of `goto defer`).",
)
for handler in node.handlers:
category, hint = self._classify_except(handler, node)
...
```
Insert `for child in node.body: self.visit(child)` after the bare try/finally check and before the handlers loop.
- **SAFETY:** The new recursion is additive — it only ADDS findings, never removes them. Existing 5 findings in `api_hooks.py` will still appear; new findings for nested Trys will also appear.
- **VERIFY:** After the fix, run the audit on `src/api_hooks.py` and confirm the count is 23 (or 23 + the raise statements = ~25), not 5.
- **COMMIT:** `fix(scripts): visit_Try recurses into node.body (fix nested-Try audit gap)`
- **GIT NOTE:** "audit bug: visit_Try did not recurse into try body. Nested Trys were silently missed. Example: api_hooks.py has 23 actual try/except nodes but the audit reported only 5. Gap: 18 sites. Fix: add 2 lines to visit_Try."
**12.2.1 — Write a TDD test for the visit_Try fix**
- **WHERE:** `tests/test_audit_exception_handling_bug_fixes.py` (extend the existing file)
- **WHAT:** Write a test that constructs a Python source string with a nested Try (an outer try with a try/except inside the try body) and asserts that the audit finds BOTH the outer and the inner except handlers.
- **HOW:** Use `audit_file(Path(test_file))` after writing the source to a temp file; assert the number of EXCEPT findings equals the expected count.
- **COMMIT:** `test(scripts): TDD for visit_Try recursing into node.body`
---
### 12.3 — ADD Heuristic D (True Drain-Point Recognition) with TDD
**WHY:** The convention allows a small set of LEGITIMATE drain points where the error is HANDLED. Heuristic D recognizes these so the audit doesn't flag them as violations. This is the REPLACEMENT for Heuristic #19.
**Drain-point patterns Heuristic D recognizes (TDD-first; the test suite defines the patterns):**
1. **HTTP error response:** `try: ...; except SomeError as e: self.send_response(<status>); self.wfile.write(<error_json>)` — the catch delivers a user-visible HTTP error response. Pattern: `send_response` or `send_error` call in the except body.
2. **GUI error display:** `try: ...; except SomeError as e: imgui.text(f"Error: {e}"); imgui.pop_style_color()` — the catch displays the error to the user. Pattern: `imgui.text` or `imgui.text_colored` with the error string in the except body.
3. **Intentional app termination:** `try: ...; except SomeError as e: sys.exit(<message>)` or `raise SystemExit(<message>)` — the catch terminates the app with a message. Pattern: `sys.exit` or `raise SystemExit` in the except body.
4. **Telemetry emission:** `try: ...; except SomeError as e: telemetry.emit("error", ...)` — the catch emits a structured error event. Pattern: call to a `telemetry.*` or `audit.*` or `events.emit` method.
5. **Retry with bounded attempts:** `try: ...; except SomeError as e: if attempt < max: retry(); else: raise` — the catch retries with a bounded loop. Pattern: `if attempt < max_retries:` followed by `continue` or `retry()`, then the catch's last line is `raise` or `return error_state`.
- **WHERE:** `scripts/audit_exception_handling.py` `_try_compliant_pattern` method
- **WHAT:** Add Heuristic D's `if` blocks AFTER Heuristic A (Result-returning recovery). Each pattern has its own `if` block with the matching condition and a hint.
- **HOW:** TDD. Write the tests first (12.3.1, 12.3.2, etc.). Then implement the heuristic.
- **COMMIT:** `feat(scripts): Heuristic D (True Drain-Point Recognition) — 5 patterns, TDD`
- **GIT NOTE:** "Heuristic D replaces Heuristic #19. Logging is NOT a drain; only HANDLED errors are. 5 specific patterns: HTTP response, GUI display, app termination, telemetry, retry-with-bounded-attempts. TDD; each pattern has a passing test."
**12.3.1 — TDD test for HTTP error response pattern**
**12.3.2 — TDD test for GUI error display pattern**
**12.3.3 — TDD test for intentional app termination pattern**
**12.3.4 — TDD test for telemetry emission pattern**
**12.3.5 — TDD test for retry-with-bounded-attempts pattern**
---
### 12.4 — Re-run audit; capture post-fix findings
- **WHERE:** Project root
- **WHAT:** Run `uv run python scripts/audit_exception_handling.py --json --src src --include-baseline > docs/reports/PHASE12_AUDIT_POST_FIX_20260617.json`
- **HOW:** Standard audit invocation. Save the JSON to the docs/reports/ directory.
- **VERIFY:** The total violation count is now HIGHER than the pre-Phase-12 count (the bug fix + heuristic removal expose new sites).
- **COMMIT:** `chore(audit): capture post-Phase-12-fix audit (visit_Try + Heuristic #19 removed + Heuristic D added)`
- **GIT NOTE:** "Phase 12 audit capture. Count delta vs pre-Phase-12: +N violations (visit_Try fix); +M violations (Heuristic #19 removed); -K (Heuristic D exempts drain points)."
---
### 12.5 — Triage the post-fix findings; build per-file action list
- **WHERE:** `docs/reports/PHASE12_TRIAGE_20260617.md`
- **WHAT:** Parse the post-fix JSON. For each violation (V or S category), record: file, line, function name, current pattern, target migration (what the Result[T] version looks like). Group by file. Save the triage as a markdown table.
- **HOW:** A small Python script (`scripts/tier2/artifacts/result_migration_small_files_20260617/triage_phase12.py`) reads the JSON, groups by file, and emits markdown. Run the script; check the output.
- **COMMIT:** `docs(report): Phase 12 triage — per-file action list for migration`
- **GIT NOTE:** "Phase 12 triage: N sites to migrate, grouped by file. The migration is broken into sub-batches per file."
---
### 12.6 — Per-file migration to Result[T] (the bulk of Phase 12)
For each file in the Phase 12 triage, do the migration. The pattern is the same as Phase 3-8:
1. Identify the function/method
2. Add `Result[T]` to the return type
3. Add `from src.result_types import Result, ErrorInfo, ErrorKind` (if not present)
4. Change the `except` body to `return Result(data=<default>, errors=[ErrorInfo(kind=ErrorKind.INTERNAL, message=str(e), source=<file>:<func>, original=e)])`
5. Update the function's `return <value>` (success path) to `return Result(data=<value>)`
6. Update callers to check `result.ok` and use `result.data` or `result.errors`
**The triage table from 12.5 lists every file:line. Each file's migration is its own task with its own commit.**
**12.6.1 — `src/api_hooks.py` migration (12+ sites)**
- Sites: L294, L387, L410, L428, L442, L561, L592, L620, L719, L739, L793, L810 (and the L912 inner try that the audit DOES see)
- WHAT: Each `except Exception: var = fallback` becomes `return Result(data=fallback, errors=[ErrorInfo(...)])` in a function that now returns `Result[T]`.
- HOW: For each site, change the enclosing function's signature to `-> Result[T]`, change the except body to return a `Result` with `errors=[ErrorInfo]`, and update the function's success-path returns to wrap in `Result(data=...)`.
- CALLER UPDATES: `_get_app_attr` callers in api_hooks.py and `api_hook_client.py` (the test client); `do_GET` / `do_POST` call sites.
- COMMIT: `refactor(src): api_hooks.py Phase 12 - 12+ sites full Result[T] migration`
- TESTS: 12.8.x
- **KNOWN EXEMPTION:** L451, L824, L914 are HTTP response patterns. Heuristic D (HTTP error response) exempts them. Document in the per-site report.
**12.6.2 — `src/warmup.py` Phase 12 verification (5 sites already migrated in Phase 11; verify Heuristic A recognizes them)**
- Sites: L139, L215, L249, L276, L300, L185
- WHAT: After Heuristic #19 is removed and Heuristic D is added, verify the audit still classifies these as INTERNAL_COMPLIANT (via Heuristic A — they return `Result(data=..., errors=[...])`).
- HOW: Re-run the audit. The 5 sites should be INTERNAL_COMPLIANT via Heuristic A. The L185 io_pool callback (indirect return) is a known audit limitation (the audit's Heuristic A only matches direct `return Result(...)`; L185 returns `self._record_failure(...)` which returns Result). Document the limitation in the report; this is acceptable (the convention is followed; the audit has a limitation).
- COMMIT: `chore(audit): verify warmup.py Phase 12 — Heuristic A recognizes the 5 sites`
- GIT NOTE: "Phase 12 verification: warmup.py sites still INTERNAL_COMPLIANT via Heuristic A. L185 indirect return is a known audit limitation; convention is followed."
**12.6.3 — `src/startup_profiler.py` Phase 12 verification**
- Sites: L17 (_log_phase_output), L49 (phase())
- WHAT: Verify the helper extraction is still recognized as INTERNAL_COMPLIANT via Heuristic A. The context manager exception is documented.
- HOW: Re-run the audit.
- COMMIT: `chore(audit): verify startup_profiler.py Phase 12`
**12.6.4 — `src/file_cache.py` Phase 12 verification**
- Sites: L48 (_get_mtime_safe)
- WHAT: Verify the helper extraction is INTERNAL_COMPLIANT via Heuristic A.
- HOW: Re-run the audit.
- COMMIT: `chore(audit): verify file_cache.py Phase 12`
**12.6.5 — `src/orchestrator_pm.py` Phase 12 verification (already Result[str])**
- Sites: L11 (function signature), L33, L42
- WHAT: Verify the function is still classified as BOUNDARY_CONVERSION (per-item ErrorInfo pattern).
- HOW: Re-run the audit.
- COMMIT: `chore(audit): verify orchestrator_pm.py Phase 12`
**12.6.6 — `src/project_manager.py` Phase 12 verification (already BOUNDARY_CONVERSION)**
- Sites: L372, L384, L399
- WHAT: Verify the per-item ErrorInfo pattern is still BOUNDARY_CONVERSION.
- HOW: Re-run the audit.
- COMMIT: `chore(audit): verify project_manager.py Phase 12`
**12.6.7 — `src/log_registry.py` Phase 12 migration (4 sites)**
- Sites: L97, L135, L250, L294
- WHAT:
- L97 (`except Exception as e: print(f'Error loading registry from...')`): Heuristic D does NOT match (print is not a drain). Migrate to `Result[T]`.
- L135: already returns `Result(data=False, errors=[ErrorInfo(...)])`. Verify Heuristic A recognizes it.
- L250: Heuristic #19 used to match. Now Heuristic #19 is removed. The site is `except OSError as e: sys.stderr.write(...)`. Per the principle, logging is NOT a drain. **Migrate to `Result[T]`.** The except body becomes `return Result(data=default, errors=[ErrorInfo(kind=ErrorKind.INTERNAL, message=str(e), source=..., original=e)])`. The function signature changes to `-> Result[T]`.
- L294: `except ValueError: start_time = None` — silent fallback. Migrate to `Result[T]`.
- HOW: For L250, change the function signature, change the except body, update callers. For L97 and L294, similar.
- CALLER UPDATES: scan with `py_find_usages`.
- COMMIT: `refactor(src): log_registry.py Phase 12 - 4 sites full Result[T] migration`
- TESTS: 12.8.x
**12.6.8 — `src/models.py` Phase 12 migration (3 sites)**
- Sites: L452, L457, L508
- WHAT: All three are `except ValueError: var = None` or `except ValueError as e: sys.stderr.write(...)`. Per the principle, none of these are drain points. Migrate all three to `Result[T]`.
- HOW: For each, change the enclosing function's signature, change the except body, update callers.
- CALLER UPDATES: `TrackState.from_dict` callers (lots; use `py_find_usages`).
- COMMIT: `refactor(src): models.py Phase 12 - 3 sites full Result[T] migration`
- TESTS: 12.8.x
**12.6.9 — `src/multi_agent_conductor.py` Phase 12 migration (4 sites)**
- Sites: L234, L236, L317, L468, L636
- WHAT: All five are `except SpecificError: print(...)` or `except SpecificError: sys.stderr.write(...)`. Per the principle, none are drain points. Migrate all to `Result[T]`.
- HOW: For each, change the enclosing function's signature, change the except body, update callers.
- CALLER UPDATES: scan with `py_find_usages`. The WorkerPool and conductor engine are the main callers.
- COMMIT: `refactor(src): multi_agent_conductor.py Phase 12 - 4 sites full Result[T] migration`
- TESTS: 12.8.x
**12.6.10 — `src/theme_2.py` Phase 12 migration (1 site)**
- Sites: L282
- WHAT: `except (ImportError, AttributeError) as e: sys.stderr.write(...)`. Migrate to `Result[T]`.
- HOW: Change the enclosing function's signature, change the except body, update callers.
- CALLER UPDATES: `apply()` callers (theme switching in gui_2.py).
- COMMIT: `refactor(src): theme_2.py Phase 12 - 1 site full Result[T] migration`
- TESTS: 12.8.x
**12.6.11 — `src/shell_runner.py` Phase 12 migration (Tier 4 QA error interception)**
- Sites: 2-3 sites per the audit
- WHAT: Migrate to `Result[T]` (Tier 4 QA may have legitimate drain points — verify with Heuristic D).
- HOW: Same pattern.
- CALLER UPDATES: shell_runner.py callers in `mcp_client.py` (the tool execution path).
- COMMIT: `refactor(src): shell_runner.py Phase 12 - N sites full Result[T] migration`
- TESTS: 12.8.x
**12.6.12 — `src/session_logger.py` Phase 12 migration (4 sites)**
- Sites: per the audit (likely 4 SILENT_SWALLOW sites from the audit summary)
- WHAT: Migrate to `Result[T]`.
- HOW: Same pattern.
- CALLER UPDATES: session logger is called from many places.
- COMMIT: `refactor(src): session_logger.py Phase 12 - 4 sites full Result[T] migration`
- TESTS: 12.8.x
**12.6.13 — Other SMALL files (triage-driven)**
- For every file in the Phase 12 triage, do the migration. The triage (12.5) lists every site.
- Each file gets its own commit.
---
### 12.7 — Update callers of all migrated functions
- **WHERE:** Every caller of the migrated functions in 12.6.x
- **WHAT:** For each caller, change the call from `result = func()` + `if result:` to `result = func()` + `if not result.ok: ...` + `use(result.data)`. The `data` field carries the value; the `errors` field carries the ErrorInfo.
- **HOW:** For each migration in 12.6.x, use `manual-slop_py_find_usages` to find all callers. Update each caller to check `result.ok` and use `result.data` or `result.errors`.
- **SAFETY:** The `data` field's type matches the original function's return type. The `errors` field is a `list[ErrorInfo]`. If the caller previously checked the return value for None, check `result.ok` instead.
- **COMMIT:** Bundled with the per-file migration in 12.6.x.
---
### 12.8 — Update tests for every migration
- **WHERE:** `tests/` directory
- **WHAT:** For each migration, update the test(s) to handle the new `Result[T]` return type. Tests that assert on the old return value now assert on `result.data` (or `result.ok` and `result.errors`).
- **HOW:** Use `manual-slop_py_find_usages` on the migrated function. For each test, update the assertions.
- **TESTS TO ADD:** For each migration, add at least 1 test for the error path:
```python
def test_<func>_error_path(self):
result = <func>(<bad_input>)
assert not result.ok
assert result.errors[0].category == ErrorKind.INTERNAL
assert result.errors[0].message # non-empty
```
- **COMMIT:** Bundled with the per-file migration in 12.6.x.
---
### 12.9 — Run all 11 test tiers; verify 11/11 PASS
- **WHERE:** Project root
- **WHAT:** Run `uv run python scripts/run_tests_batched.py` and confirm all 11 tiers PASS.
- **HOW:** Standard batched runner. The 11 tiers are: 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.
- **VERIFY:** All 11 PASS. If any tier fails, the migration is incomplete; fix the regression before marking Phase 12 complete.
- **COMMIT:** (no commit — just verification)
- **TEST_COUNT_CLAIM:** The number of test tiers is 11, not 10. This is the FOURTH time this is being emphasized. If the report says 10, it is wrong.
---
### 12.10 — Update the per-site report and the track completion report
- **WHERE:** `docs/reports/RESULT_MIGRATION_SMALL_FILES_20260617.md` (per-site) + `docs/reports/TRACK_COMPLETION_result_migration_small_files_20260617.md` (completion)
- **WHAT:** Add a "Phase 12" section that:
- REJECTS Phase 11 (Phase 11 was REJECTED because it left Heuristic #19 in place; the user's principle says logging is NOT a drain; also Phase 11 missed the visit_Try bug)
- Documents Phase 12: Heuristic #19 removed, visit_Try fixed, Heuristic D added, N new sites migrated
- Per-site decisions: which sites were drained (HTTP response, GUI display, app termination) vs Result-typed
- Test pass count: ALL 11 TIERS PASS
- **COMMIT:** `docs(reports): Phase 12 addendum — Heuristic #19 removed; visit_Try fixed; Heuristic D added; N sites migrated`
- **GIT NOTE:** "Phase 12 addendum. The 4th redo of the small-files Result[T] migration. The user's principle: Result[T] propagates until a drain point. Logging is not a drain. ALL 11 test tiers PASS."
---
### 12.11 — Mark Phase 12 complete
- **WHERE:** `conductor/tracks/result_migration_small_files_20260617/state.toml` + `metadata.json` + `conductor/tracks.md`
- **WHAT:**
- state.toml: mark all Phase 12 tasks completed with commit SHAs; update `status: active → completed`; `current_phase: 12 → "complete"`
- metadata.json: add Phase 12 outcomes (heuristics_removed=1, heuristics_added=1, audit_bug_fixes=1, sites_migrated_phase_12=N, total_sites_migrated=49+N, total_sites_compliant=...)
- tracks.md: update the sub-track 2 row to reflect Phase 12 completion
- **COMMIT:** `conductor(track): mark result_migration_small_files_20260617 Phase 12 complete (Heuristic #19 removed; visit_Try fixed; Heuristic D added; N sites Result-typed; 11/11 test tiers PASS)`
- **GIT NOTE:** "Phase 12 is the ACTUAL completion. Phase 10 was REJECTED. Phase 11 was REJECTED. Phase 12 follows the user's principle: Result[T] propagates to drain points. Heuristic #19 was laundering. visit_Try was buggy. Both fixed."
---
### 12.12 — Update the umbrella spec
- **WHERE:** `conductor/tracks/result_migration_20260616/spec.md`
- **WHAT:** Update the post-sub-track-2 callout:
- Replace "Phase 11 in progress" with "Phase 12 COMPLETE; the user's principle: Result[T] propagates to drain points. Heuristic #19 removed; visit_Try fixed; Heuristic D added; N sites Result-typed; 11/11 test tiers PASS."
- Add a "Phase 12 Update" callout with the principle and the per-site counts.
- **COMMIT:** `docs(track): update umbrella with sub-track 2 Phase 12 complete (REAL completion; drain-point principle)`
- **GIT NOTE:** "Phase 12 is the actual completion. The drain-point principle. 11/11 test tiers PASS."
---
### 12.13 — Conductor - User Manual Verification
Per workflow.md: User manually verifies the per-file migrations, the per-file Result[T] returns, the test pass count, and the report's claims about which sites are drained vs Result-typed. The user confirms Phase 12 is complete (or identifies remaining issues).
---
## Risks at the Plan Level
| Risk | Mitigation |
@@ -842,26 +1187,35 @@ For each of the 21 migrated sites, update all callers to check `result.ok` and u
| **Phase 11 R2 (NEW):** Tier-2 may try to use "context manager" or "user callback" as excuses for not doing Result migration | `StartupProfiler.phase()` is NOT a context manager. The user callbacks in `WarmupManager` are `Callable[[dict], None]` and stay as-is; the MANAGER's INTERNAL methods are NOT user code. **Look at `src/hot_reloader.py`** for the pattern tier-2 used correctly. Apply the same pattern to `warmup.py`. |
| **Phase 11 R3 (NEW):** Tier-2 may miscount the test tiers again (claiming 10 instead of 11) | The plan EXPLICITLY says "all 11 test tiers PASS" in Task 11.7.2. The 11th tier is `tier-1-unit-comms`. The report MUST say 11, not 10. |
| **Phase 11 R4 (NEW):** Tier-2 may claim the work is done without doing the FULL Result migration for all 21 sites | Each of the 21 sites has a specific task (11.3.1.1 - 11.3.10.1). The plan EXPLICITLY lists each site. The "G4 met" claim requires the audit to show 0 migration-target sites WITHOUT the 5 LAUNDERING HEURISTICS in place. |
| **Phase 12 R1 (NEW):** Tier-2 may keep the laundering-heuristic mindset and try to keep Heuristic #19 | Phase 12.1 EXPLICITLY REMOVES Heuristic #19. The user's principle: logging is NOT a drain. Result[T] propagates to drain points. The plan EXPLICITLY states this. |
| **Phase 12 R2 (NEW):** Tier-2 may not fix the visit_Try audit bug, leaving nested Trys silently missed | Phase 12.2 EXPLICITLY FIXES the bug with a 2-line change. The fix is verified by re-running the audit on `src/api_hooks.py` and confirming the count is 23 (not 5). The TDD test (12.2.1) is non-bypassable. |
| **Phase 12 R3 (NEW):** Tier-2 may not add Heuristic D (True Drain-Point Recognition) and end up flagging all HTTP error responses / GUI error displays as violations | Phase 12.3 EXPLICITLY ADDS Heuristic D with 5 patterns (HTTP error response, GUI error display, app termination, telemetry emission, retry-with-bounded-attempts). TDD-first; each pattern has a passing test. The small set of legitimate drain points is recognized. |
| **Phase 12 R4 (NEW):** Tier-2 may claim Phase 12 is done but leave sites un-migrated | The per-file migration (12.6.1-12.6.13) lists every file:line. The triage (12.5) is the master list. Every site in the triage MUST be migrated or classified as a drain point (via Heuristic D). The audit's post-Phase-12 count must reflect the new state. |
| **Phase 12 R5 (NEW):** Tier-2 may miscount test tiers (claiming 10 instead of 11) AGAIN | The plan EXPLICITLY says "ALL 11 TIERS PASS" in Task 12.9. The 11th tier is `tier-1-unit-comms`. This is the FOURTH time this is being emphasized. |
| **Phase 12 R6 (NEW):** Tier-2 may claim "Phase 12 complete" without running the test suite | Task 12.9 is the test verification. The completion commit (12.11) requires all 11 test tiers passing. The user verifies via 12.13 (Conductor - User Manual Verification). |
| **Phase 12 R7 (NEW):** The migration may break behavior in a way the test suite doesn't catch | Task 12.9 catches regressions. For non-tier-tested files, manual smoke-testing is added (sub-task of 12.6.x). |
---
## Verification Snapshot (capture in the report)
After Phase 11, capture in `docs/reports/RESULT_MIGRATION_SMALL_FILES_20260617.md` and `docs/reports/TRACK_COMPLETION_result_migration_small_files_20260617.md`:
After Phase 12, capture in `docs/reports/RESULT_MIGRATION_SMALL_FILES_20260617.md` and `docs/reports/TRACK_COMPLETION_result_migration_small_files_20260617.md`:
- **The user's principle (2026-06-17, in CAPS):** Result[T] propagates until it reaches a drain point. Logging is NOT a drain. The app should almost never crash unless something critical fails.
- Phase 10 REJECTED: 21 sites slimed; 5 LAUNDERING HEURISTICS (#22-#26) added.
- Phase 11 REJECTED: Heuristic #19 (narrow+log = compliant) was laundering; visit_Try audit bug not fixed; ~18+ nested-Try sites silently missed; tier-2 misclassified 2 sites.
- Phase 12 (this phase): Heuristic #19 REMOVED; visit_Try FIXED; Heuristic D ADDED (5 drain-point patterns); N new sites Result-typed.
- 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-1: 3 audit-script bugs fixed (visit_Try walker, render_json filter, render_json truncation)
- Audit post-Phase-2: 4 UNCLEAR sites classified (2 compliant + 2 migration-target)
- Audit post-Phase-9: 49/76 sites migrated; 27 SILENT_SWALLOW remain; 14 new UNCLEAR sites
- Audit post-Phase-10 (REJECTED): 5 sites full Result + 21 sites narrowed+log; 5 LAUNDERING HEURISTICS (#22-#26) added
- Audit post-Phase-11: 76/76 sites FULL Result[T] migration; 0 SILENT_SWALLOW; 0 UNCLEAR; 0 laundering heuristics; 0 migration-target in 37-file scope
- 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 from Phase 1 + Heuristic A from Phase 11)
- **Test pass count: ALL 11 TIERS PASS** (not 10; the 11th tier is `tier-1-unit-comms`; tier-2 had been miscounting); new tests added (4 for Phase 1 + N for Phase 11)
- Phase 11 REJECTED Phase 10's sliming of 21 sites
- Phase 11 REVERTED the 5 LAUNDERING HEURISTICS (#22-#26)
- Phase 11 ADDED Heuristic A (Result-returning recovery in non-*_result function)
- Phase 11 migrated all 21 slimed sites to FULL Result[T]
- Audit post-Phase-11 (REJECTED): 5 LAUNDERING HEURISTICS REVERTED; 5 sites full Result + 2 helper extracts; 14 sites claimed as "already compliant" (6 legitimately, 2 misclassified, 6+ silently missed by visit_Try bug)
- Audit post-Phase-12: 0 SILENT_SWALLOW; 0 UNCLEAR; 0 laundering heuristics; 0 migration-target; the small set of true drain points (HTTP responses, GUI error displays, app terminations, telemetry emissions, retry-with-bounded-attempts) is correctly recognized by Heuristic D
- Per-file migration summary (76 + N new sites → 0 migration-target; per-file counts; per-site function signatures + ErrorInfo fields)
- Per-site decisions for the 4 UNCLEAR sites (Phase 2)
- Per-site drain-point decisions (Phase 12.6.x) — for each site, state whether it's a drain point (Heuristic D) or a Result-typed function
- Audit-script changes: 3 from Phase 1 + visit_Try fix (Phase 12.2) + Heuristic #19 removal (Phase 12.1) + Heuristic D (Phase 12.3) + Heuristic A (Phase 11.2)
- **Test pass count: ALL 11 TIERS PASS** (not 10; the 11th tier is `tier-1-unit-comms`; tier-2 had been miscounting in 3 prior phases); new tests added (4 for Phase 1 + 2 for Heuristic A + 5 for Heuristic D + N for the migrations)
- The io_pool callback sites (`warmup.py:139/215/249`) thread the Result through the completion handler (same pattern as `src/hot_reloader.py`)
- `startup_profiler.py:40` was MIGRATED, not skipped (it is NOT a context manager)
- `startup_profiler.py:40` was MIGRATED via the `_log_phase_output` helper (phase() IS `@contextmanager`; the helper extraction is the partial-migration workaround; tier-2's original claim that phase() is "not a context manager" was wrong, and the plan's claim that "phase() is not a context manager" was also wrong — phase() IS `@contextmanager`; the helper extraction is the correct workaround)
@@ -3,9 +3,9 @@
[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" # 0 = pre-Phase 1; 1..N = in Phase N; "complete" if all phases done
name = "Result Migration Sub-Track 2 (Small Files + Audit-Script Bug Fixes + Result[T] propagation to drain points)"
status = "active"
current_phase = 12 # 0 = pre-Phase 1; 1..N = in Phase N; "complete" if all phases done
last_updated = "2026-06-17"
[parent]
@@ -32,7 +32,8 @@ phase_7 = { status = "completed", checkpointsha = "a5b40bcf", name = "Migrate Ph
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 = "completed", checkpointsha = "48fb9577", name = "REJECTED Phase 10 (sliming 21 sites via laundering heuristics)" }
phase_11 = { status = "completed", checkpointsha = "6c66c03e", name = "ACTUAL Full Result[T] migration (REJECT Phase 10; revert 5 laundering heuristics; redo 21 sites)" }
phase_11 = { status = "completed", checkpointsha = "6c66c03e", name = "REJECTED Phase 11 (Heuristic #19 left in place; visit_Try audit bug not fixed; tier-2 misclassified 2 sites; ~18+ nested-Try sites silently missed)" }
phase_12 = { status = "in_progress", checkpointsha = "", name = "Result[T] propagation; remove Heuristic #19; fix visit_Try; add Heuristic D (drain-point recognition); migrate ALL hidden violations" }
[tasks]
# Phase 1: Audit-Script Bug Fixes
@@ -171,6 +172,38 @@ t11_7_3 = { status = "pending", commit_sha = "", description = "Update track com
t11_8_1 = { status = "pending", commit_sha = "", description = "Update state.toml + metadata.json + tracks.md to mark Phase 11 complete" }
t11_8_2 = { status = "pending", commit_sha = "", description = "Update umbrella spec: Phase 11 complete; FULL Result[T] migration for 76 sites; G4 met WITHOUT laundering heuristics" }
# Phase 12: Result[T] propagation; remove Heuristic #19; fix visit_Try; add Heuristic D; migrate ALL hidden violations
# Per user directive 2026-06-17: "IF ANY PLACE HAS A ERROR LOG IT ALSO NEEDS A RESULT[T]. RESULT[T] PROPOGATES UNTIL IT REACHED A DRAIN POINT WHERE THE ERROR CAN BE HANDLED APPROPRIATELY WITHOUT CRASHING THE APP."
t12_1_1 = { status = "pending", commit_sha = "", description = "REMOVE Heuristic #19 from scripts/audit_exception_handling.py (narrow+log laundering; logging is NOT a drain)" }
t12_1_2 = { status = "pending", commit_sha = "", description = "Update the Heuristic #19 test in tests/test_audit_exception_handling_heuristics.py (same input, NEW expected category: violation)" }
t12_2_1 = { status = "pending", commit_sha = "", description = "FIX visit_Try in scripts/audit_exception_handling.py: add 'for child in node.body: self.visit(child)' (recurse into try body)" }
t12_2_2 = { status = "pending", commit_sha = "", description = "TDD test for visit_Try fix: nested Try in try body must be found by audit (tests/test_audit_exception_handling_bug_fixes.py)" }
t12_3_1 = { status = "pending", commit_sha = "", description = "Heuristic D TDD: 5 patterns (HTTP error response, GUI error display, app termination, telemetry emission, retry-with-bounded-attempts)" }
t12_3_2 = { status = "pending", commit_sha = "", description = "Heuristic D implementation: 5 if blocks in _try_compliant_pattern, each with a passing test" }
t12_4_1 = { status = "pending", commit_sha = "", description = "Re-run audit; capture post-Phase-12-fix JSON to docs/reports/PHASE12_AUDIT_POST_FIX_20260617.json" }
t12_5_1 = { status = "pending", commit_sha = "", description = "Triage post-fix findings: per-file action list with file:line + target migration; save to docs/reports/PHASE12_TRIAGE_20260617.md" }
t12_6_1 = { status = "pending", commit_sha = "", description = "Migrate src/api_hooks.py: 12+ silent-fallback sites to full Result[T] (L294, L387, L410, L428, L442, L561, L592, L620, L719, L739, L793, L810, L912); exempt L451, L824, L914 as HTTP error responses (Heuristic D)" }
t12_6_2 = { status = "pending", commit_sha = "", description = "Verify src/warmup.py Phase 12: 5 sites still INTERNAL_COMPLIANT via Heuristic A; L185 indirect return is a known audit limitation" }
t12_6_3 = { status = "pending", commit_sha = "", description = "Verify src/startup_profiler.py Phase 12: _log_phase_output is INTERNAL_COMPLIANT via Heuristic A; phase() context manager is a known partial-migration" }
t12_6_4 = { status = "pending", commit_sha = "", description = "Verify src/file_cache.py Phase 12: _get_mtime_safe is INTERNAL_COMPLIANT via Heuristic A" }
t12_6_5 = { status = "pending", commit_sha = "", description = "Verify src/orchestrator_pm.py Phase 12: get_track_history_summary is still BOUNDARY_CONVERSION" }
t12_6_6 = { status = "pending", commit_sha = "", description = "Verify src/project_manager.py Phase 12: per-item ErrorInfo is still BOUNDARY_CONVERSION" }
t12_6_7 = { status = "pending", commit_sha = "", description = "Migrate src/log_registry.py: 4 sites (L97, L135, L250, L294) to full Result[T] (L250 was Heuristic #19 laundering; logging is not a drain)" }
t12_6_8 = { status = "pending", commit_sha = "", description = "Migrate src/models.py: 3 sites (L452, L457, L508) to full Result[T] (L508 was Heuristic #19 laundering)" }
t12_6_9 = { status = "pending", commit_sha = "", description = "Migrate src/multi_agent_conductor.py: 4 sites (L234, L236, L317, L468, L636) to full Result[T] (most were Heuristic #19 laundering)" }
t12_6_10 = { status = "pending", commit_sha = "", description = "Migrate src/theme_2.py: 1 site (L282) to full Result[T] (was Heuristic #19 laundering)" }
t12_6_11 = { status = "pending", commit_sha = "", description = "Migrate src/shell_runner.py: per the audit (likely 2-3 sites) to full Result[T]" }
t12_6_12 = { status = "pending", commit_sha = "", description = "Migrate src/session_logger.py: 4 sites per the audit to full Result[T]" }
t12_6_13 = { status = "pending", commit_sha = "", description = "Migrate any other SMALL files surfaced by the Phase 12 triage (per docs/reports/PHASE12_TRIAGE_20260617.md)" }
t12_7_1 = { status = "pending", commit_sha = "", description = "Update callers of all migrated functions (use manual-slop_py_find_usages to find each caller; check result.ok and use result.data)" }
t12_8_1 = { status = "pending", commit_sha = "", description = "Update tests for every migration: existing tests assert on result.data (or result.ok/result.errors); add 1+ error-path test per migration" }
t12_9_1 = { status = "pending", commit_sha = "", description = "Run all 11 test tiers via uv run python scripts/run_tests_batched.py; confirm 11/11 PASS (the 11th tier is tier-1-unit-comms; the test count is 11, NOT 10)" }
t12_10_1 = { status = "pending", commit_sha = "", description = "Update docs/reports/RESULT_MIGRATION_SMALL_FILES_20260617.md: Phase 12 addendum (REJECT Phase 11; Heuristic #19 removed; visit_Try fixed; Heuristic D added; N sites migrated; 11/11 tiers PASS)" }
t12_10_2 = { status = "pending", commit_sha = "", description = "Update docs/reports/TRACK_COMPLETION_result_migration_small_files_20260617.md: Phase 12 addendum" }
t12_11_1 = { status = "pending", commit_sha = "", description = "Mark Phase 12 complete: state.toml current_phase=12→complete; metadata.json outcomes; tracks.md sub-track 2 row" }
t12_12_1 = { status = "pending", commit_sha = "", description = "Update umbrella spec.md: Phase 12 complete; the user's principle (drain-point); Heuristic #19 removed; visit_Try fixed; Heuristic D added; 11/11 tiers PASS" }
t12_13_1 = { status = "pending", commit_sha = "", description = "Conductor - User Manual Verification: user confirms Phase 12 is complete" }
[verification]
phase_1_audit_fixes_complete = true
phase_2_unclear_classification_complete = true
@@ -181,24 +214,31 @@ 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 = true # REJECTED; slimed 21 sites via laundering heuristics
phase_11_actual_result_migration_complete = true
phase_10_result_migration_complete = false # REJECTED; slimed 21 sites via laundering heuristics
phase_11_actual_result_migration_complete = false # REJECTED; Heuristic #19 left in place; visit_Try bug not fixed; tier-2 misclassified 2 sites
phase_12_drain_point_propagation_complete = false # in progress
report_exists = true
umbrella_spec_updated = true
audit_post_migration_zero_migration_target = true # TRUE — 5 laundering heuristics REVERTED in Phase 11; 21 sites migrated or skipped with documented exemption
test_pass_count_unchanged = true
metadata_json_status_completed = true
silent_swallow_sites_migrated_to_result = 26 # 21 sites slimed in Phase 10; 5 sites fully migrated; 21 sites redone in Phase 11 (5 full Result + 4 helper extracts + 12 already compliant with documentation)
audit_post_migration_zero_migration_target = false # Phase 12 in progress; visit_Try fix + Heuristic #19 removal will reveal more sites
test_pass_count_unchanged = false # Phase 12 may require test updates; full re-verification with 11/11 tiers
metadata_json_status_completed = false
silent_swallow_sites_migrated_to_result = 5 # Phase 11 migrated 5 sites in warmup.py
new_unclear_sites_reclassified = 17
new_audit_heuristics_added_phase_10 = 5 # REJECTED — LAUNDERING heuristics; REVERTED in Phase 11; REVERTED in Phase 11 (commit 37872544)
heuristic_a_added_phase_11 = true # LEGITIMATE heuristic added (commit 3c839c91)
new_audit_heuristics_added_phase_10 = 5 # REJECTED — LAUNDERING heuristics; REVERTED in Phase 11; REMOVED PERMANENTLY in Phase 12
heuristic_a_added_phase_11 = true # LEGITIMATE heuristic added (commit 3c839c91); RETAINS in Phase 12
io_pool_callback_sites_threaded_result = 4
phase_11_audit_heuristics_reverted = 5 # 5 LAUNDERING heuristics (#22-#26) REVERTED
phase_11_audit_heuristics_reverted = 5 # 5 LAUNDERING heuristics (#22-#26) REVERTED in Phase 11
phase_11_sites_migrated_to_full_result = 5 # warmup.py: 5 sites full Result (on_complete, _record_success, _record_failure, _log_canary, _log_summary)
phase_11_sites_helpers_extracted = 2 # startup_profiler._log_phase_output + file_cache._get_mtime_safe
phase_11_sites_already_compliant = 14 # documented as exempt from Result migration
phase_11_sites_already_compliant = 14 # REJECTED — 6 legitimately compliant + 2 misclassified + 6+ silently missed by visit_Try bug
phase_11_heuristic_a_added = true
phase_11_result_migration_complete = true
phase_11_result_migration_complete = false # REJECTED; Phase 12 supersedes
phase_12_visit_try_bug_fixed = false # in progress (Task 12.2.1)
phase_12_heuristic_19_removed = false # in progress (Task 12.1.1)
phase_12_heuristic_d_added = false # in progress (Task 12.3.x)
phase_12_sites_migrated_to_full_result = 0 # tracked as migrations complete
phase_12_test_count_corrected_to_11 = true # The test count is 11, NOT 10. The 11th tier is tier-1-unit-comms.
phase_12_principle_drain_point_propagation = true # The user's principle: Result[T] propagates until a drain point. Logging is NOT a drain.
[scope_metrics]
files_target = 37