name: Multi-agent review

on:
  pull_request:
    types: [opened, synchronize, reopened, ready_for_review]
  workflow_dispatch:

permissions:
  contents: read
  security-events: write

concurrency:
  group: mar-${{ github.event.pull_request.number || github.ref }}
  cancel-in-progress: true

jobs:
  review:
    if: >-
      github.event_name == 'workflow_dispatch' ||
      (!github.event.pull_request.draft &&
       github.event.pull_request.head.repo.full_name == github.repository)
    runs-on: ubuntu-latest
    environment: ai-review
    timeout-minutes: 40
    env:
      KNODR_CREDENTIAL_CLAUDE: ${{ secrets.MAR_ANTHROPIC_API_KEY }}
      KNODR_CREDENTIAL_OPENAI: ${{ secrets.MAR_OPENAI_API_KEY }}
      KNODR_CREDENTIAL_GEMINI: ${{ secrets.MAR_GEMINI_API_KEY }}
      KNODR_CREDENTIAL_GROK: ${{ secrets.MAR_XAI_API_KEY }}

    steps:
      - name: Check out the change
        uses: actions/checkout@v6
        with:
          ref: ${{ github.event.pull_request.head.sha || github.sha }}
          fetch-depth: 0
          persist-credentials: false

      # Review tooling comes from the base revision so a PR cannot replace its own reviewer.
      - name: Check out trusted review tooling
        uses: actions/checkout@v6
        with:
          ref: ${{ github.event.pull_request.base.sha || github.sha }}
          path: _mar-tooling
          sparse-checkout: ci/mar
          persist-credentials: false

      - name: Install knodr CLI
        run: |
          mkdir -p "$HOME/.local/knodr"
          curl -fSL https://dl.knodr.com/knodr-linux-x64.tar.gz | tar xz -C "$HOME/.local/knodr"
          echo "$HOME/.local/knodr" >> "$GITHUB_PATH"

      - name: Install agent CLIs
        run: |
          npm install -g @anthropic-ai/claude-code @openai/codex opencode-ai
          claude --version && codex --version && opencode --version

      - name: Build a reviewable diff
        id: diff
        run: |
          mkdir -p .mar-tmp
          base='${{ github.event.pull_request.base.sha }}'
          [ -n "$base" ] || base=$(git rev-parse HEAD^)
          git diff "$base...HEAD" -- . \
            ':(exclude)_mar-tooling/**' ':(exclude)**/bin/**' ':(exclude)**/obj/**' \
            ':(exclude)*.png' ':(exclude)*.jpg' ':(exclude)*.pdf' \
            > .mar-tmp/diff.txt
          if [ -s .mar-tmp/diff.txt ]; then
            echo "has_changes=true" >> "$GITHUB_OUTPUT"
          else
            echo "has_changes=false" >> "$GITHUB_OUTPUT"
          fi

      - name: Preflight
        if: steps.diff.outputs.has_changes == 'true'
        run: |
          knodr doctor _mar-tooling/ci/mar/ci-multi-agent-review.knodrflow \
            --var repo="$GITHUB_WORKSPACE" \
            --var diffPath="$GITHUB_WORKSPACE/.mar-tmp/diff.txt" \
            --var comments=preflight \
            --var rendererPath="$GITHUB_WORKSPACE/_mar-tooling/ci/mar/render.py" \
            --deep --output-format json

      - name: Run multi-agent review
        if: steps.diff.outputs.has_changes == 'true'
        run: |
          knodr run _mar-tooling/ci/mar/ci-multi-agent-review.knodrflow \
            --var repo="$GITHUB_WORKSPACE" \
            --var diffPath="$GITHUB_WORKSPACE/.mar-tmp/diff.txt" \
            --var comments="${{ github.event.pull_request.title || 'Manual review' }}" \
            --var rendererPath="$GITHUB_WORKSPACE/_mar-tooling/ci/mar/render.py" \
            --timeout 30m --output-format json

      - name: Add the report to the job summary
        if: always() && hashFiles('.mar-out/mar-report.md') != ''
        run: cat .mar-out/mar-report.md >> "$GITHUB_STEP_SUMMARY"

      - name: Upload SARIF annotations
        if: always() && hashFiles('.mar-out/mar-results.sarif') != ''
        continue-on-error: true
        uses: github/codeql-action/upload-sarif@v4
        with:
          sarif_file: .mar-out/mar-results.sarif
          category: knodr-multi-agent-review

      - name: Upload review artifacts
        if: always() && hashFiles('.mar-out/**') != ''
        uses: actions/upload-artifact@v7
        with:
          name: multi-agent-review-${{ github.event.pull_request.number || github.run_number }}
          path: .mar-out/
          include-hidden-files: true
          retention-days: 7
