workflow:
  id: qa-loop
  name: QA Loop Orchestrator - Review Fix Re-review Cycle
  version: "1.0"
  description: >-
    Automated QA loop that orchestrates the review → fix → re-review cycle.
    Runs up to maxIterations (default 5), tracking each iteration's results.
    Escalates to human when max iterations reached or manual stop requested.

    Part of Epic 6 - QA Evolution: Autonomous Development Engine (ADE).

  type: loop
  project_types:
    - aiox-development
    - autonomous-development
    - qa-automation

  # ═══════════════════════════════════════════════════════════════════════════════════
  #                              TRIGGER CONFIGURATION
  # ═══════════════════════════════════════════════════════════════════════════════════

  triggers:
    # Primary trigger: Explicit command to start loop
    - event: command
      command: "*qa-loop"
      action: start_loop

    # Start from specific phase
    - event: command
      command: "*qa-loop-review"
      action: run_step
      step: review

    - event: command
      command: "*qa-loop-fix"
      action: run_step
      step: fix

    # Stop command (AC5)
    - event: command
      command: "*stop-qa-loop"
      action: stop_loop

    # Resume command
    - event: command
      command: "*resume-qa-loop"
      action: resume_loop

    # Force escalation
    - event: command
      command: "*escalate-qa-loop"
      action: escalate

  # ═══════════════════════════════════════════════════════════════════════════════════
  #                              CONFIGURATION
  # ═══════════════════════════════════════════════════════════════════════════════════

  config:
    # AC2: Maximum iterations (configurable)
    maxIterations: 5
    configPath: autoClaude.qaLoop.maxIterations

    # Progress tracking
    showProgress: true
    verbose: true

    # Status file location (AC4)
    statusFile: qa/loop-status.json

    # Dashboard integration (AC7)
    dashboardStatusPath: .aiox/dashboard/status.json
    legacyStatusPath: .aiox/status.json

    # Timeout per phase (milliseconds)
    reviewTimeout: 1800000  # 30 minutes
    fixTimeout: 3600000     # 60 minutes

    # Retry configuration
    maxRetries: 2
    retryDelay: 5000

  # ═══════════════════════════════════════════════════════════════════════════════════
  #                              LOOP STATUS SCHEMA (AC4)
  # ═══════════════════════════════════════════════════════════════════════════════════

  status_schema:
    storyId: string
    currentIteration: number
    maxIterations: number
    status: "pending | in_progress | completed | stopped | escalated"
    startedAt: ISO-8601
    updatedAt: ISO-8601
    history:
      - iteration: number
        reviewedAt: ISO-8601
        verdict: "APPROVE | REJECT | BLOCKED"
        issuesFound: number
        fixedAt: ISO-8601 | null
        issuesFixed: number | null
        duration: number  # milliseconds

  # ═══════════════════════════════════════════════════════════════════════════════════
  #                              WORKFLOW SEQUENCE
  # ═══════════════════════════════════════════════════════════════════════════════════

  sequence:

    # ═════════════════════════════════════════════════════════════════════════════════
    # STEP 1: REVIEW (QA Agent)
    # ═════════════════════════════════════════════════════════════════════════════════

    - step: review
      phase: 1
      phase_name: "QA Review"
      agent: qa

      description: >-
        Execute comprehensive QA review of the story implementation.
        Produces a verdict: APPROVE, REJECT, or BLOCKED.

      task: qa-review-story.md

      inputs:
        storyId: "{storyId}"
        iteration: "{currentIteration}"
        previousIssues: "{history[-1].issuesFound|0}"

      outputs:
        - gate-file.yaml
        - verdict
        - issuesFound

      timeout: "{config.reviewTimeout}"

      on_success:
        log: "Review complete: {verdict} ({issuesFound} issues)"
        next: check_verdict

      on_failure:
        action: retry
        max_retries: "{config.maxRetries}"
        on_exhausted: escalate

    # ═════════════════════════════════════════════════════════════════════════════════
    # STEP 2: CHECK VERDICT (AC1)
    # ═════════════════════════════════════════════════════════════════════════════════

    - step: check_verdict
      phase: 2
      phase_name: "Verdict Check"
      agent: system

      description: >-
        Evaluate the review verdict and determine next action.
        APPROVE = complete, REJECT = continue to fix, BLOCKED = escalate.

      condition_check:
        - condition: verdict == "APPROVE"
          action: complete
          log: "Story APPROVED after {currentIteration} iteration(s)"

        - condition: verdict == "BLOCKED"
          action: escalate
          reason: "QA review BLOCKED - requires human intervention"

        - condition: verdict == "REJECT"
          action: continue
          next: create_fix_request

    # ═════════════════════════════════════════════════════════════════════════════════
    # STEP 3: CREATE FIX REQUEST (QA Agent)
    # ═════════════════════════════════════════════════════════════════════════════════

    - step: create_fix_request
      phase: 3
      phase_name: "Create Fix Request"
      agent: qa

      description: >-
        Generate a structured fix request document from review findings.
        Prioritizes issues and provides actionable fix instructions.

      task: qa-create-fix-request.md

      inputs:
        storyId: "{storyId}"
        gateFile: "{outputs.review.gate-file}"
        iteration: "{currentIteration}"

      outputs:
        - fix-request.md
        - prioritizedIssues

      on_success:
        log: "Fix request created with {prioritizedIssues.length} prioritized issues"
        next: fix_issues

      on_failure:
        action: continue
        fallback: "Use raw gate file for fixes"

    # ═════════════════════════════════════════════════════════════════════════════════
    # STEP 4: FIX ISSUES (Dev Agent)
    # ═════════════════════════════════════════════════════════════════════════════════

    - step: fix_issues
      phase: 4
      phase_name: "Apply Fixes"
      agent: dev

      description: >-
        Developer agent applies fixes based on the fix request.
        Runs tests and validates changes.

      task: dev-apply-qa-fixes.md

      inputs:
        storyId: "{storyId}"
        fixRequest: "{outputs.create_fix_request.fix-request}"
        iteration: "{currentIteration}"

      outputs:
        - fixes-applied.json
        - issuesFixed

      timeout: "{config.fixTimeout}"

      on_success:
        log: "Fixed {issuesFixed} of {issuesFound} issues"
        next: increment_iteration

      on_failure:
        action: retry
        max_retries: "{config.maxRetries}"
        on_exhausted:
          action: escalate
          reason: "Dev agent unable to apply fixes after retries"

    # ═════════════════════════════════════════════════════════════════════════════════
    # STEP 5: INCREMENT ITERATION (AC2)
    # ═════════════════════════════════════════════════════════════════════════════════

    - step: increment_iteration
      phase: 5
      phase_name: "Check Iteration"
      agent: system

      description: >-
        Increment iteration counter and check against max.
        If max reached, escalate to human (AC3).

      action: increment_and_check

      condition_check:
        - condition: currentIteration >= maxIterations
          action: escalate
          reason: "Max iterations ({maxIterations}) reached without APPROVE"
          log: "Max iterations reached - escalating to human"

        - condition: currentIteration < maxIterations
          action: continue
          next: review
          log: "Starting iteration {currentIteration + 1}/{maxIterations}"

  # ═══════════════════════════════════════════════════════════════════════════════════
  #                              ESCALATION (AC3)
  # ═══════════════════════════════════════════════════════════════════════════════════

  escalation:
    enabled: true

    triggers:
      - max_iterations_reached
      - verdict_blocked
      - fix_failure
      - manual_escalate

    action:
      log: "Escalating to human with full context"
      status: "escalated"

      context_package:
        - loop-status.json
        - all gate files from history
        - all fix requests
        - summary of iterations

      notification:
        message: |
          QA Loop Escalation for {storyId}

          Reason: {escalation.reason}
          Iterations completed: {currentIteration}
          Last verdict: {history[-1].verdict}
          Outstanding issues: {history[-1].issuesFound - history[-1].issuesFixed}

          Review the context package and decide:
          1. Resume loop: *resume-qa-loop {storyId}
          2. Manually fix and approve
          3. Reject story and create follow-up

        channels: [log, console]

  # ═══════════════════════════════════════════════════════════════════════════════════
  #                              WORKFLOW COMPLETION (AC6)
  # ═══════════════════════════════════════════════════════════════════════════════════

  completion:
    success_message: |
      ╔══════════════════════════════════════════════════════════════╗
      ║  QA Loop Complete                                            ║
      ╚══════════════════════════════════════════════════════════════╝

      Story:       {storyId}
      Status:      {status}
      Iterations:  {currentIteration}/{maxIterations}
      Final Verdict: {history[-1].verdict}

      Iteration History:
      {history.map(h => `  ${h.iteration}. ${h.verdict} - ${h.issuesFound} found, ${h.issuesFixed || 0} fixed`).join('\n')}

      Duration: {totalDuration}

    summary:
      storyId: "{storyId}"
      status: "{status}"
      iterations: "{currentIteration}"
      finalVerdict: "{history[-1].verdict}"
      totalIssuesFound: "{history.reduce((sum, h) => sum + h.issuesFound, 0)}"
      totalIssuesFixed: "{history.reduce((sum, h) => sum + (h.issuesFixed || 0), 0)}"
      duration: "{totalDuration}"

    outputs:
      - loop-status.json
      - summary.md

  # ═══════════════════════════════════════════════════════════════════════════════════
  #                              ERROR HANDLING
  # ═══════════════════════════════════════════════════════════════════════════════════

  error_handling:
    missing_story_id:
      message: "Story ID is required"
      suggestion: "Usage: *qa-loop STORY-42"
      action: prompt

    review_timeout:
      message: "Review phase timed out"
      suggestion: "Check QA agent status and retry: *resume-qa-loop {storyId}"
      action: escalate

    fix_timeout:
      message: "Fix phase timed out"
      suggestion: "Check Dev agent status and retry: *resume-qa-loop {storyId}"
      action: escalate

    invalid_status:
      message: "Loop status file is corrupted or invalid"
      suggestion: "Reset loop: *qa-loop {storyId} --reset"
      action: halt

  # ═══════════════════════════════════════════════════════════════════════════════════
  #                              STOP/RESUME SUPPORT (AC5)
  # ═══════════════════════════════════════════════════════════════════════════════════

  control:
    stop:
      command: "*stop-qa-loop"
      action: |
        - Set status to "stopped"
        - Save current state to loop-status.json
        - Log: "QA loop stopped at iteration {currentIteration}"
        - Allow resume later

    resume:
      command: "*resume-qa-loop"
      action: |
        - Load state from loop-status.json
        - Verify status was "stopped" or "escalated"
        - Set status to "in_progress"
        - Continue from last step
        - Log: "QA loop resumed at iteration {currentIteration}"

    reset:
      command: "*qa-loop --reset"
      action: |
        - Delete loop-status.json
        - Start fresh loop
        - Log: "QA loop reset for {storyId}"

  # ═══════════════════════════════════════════════════════════════════════════════════
  #                              DASHBOARD INTEGRATION (AC7)
  # ═══════════════════════════════════════════════════════════════════════════════════

  integration:
    status_json:
      track_loop: true
      field: qaLoop
      update_on_each_iteration: true

      schema:
        storyId: string
        status: string
        currentIteration: number
        maxIterations: number
        lastVerdict: string
        lastIssuesFound: number
        updatedAt: ISO-8601

    project_status:
      update_story_status: true
      status_field: qaLoopStatus

    notifications:
      on_approve:
        message: "QA Loop APPROVED: {storyId}"
        channels: [log]
      on_escalate:
        message: "QA Loop ESCALATED: {storyId} - needs attention"
        channels: [log]
      on_stop:
        message: "QA Loop STOPPED: {storyId}"
        channels: [log]

  # ═══════════════════════════════════════════════════════════════════════════════════
  #                              METADATA
  # ═══════════════════════════════════════════════════════════════════════════════════

  metadata:
    story: "6.5"
    epic: "Epic 6 - QA Evolution"
    created: "2026-01-29"
    author: "@architect (Aria)"
    dependencies:
      - qa-review-story.md
      - qa-create-fix-request.md
      - dev-apply-qa-fixes.md
    tags:
      - qa-loop
      - workflow
      - orchestration
      - ade
      - autonomous
