Files
manual_slop/conductor/tracks/fix_test_failures_20260624/plan.md
T

7.5 KiB

Plan: fix_test_failures_20260624

3 phases, 3 tasks, 3 atomic commits. TDD: write the failing test invocation first (the existing 14 tests are the red), fix the code (green), commit.

Phase 1: NormalizedResponse dual-signature (1 task)

Focus: Add custom __init__ to NormalizedResponse that accepts both new nested usage: UsageStats and legacy flat kwargs. This fixes 12 of the 14 failing tests in one place.

  • Task 1.1: Add custom __init__ to NormalizedResponse in src/openai_schemas.py. [1b39aae7]
    • WHERE: src/openai_schemas.py:75-80 (the @dataclass(frozen=True) class NormalizedResponse: block)
    • WHAT:
      • Change @dataclass(frozen=True) to @dataclass(frozen=True, init=False) on line 75
      • Add a custom __init__ method (after the class fields) that:
        • Signature: (self, text: str, tool_calls: tuple[ToolCall, ...] = (), usage: Optional[UsageStats] = None, raw_response: Any = None, usage_input_tokens: Optional[int] = None, usage_output_tokens: Optional[int] = None, usage_cache_read_tokens: Optional[int] = None, usage_cache_creation_tokens: Optional[int] = None) -> None
        • If usage is None and any legacy flat kwarg is non-None: build UsageStats(input_tokens=usage_input_tokens or 0, output_tokens=usage_output_tokens or 0, cache_read_tokens=usage_cache_read_tokens or 0, cache_creation_tokens=usage_cache_creation_tokens or 0)
        • If usage is None and all legacy flat kwargs are None: build UsageStats(0, 0)
        • Otherwise: use the provided usage
        • Use object.__setattr__(self, "text", text) for all 4 field assignments (required because frozen=True locks __setattr__)
    • HOW: Use manual-slop_py_update_definition to replace the entire class block. The new content includes the init=False decorator and the custom __init__ method.
    • SAFETY:
      • Verify with ast.parse(open("src/openai_schemas.py").read()) (no syntax errors)
      • Run uv run python -c "from src.openai_schemas import NormalizedResponse, UsageStats; r = NormalizedResponse(text='hi', tool_calls=(), usage_input_tokens=10, usage_output_tokens=5, raw_response=None); print(r.usage.input_tokens, r.usage.output_tokens)"
      • Run the 12 affected tests
    • COMMIT: fix(schemas): add legacy-kwarg backward compat to NormalizedResponse.__init__
    • GIT NOTE: 12 tests fixed by single backward-compat init; supports both new nested usage: UsageStats and legacy flat usage_input_tokens=... kwargs
    • VERIFY: uv run pytest tests/test_ai_client_cli.py tests/test_ai_client_tool_loop.py tests/test_ai_client_tool_loop_builder.py tests/test_ai_client_tool_loop_send_func.py tests/test_gemini_cli_integration.py tests/test_gemini_cli_parity_regression.py tests/test_gemini_cli_edge_cases.py -v shows 12/12 pass

Phase 2: Session frozen fix (1 task)

Focus: Update the test to use dataclasses.replace() instead of mutating the frozen Session.

  • Task 2.1: Update test_auto_whitelist_keywords to use dataclasses.replace. [24b39aee]
    • WHERE: tests/test_auto_whitelist.py:20
    • WHAT: Change reg.data[session_id]["whitelisted"] = True to reg.data[session_id] = dataclasses.replace(reg.data[session_id], whitelisted=True)
    • HOW: Use manual-slop_edit_file with the exact old/new text. Add import dataclasses to the top of the file if not already imported.
    • SAFETY: Verify with uv run pytest tests/test_auto_whitelist.py -v
    • COMMIT: test(auto-whitelist): use dataclasses.replace for frozen Session mutation
    • GIT NOTE: 1 test fixed; the old ["whitelisted"] = True was invalid on a frozen dataclass
    • VERIFY: uv run pytest tests/test_auto_whitelist.py -v shows 0 failures

Phase 3: Toggle race fix (1 task)

