{
  "id": "result_migration_app_controller_20260618",
  "name": "Result Migration - Sub-Track 3 (App Controller)",
  "date": "2026-06-18",
  "phase_6_added": "2026-06-18",
  "type": "refactor",
  "priority": "A",
  "spec": "conductor/tracks/result_migration_app_controller_20260618/spec.md",
  "plan": "conductor/tracks/result_migration_app_controller_20260618/plan.md",
  "status": "active",
  "umbrella": "result_migration_20260616",
  "sub_track_index": 3,
  "blocked_by": {
    "result_migration_small_files_20260617": "shipped 2026-06-17"
  },
  "blocks": {},
  "scope": {
    "new_files": [
      "tests/test_app_controller_result.py",
      "docs/reports/TRACK_COMPLETION_result_migration_app_controller_20260618.md"
    ],
    "modified_files": [
      "src/app_controller.py",
      "tests/test_app_controller_offloading.py",
      "tests/test_audit_exception_handling_heuristics.py",
      "conductor/tracks.md",
      "conductor/tracks/result_migration_app_controller_20260618/state.toml",
      "conductor/tracks/result_migration_app_controller_20260618/metadata.json",
      "conductor/tracks/result_migration_app_controller_20260618/plan.md",
      "conductor/tracks/result_migration_app_controller_20260618/spec.md",
      "conductor/tracks/result_migration_20260616/spec.md",
      "scripts/audit_exception_handling.py",
      "tests/test_audit_heuristics.py"
    ],
    "deleted_files": []
  },
  "verification_criteria": [
    "src/app_controller.py has zero INTERNAL_BROAD_CATCH sites (32 migrated in Phase 2)",
    "src/app_controller.py has zero INTERNAL_SILENT_SWALLOW sites (30 properly migrated in Phase 6 with Result[T] propagation; no logging.debug anti-pattern per error_handling.md:530)",
    "src/app_controller.py has zero INTERNAL_RETHROW sites (4 classified in Phase 4 as legitimate Pattern 1/3; stay as-is)",
    "src/app_controller.py has zero INTERNAL_OPTIONAL_RETURN sites (1 migrated to Result[float] in Phase 4)",
    "src/app_controller.py preserves 15 BOUNDARY_FASTAPI sites (unchanged, per styleguide Boundary Types section)",
    "src/app_controller.py preserves 2 BOUNDARY_SDK sites (unchanged, per styleguide Boundary Types section)",
    "src/app_controller.py preserves 1 INTERNAL_PROGRAMMER_RAISE site (unchanged, per Fail Early pattern)",
    "tests/test_app_controller_result.py exists with 5+ tests, all pass (extended with 27 Phase 6 site tests)",
    "tests/test_app_controller_offloading.py has 2 unwrap-path tests, all pass",
    "tests/test_app_controller_sigint.py has 2 sigint-handler tests, all pass (updated _FakeController for Phase 6 helpers)",
    "tests/test_tool_presets_execution::test_tool_ask_approval passes (Regression 1 fixed in Phase 1)",
    "tests/test_extended_sims::test_execution_sim_live passes (Regression 2 fixed in Phase 1 + verified environmentally dependent)",
    "uv run python scripts/audit_exception_handling.py per-file count for src/app_controller.py: 0 INTERNAL_SILENT_SWALLOW (Phase 6 hard gate)",
    "uv run python scripts/audit_exception_handling.py --json shows 0 sites in INTERNAL_SILENT_SWALLOW category for app_controller.py",
    "Tier 1 batched suite (253 tests) ALL 5 batches PASS",
    "Tier 2 batched suite (35 tests) ALL 5 batches PASS",
    "Tier 3 batched suite (56 tests): 1 known environmental live_gui flake (test_context_sim_live - 2s eventual consistency timeout under load); not caused by Phase 6 migration",
    "Every migrated except body contains Result(data=..., errors=[ErrorInfo(original=e)]) (verified by grep - no debug-log-only except bodies)",
    "docs/reports/TRACK_COMPLETION_result_migration_app_controller_20260618.md rewritten with full Phase 1-6 coverage; the misleading '8 silent swallow migrated' claim from Phase 5 is superseded",
    "src/app_controller.py has 0 strict-violation sites after Phase 7 (L242, L256, L5064, L5093 migrated to Result[T] or no longer over-classified by audit heuristic)",
    "scripts/audit_exception_handling.py _is_api_handler heuristic tightened: BOUNDARY_FASTAPI only applies when except body raises HTTPException or returns Result",
    "tests/test_audit_heuristics.py has 3 unit tests verifying the tightened heuristic does not regress the 15 existing BOUNDARY_FASTAPI sites"
  ],
  "regressions_and_pre_existing_failures": [
    {
      "name": "test_tool_presets_execution::test_tool_ask_approval",
      "cause": "session_logger.log_tool_call was partially migrated to return Result but the call site in _offload_entry_payload was not updated",
      "fix_phase": 1,
      "fix_task": 1.3
    },
    {
      "name": "test_extended_sims::test_execution_sim_live",
      "cause": "downstream effect of test_tool_ask_approval failure; the live GUI runs the same _offload_entry_payload path",
      "fix_phase": 1,
      "fix_task": 1.3
    }
  ],
  "pre_existing_failures_remaining": [],
  "deferred_to_followup_tracks": [
    {
      "title": "Sub-track 4: result_migration_gui_2",
      "description": "Migrate src/gui_2.py (260KB) to the Result convention. The umbrella's sub-track 4 plan (line 276 of conductor/tracks/result_migration_20260616/spec.md) covers the 55 sites in gui_2.py.",
      "track_status": "planned (per umbrella)"
    },
    {
      "title": "Sub-track 5: result_migration_baseline_cleanup",
      "description": "Close the remaining 77 violations in the 3 refactored baseline files (mcp_client.py, ai_client.py, rag_engine.py). Per umbrella sub-track 5 (line 296-309 of result_migration_20260616/spec.md).",
      "track_status": "planned (per umbrella)"
    }
  ],
  "estimated_effort": {
    "method": "scope (per workflow.md Tier 1 Track Initialization Rules). NO day estimates.",
    "scope": "1 source file (src/app_controller.py) + 1 audit script (scripts/audit_exception_handling.py) modified across 7 phases; 49 migration sites (45 in Phases 1-5 + 4 strict-violation sites in Phase 7); 1 new test file (test_app_controller_result.py) extended + 1 new test file (tests/test_audit_heuristics.py); 4 metadata/plan/state files; 1 end-of-track report. 25+ atomic commits (18 in Phases 1-6 + 7+ in Phase 7)."
  },
  "risk_register": [
    {
      "risk": "Migrating __getattr__ may break Python's attribute lookup protocol (e.g., hasattr)",
      "likelihood": "medium",
      "mitigation": "Phase 4 task 4.1 explicitly tests test_app_getattr_hasattr_bug.py and test_app_controller_getattr_ui_bug.py; SUSPICIOUS rethrows are migrated; Pattern 1/2/3 legitimate rethrows stay"
    },
    {
      "risk": "Migrating 32 broad-catch sites changes error reporting semantics that downstream code may depend on",
      "likelihood": "medium",
      "mitigation": "Each batch is committed separately; the 2 new Result tests verify the contract; the batched suite is re-run at the end of Phase 5 to catch downstream breakage"
    },
    {
      "risk": "The audit's per-category count may shift as the migration proceeds (the script may reclassify sites based on context)",
      "likelihood": "low",
      "mitigation": "The audit is run after each phase; if a site moves from INTERNAL_BROAD_CATCH to BOUNDARY_FASTAPI mid-migration, the plan task description is updated to reflect the new category"
    },
    {
      "risk": "Scope is larger than the umbrella estimated (45 vs 22 migration sites); the XL T-shirt size may understate the work",
      "likelihood": "medium",
      "mitigation": "The umbrella spec is updated post-track (Phase 5 task 5.6) to reflect the actual count; the audit's per-category output is the source of truth"
    },
    {
      "risk": "The 2 known regressions (test_tool_ask_approval, test_execution_sim_live) may have additional root causes beyond the log_tool_call half-migration",
      "likelihood": "low",
      "mitigation": "Phase 1 task 1.3 is the regression fix; if the tests still fail after the fix, the implementation investigates before Phase 2 begins (do not loop; read code, predict, fix once, report)"
    },
    {
      "risk": "Phase 6: Tier 2 may repeat the Phase 3 deferral pattern (using logging.debug as a 'migration' that the audit still flags as silent swallow)",
      "likelihood": "medium",
      "mitigation": "The audit gate in FR12 (--strict exits 1 on any violation) is the hard verification. If FR12 fails, the track is not complete regardless of how many sites are touched."
    },
    {
      "risk": "Phase 6: Some sites may need their callers updated to receive Result[T] instead of T (e.g., _update_inject_preview)",
      "likelihood": "medium",
      "mitigation": "Each task identifies its caller chain via py_find_usages and updates all callers in the same commit. For property setters (which can't return values), the migration uses a sibling _result helper pattern."
    },
    {
      "risk": "Phase 6: The 20 nested sites introduced by Phase 2 may have been overwritten by Phase 3's logging.debug add",
      "likelihood": "medium",
      "mitigation": "The migration must remove the logging.debug AND replace with Result return (not add a Result on top of the logging). The audit --strict gate catches any leftover logging-only bodies."
    },
    {
      "risk": "Phase 6: Scope (28 sites) is large; Phase 6 may itself need a follow-up Phase 7 if any site resists migration",
      "likelihood": "low",
      "mitigation": "Phase 6 is bounded by 8 sub-phases with concrete drain-point patterns. If a site resists migration (e.g., a function with side effects that cannot return Result), the user explicitly carves it out; no Tier 2-initiated 'follow-up' deferrals are allowed."
    },
    {
      "risk": "Phase 7: Heuristic tightening may regress other files' _api_* boundary sites that do not raise HTTPException",
      "likelihood": "medium",
      "mitigation": "FR7's 3 unit tests in tests/test_audit_heuristics.py lock the 15 existing BOUNDARY_FASTAPI sites; manual verification of src/api_hooks.py during implementation"
    },
    {
      "risk": "Phase 7: Legacy wrapper for _push_mma_state_update preserves fire-and-forget semantics that may mask future failures",
      "likelihood": "low",
      "mitigation": "Docstring deprecation note in _push_mma_state_update; follow-up track migrates callers to the _result variant"
    },
    {
      "risk": "Phase 7: _last_request_errors field may grow unbounded if not reset per-request",
      "likelihood": "low",
      "mitigation": "Verify Phase 6 added the per-request reset; add reset in _api_generate entry point if missing"
    }
  ]
}
