name: fix-quality-and-tests
description: |
  Sequential quality gate: lint + format + types must be clean before tests are
  checked. Auto-fixes lint/format violations; analyzes and fixes type errors with
  a dedicated investigation pass. After fixing test failures, loops back to
  check-quality to catch regressions.
initial: check-quality
states:
  check-quality:
    action: "Run `/ll:check-code lint,format,types` and report results."
    action_type: prompt
    evaluate:
      type: llm_structured
      prompt: |
        Did ALL three checks (lint, format, types) pass with zero errors?
        Return "yes" only if all three are clean.
        Return "no" if any check found errors.
        Return "partial" if the output is ambiguous or incomplete.
    on_yes: check-tests
    on_no: fix-lint-format
    on_partial: check-quality
    on_error: fix-lint-format
  fix-lint-format:
    action_type: prompt
    timeout: 300
    action: |
      Run `/ll:check-code fix` to auto-fix any lint and format violations.
    next: analyze-type-errors
  analyze-type-errors:
    action_type: prompt
    timeout: 120
    action: |
      Run `/ll:check-code types` to get the current type errors.

      If mypy exits cleanly (no errors), state: "No type errors found."

      Otherwise, categorize the errors found:
      - Missing type annotations
      - Incompatible types
      - Missing imports / stubs
      - Other

      List the top 5 highest-impact errors (those most likely to cause cascading
      failures when fixed). We will fix these first.
    capture: type_analysis
    next: fix-type-errors
  fix-type-errors:
    action_type: prompt
    timeout: 600
    action: |
      Based on the type error analysis:
      ${captured.type_analysis.output}

      If the analysis says "No type errors found", skip this step and proceed.

      Otherwise, fix the identified type errors in priority order. For each error:
      1. Read the affected file
      2. Understand what the correct type should be
      3. Apply a targeted fix — prefer accurate types over broad Any/ignore
      4. Do NOT use # type: ignore unless genuinely unavoidable and documented why

      Fix up to 5 errors per iteration to keep changes reviewable.
    next: check-quality
  check-tests:
    action_type: shell
    timeout: 600
    action: |
      CMD=$(python3 -c "
      import json, pathlib
      p = pathlib.Path('.ll/ll-config.json')
      cfg = json.loads(p.read_text()) if p.exists() else {}
      print(cfg.get('project', {}).get('test_cmd', 'pytest'))
      ")
      mkdir -p .loops/tmp
      set -o pipefail
      eval "$CMD" 2>&1 | tee .loops/tmp/ll-test-results.txt
    evaluate:
      type: exit_code
    on_yes: done
    on_no: fix-tests
    on_error: fix-tests
  fix-tests:
    action_type: prompt
    timeout: 1800
    action: |
      Read .loops/tmp/ll-test-results.txt to see the current test failures captured
      from the last test run.

      For each failing test, diagnose BEFORE making any changes:

      Ask: "Is the test assertion correct given the intended behavior?"

      → If the TEST is wrong (outdated assertion, stale expected value,
        testing implementation details that legitimately changed):
        fix the test to reflect the correct expected behavior.

      → If the IMPLEMENTATION is wrong (genuine bug, regression, broken
        contract): fix the implementation, not the test.

      Rules:
      - Never delete a test to make it pass
      - Never mock away a real failure
      - Fix one failure at a time; re-run that test before moving on
      - If ambiguous, prefer fixing the implementation over the test
    next: check-quality
  done:
    terminal: true
max_iterations: 30
timeout: 7200
on_handoff: spawn