Focus: Replace the non-deterministic toggle with a deterministic close path.

  • Task 3.1: Update test_palette_starts_hidden to use a deterministic close callback. [63e4e54e]
    • WHERE: tests/test_command_palette_sim.py:38 (the client.push_event("custom_callback", {"callback": "_toggle_command_palette", "args": []}) call)
    • WHAT:
      • Check _predefined_callbacks in src/api_hooks.py for a close callback (e.g., _close_command_palette or similar). If found, use it.
      • If no close callback exists, push _toggle_command_palette once, poll for state, then push again to guarantee the palette is closed.
    • HOW: Use manual-slop_edit_file with the exact old/new text.
    • SAFETY: The test must end with show_command_palette is False regardless of starting state. Verify with uv run pytest tests/test_command_palette_sim.py -v in isolation AND in the full batch (per the Isolated-Pass Verification Fallacy rule in conductor/workflow.md).
    • COMMIT: test(palette): use deterministic close instead of toggle for palette_starts_hidden test
    • GIT NOTE: 1 test fixed; toggle is non-deterministic (close-if-open, open-if-closed); new code forces close regardless of starting state
    • VERIFY: uv run pytest tests/test_command_palette_sim.py -v AND uv run python scripts/run_tests_batched.py (tier-3-live_gui)

Phase 4: Verification (1 task)

Focus: Confirm all 10 verification criteria pass.

  • Task 4.1: Run all 6 VCs; write the track's end-of-track report. [885bc1be]
    • WHERE: Full test suite + audit gates
    • WHAT:
      • Run VC1-VC6 (the 6 verification criteria from the spec)
      • Write docs/reports/TRACK_COMPLETION_fix_test_failures_20260624.md with the verification results
      • Update this track's state.toml to status = "completed", current_phase = "complete", all 4 phases completed
      • Update conductor/tracks.md to add a row for this track
    • HOW: Run each VC command, capture output, write the report.
    • SAFETY: The 2 pre-existing-violation audit gates (NG1, NG2 from the polish track) are still out of scope. Do not regress them.
    • COMMIT: 3 commits: conductor(state): fix_test_failures_20260624 SHIPPED, docs(reports): TRACK_COMPLETION for fix_test_failures_20260624, conductor(tracks): add fix_test_failures_20260624 row
    • GIT NOTE: 1 per commit per workflow.md
    • VERIFY: All 6 VCs pass; the 14 previously-failing tests are now green; no new failures introduced

Commit Log (Expected)

  1. fix(schemas): add legacy-kwarg backward compat to NormalizedResponse.__init__ (Task 1.1)
  2. test(auto-whitelist): use dataclasses.replace for frozen Session mutation (Task 2.1)
  3. test(palette): use deterministic close instead of toggle for palette_starts_hidden test (Task 3.1)
  4. conductor(state): fix_test_failures_20260624 SHIPPED (Task 4.1)
  5. docs(reports): TRACK_COMPLETION for fix_test_failures_20260624 (Task 4.1)
  6. conductor(tracks): add fix_test_failures_20260624 row (Task 4.1)

Verification Commands (run at end of Phase 4)

# VC1: the 12 NormalizedResponse tests pass
uv run pytest tests/test_ai_client_cli.py tests/test_ai_client_tool_loop.py tests/test_ai_client_tool_loop_builder.py tests/test_ai_client_tool_loop_send_func.py tests/test_gemini_cli_integration.py tests/test_gemini_cli_parity_regression.py tests/test_gemini_cli_edge_cases.py -v

# VC2: test_auto_whitelist_keywords passes
uv run pytest tests/test_auto_whitelist.py -v

# VC3: test_palette_starts_hidden passes
uv run pytest tests/test_command_palette_sim.py -v

# VC4: full batched suite is green
uv run python scripts/run_tests_batched.py

# VC5: 4 audit gates
uv run python scripts/audit_exception_handling.py
uv run python scripts/audit_weak_types.py
uv run python scripts/audit_main_thread_imports.py
uv run python scripts/audit_no_models_config_io.py

# VC6: confirm no new failures (diff against pre-fix summary)