name: Triage Sweep

on:
  workflow_dispatch:
    inputs:
      iqr_multiplier:
        description: >-
          IQR multiplier for outlier cutoff.
          cutoff = Q75 + multiplier * IQR.
          Higher = fewer outliers flagged.
        type: number
        default: 3.0
      max_outlier_pct:
        description: >-
          Maximum fraction of items that can be flagged as outliers (0-1).
          Hard cap to prevent over-flagging.
        type: number
        default: 0.05
      contamination:
        description: >-
          Expected fraction of outliers in the data (0-0.5).
          Controls how aggressively EllipticEnvelope downweights extremes.
        type: number
        default: 0.1
      cosine_threshold:
        description: >-
          Cosine similarity threshold for duplicate detection.
          Pairs with similarity above this are flagged as potential duplicates.
          Higher = only very similar pairs flagged.
        type: number
        default: 0.92
      max_items:
        description: >-
          Maximum number of open issues + PRs to process.
          Hard cap to prevent runaway costs on very large repos.
        type: number
        default: 500
      dry_run:
        description: >-
          Check this to only log results to the workflow summary.
          Uncheck to create a GitHub issue with the report and apply labels.
        type: boolean
        default: false

permissions:
  contents: read
  issues: write
  pull-requests: write

# Concurrency convention: see CONTRIBUTING.md → "GitHub Actions — Concurrency Convention".
# Single global slot — newest manual dispatch supersedes any in-flight run.
concurrency:
  group: ${{ github.workflow }}
  cancel-in-progress: true

jobs:
  sweep:
    runs-on: ubuntu-latest
    timeout-minutes: 30
    steps:
      - name: Checkout repository
        uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
        with:
          sparse-checkout: .github/scripts/triage
          sparse-checkout-cone-mode: false
          fetch-depth: 1

      - name: Set up Python
        uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6
        with:
          python-version: '3.12'
          cache: pip
          cache-dependency-path: .github/scripts/triage/requirements.txt

      - name: Install dependencies
        run: pip install -r .github/scripts/triage/requirements.txt

      - name: Cache FastEmbed model weights
        uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5
        with:
          path: ${{ github.workspace }}/.fastembed_cache
          key: fastembed-bge-small-en-v1.5

      - name: Run triage sweep
        id: sweep
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          GITHUB_REPOSITORY: ${{ github.repository }}
          FASTEMBED_CACHE_PATH: ${{ github.workspace }}/.fastembed_cache
          INPUT_IQR_MULTIPLIER: ${{ inputs.iqr_multiplier }}
          INPUT_MAX_OUTLIER_PCT: ${{ inputs.max_outlier_pct }}
          INPUT_CONTAMINATION: ${{ inputs.contamination }}
          INPUT_COSINE_THRESHOLD: ${{ inputs.cosine_threshold }}
          INPUT_MAX_ITEMS: ${{ inputs.max_items }}
          INPUT_DRY_RUN: ${{ inputs.dry_run }}
        run: python .github/scripts/triage/sweep.py

      - name: Post summary
        if: always()
        run: |
          if [ -f /tmp/triage-report.md ]; then
            cat /tmp/triage-report.md >> "$GITHUB_STEP_SUMMARY"
          else
            echo "No report generated." >> "$GITHUB_STEP_SUMMARY"
          fi
