name: Multi-agent review

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

permissions:
  contents: read
  actions: read
  security-events: write

concurrency:
  group: multi-agent-review-${{ 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: [self-hosted, windows, x64, ai-review]
    environment: ai-review
    timeout-minutes: 40
    continue-on-error: true
    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 }}
      MAR_BASE_SHA: ${{ github.event.pull_request.base.sha }}
      MAR_HEAD_SHA: ${{ github.event.pull_request.head.sha || github.sha }}
      MAR_COMMENTS: ${{ github.event.pull_request.title || 'Manual multi-agent review' }}

    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

      - name: Check out trusted review tooling from the base revision
        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: Verify the runner
        shell: pwsh
        run: |
          $commands = @("knodr", "python", "git", "claude", "codex", "opencode")
          foreach ($command in $commands) {
            if (-not (Get-Command $command -ErrorAction SilentlyContinue)) {
              throw "Required command '$command' is not on PATH."
            }
          }
          $secretNames = @(
            "KNODR_CREDENTIAL_CLAUDE",
            "KNODR_CREDENTIAL_OPENAI",
            "KNODR_CREDENTIAL_GEMINI",
            "KNODR_CREDENTIAL_GROK"
          )
          foreach ($name in $secretNames) {
            if (-not [Environment]::GetEnvironmentVariable($name)) {
              throw "Required GitHub environment secret for '$name' is missing."
            }
          }
          knodr --version
          python --version
          git --version

      - name: Build a reviewable UTF-8 diff
        id: diff
        shell: pwsh
        run: |
          [Console]::OutputEncoding = [Text.UTF8Encoding]::new($false)
          New-Item -ItemType Directory -Force -Path .mar-tmp | Out-Null

          $base = $env:MAR_BASE_SHA
          if (-not $base) {
            $base = (git rev-parse HEAD^).Trim()
          }
          $exclude = @(
            ":(exclude)_mar-tooling/**",
            ":(exclude)**/bin/**",
            ":(exclude)**/obj/**",
            ":(exclude)packages/**",
            ":(exclude)*.dll",
            ":(exclude)*.exe",
            ":(exclude)*.pdb",
            ":(exclude)*.nupkg",
            ":(exclude)*.zip",
            ":(exclude)*.7z",
            ":(exclude)*.png",
            ":(exclude)*.jpg",
            ":(exclude)*.gif",
            ":(exclude)*.pdf",
            ":(exclude)*.Designer.cs",
            ":(exclude)*.g.cs",
            ":(exclude)*.g.i.cs"
          )

          $raw = git diff "$base...$env:MAR_HEAD_SHA" -- . $exclude
          if ($LASTEXITCODE -ne 0) {
            throw "git diff failed with exit code $LASTEXITCODE"
          }
          $diff = $raw -join "`n"
          if (-not $diff.Trim()) {
            "has_changes=false" | Out-File -FilePath $env:GITHUB_OUTPUT -Append -Encoding utf8
            Write-Host "No reviewable code changes."
            exit 0
          }

          [IO.File]::WriteAllText(
            "$env:GITHUB_WORKSPACE\.mar-tmp\diff.txt",
            $diff,
            [Text.UTF8Encoding]::new($false)
          )
          "has_changes=true" | Out-File -FilePath $env:GITHUB_OUTPUT -Append -Encoding utf8
          Write-Host "Prepared $($diff.Length) characters of diff."

      - name: Run Knodr multi-agent review
        if: steps.diff.outputs.has_changes == 'true'
        shell: pwsh
        run: |
          $title = $env:MAR_COMMENTS.Replace([char]34, [char]39).TrimEnd([char]92)
          $toolRoot = "$env:GITHUB_WORKSPACE\_mar-tooling\ci\mar"
          & knodr run "$toolRoot\ci-multi-agent-review.knodrflow" `
            --var "repo=$env:GITHUB_WORKSPACE" `
            --var "diffPath=$env:GITHUB_WORKSPACE\.mar-tmp\diff.txt" `
            --var "comments=$title" `
            --var "rendererPath=$toolRoot\render.py" `
            --timeout 30m `
            --log-level Debug `
            --output-format json
          if ($LASTEXITCODE -ne 0) {
            exit $LASTEXITCODE
          }

      - name: Add the report to the job summary
        if: always() && hashFiles('.mar-out/mar-report.md') != ''
        shell: pwsh
        run: Get-Content .mar-out/mar-report.md -Raw | Add-Content $env: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/mar-report.html
            .mar-out/mar-report.md
            .mar-out/mar-results.sarif
            .mar-out/agents-raw.log
          if-no-files-found: warn
          include-hidden-files: true
          retention-days: 7
