{
  "track_id": "mma_tier_usage_reset_fix_20260610",
  "name": "Fix mma_tier_usage reset + 2 pre-existing controller bugs (2026-06-10)",
  "created_at": "2026-06-10",
  "status": "shipped",
  "priority": "A",
  "blocked_by": [],
  "blocks": [],
  "inherits_from": [
    "conductor/tracks/workspace_path_finalize_20260609/"
  ],
  "supersedes": [],
  "domain": "AppController (test infrastructure)",
  "scope_summary": "Four surgical fixes in src/app_controller.py: (FR1) pre-populate mma_tier_usage on reset (matches __init__ defaults) so _flush_to_project doesn't crash with KeyError; (FR2) make _flush_to_project defensive against missing 'model' key; (FR3) re-add self.context_preset_manager = ContextPresetManager() init that was lost in 72f8f466; (FR4) remove 'persona_manager' from _LAZY_MANAGER_DEFAULTS in __getattr__ because the comment is wrong (returning None makes hasattr() return True, not False).",
  "estimated_effort": "1.5 hours",
  "phases": 1,
  "verification_criteria": [
    "src/app_controller.py:3409 pre-populates mma_tier_usage with the full default shape (input, output, provider, model, tool_preset for all 4 tiers)",
    "src/app_controller.py:2639 uses d.get('model') instead of d['model']",
    "src/app_controller.py:__init__ contains self.context_preset_manager = ContextPresetManager()",
    "src/app_controller.py:1266-1275 does NOT contain 'persona_manager' in _LAZY_MANAGER_DEFAULTS",
    "A new unit test in tests/test_mma_tier_usage_reset_fix.py verifies the post-reset flush does not raise KeyError",
    "tests/test_reset_session_clears_mma_and_rag.py (3 tests) still pass",
    "tests/test_context_presets_manager.py::test_app_controller_save_load passes",
    "tests/test_project_switch_persona_preset.py::test_load_active_project_creates_persona_manager passes",
    "tests/test_project_switch_persona_preset.py::test_load_context_preset_missing_raises_keyerror passes",
    "All 4 tests in tests/test_extended_sims.py pass in batch (test_context_sim_live, test_ai_settings_sim_live, test_tools_sim_live, test_execution_sim_live)",
    "Tier-1 batch: 5/5 pass",
    "Tier-2 batch: 5/5 pass",
    "Tier-3 batch: 0 new failures vs 33d02bb1 baseline"
  ],
  "out_of_scope": [
    "Refactoring _switch_project to use a state machine",
    "Removing the recursive re-switch in _do_project_switch's finally",
    "Removing the other 5 names from _LAZY_MANAGER_DEFAULTS (context_preset_manager, tool_preset_manager, preset_manager, vendor_state, perf_monitor) — only persona_manager is removed in this track",
    "Modifying the 3 tests in tests/test_reset_session_clears_mma_and_rag.py",
    "Modifying tests/test_context_presets_manager.py::test_app_controller_save_load",
    "Modifying tests/test_project_switch_persona_preset.py::test_load_active_project_creates_persona_manager",
    "Modifying tests/test_project_switch_persona_preset.py::test_load_context_preset_missing_raises_keyerror",
    "Refactoring simulation/sim_base.py or simulation/sim_context.py",
    "Adding new audit scripts",
    "Doc updates",
    "Follow-up tracks",
    "Any 'while we're at it' refactors"
  ],
  "risks": [
    {
      "risk": "The pre-populated default values drift from the __init__ values over time (someone changes one but not the other)",
      "mitigation": "Add a comment in the reset code pointing to the __init__ shape; both sites should be updated together. Out of scope for this track to extract a shared constant."
    },
    {
      "risk": "Defense-in-depth change at line 2639 silently drops 'model' from the saved project, causing the next load to lose data",
      "mitigation": "The d.get('model') fallback writes None when the key is missing, which is a better failure mode than a crash. The test_extended_sims tests use gemini_cli (not affected). A test asserts the saved value matches the pre-populated default."
    },
    {
      "risk": "Removing 'persona_manager' from _LAZY_MANAGER_DEFAULTS breaks code that does getattr(ctrl, 'persona_manager', None) or relies on the lazy fallback",
      "mitigation": "The track verifies in the full batch run. If any other test fails due to the change, file a follow-up. The minimal change is to remove only 'persona_manager' (the one the failing test asserts on)."
    }
  ],
  "tier_2_supervision_required_for": []
}
