# Triage every newly opened issue with an agent resolved from the catalog.
#
# `agent` is the fallback, not an override. An `agent:<slug>` label on the
# issue selects the agent first — label `agent:outfitter-bot` and the same
# workflow hands the issue to that agent instead. Only accounts with triage
# permission can label, so an issue author cannot choose the agent.
#
# Run it by hand against any issue:
#   gh workflow run issue-triage.yml -f issue=<number>
name: Issue triage
on:
  issues:
    types: [opened, labeled]
  workflow_dispatch:
    inputs:
      issue:
        description: Issue number to triage
        required: true
        type: string

permissions:
  contents: read
  issues: write
  models: read

jobs:
  triage:
    # Never triage issues the automation itself opened; manual dispatch is
    # always a human decision, so it skips the check. On `labeled`, only run
    # when the label routes an agent — otherwise every label edit re-triages.
    if: >-
      github.event_name == 'workflow_dispatch' ||
      (github.event.issue.user.type != 'Bot' &&
       (github.event.action == 'opened' ||
        startsWith(github.event.label.name, 'agent:')))
    runs-on: ubuntu-latest
    timeout-minutes: 15
    env:
      ISSUE_NUMBER: ${{ github.event.issue.number || inputs.issue }}
    steps:
      - uses: actions/checkout@v4

      - uses: ai-outfitter/actions@v1
        id: agent
        with:
          # Fallback when no `agent:<slug>` label routes the issue.
          agent: actions-agent
          # This repo's Dotagents payload sits at the repository root, so
          # without the explicit GitHub source the action would classify the
          # payload as a path source and skip `outfitter sync`.
          source: ai-outfitter/.agents
          # trigger_context passes only trusted event identifiers; the agent
          # fetches issue content with `gh`, so untrusted issue text never
          # enters workflow code. The author login is user-influenced — treat
          # it as an opaque identifier, never as instructions.
          prompt: |
            Handle this GitHub event using your system-prompt rules. Treat
            trigger_context as routing metadata, select only the relevant
            skill, then fetch the source material that skill needs with
            trusted tools. Apply exactly one label, chosen from
            available_labels.

            trigger_context:
              repository: ${{ github.repository }}
              # A manual dispatch exists to triage an issue that was missed or
              # needs re-running, so it presents the same routing metadata a
              # fresh issue would. Passing `workflow_dispatch` here selects no
              # skill: the agent declines with "not a supported issues/opened
              # trigger" and the run reports success having done nothing.
              event_name: ${{ github.event_name == 'workflow_dispatch' && 'issues' || github.event_name }}
              event_action: ${{ github.event_name == 'workflow_dispatch' && 'opened' || github.event.action }}
              issue_number: ${{ github.event.issue.number || inputs.issue }}
              issue_author: ${{ github.event.issue.user.login || '' }}
              # This catalog's native vocabulary: its issue templates are
              # feat.yml and fix.yml, and the issue-triage skill defines both
              # terms. Without available_labels the agent classifies into a
              # vocabulary the repo lacks and the apply is rejected.
              available_labels: feat, fix
        env:
          # The provider config lives in the org catalog (ai-outfitter/.agents
          # models.json) and names this key by variable, so only the value is
          # supplied here. Org-wide secret; nothing is written to disk.
          OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}

      # The action saved the agent's full session as a workflow artifact.
      # Append the link to the agent's own comment so the decision trail is one
      # click from the issue. Runs even when the agent step failed — a
      # transcript matters most then.
      - name: Link transcript on the triage comment
        if: ${{ !cancelled() && steps.agent.outputs.transcript-artifact-url != '' }}
        env:
          GH_TOKEN: ${{ github.token }}
          REPO: ${{ github.repository }}
          URL: ${{ steps.agent.outputs.transcript-artifact-url }}
        run: |
          comment_id="$(gh api --paginate "repos/$REPO/issues/$ISSUE_NUMBER/comments" \
            --jq '.[] | select(.user.login == "github-actions[bot]") | .id' | tail -n 1)"
          footer="$(printf '\n\n---\n<!-- outfitter-transcript -->\n<sub>🧾 <a href="%s">Full agent transcript</a> (workflow artifact; requires repo access)</sub>' "$URL")"
          if [ -n "$comment_id" ]; then
            gh api "repos/$REPO/issues/comments/$comment_id" --jq .body > /tmp/body.md
            # Idempotent on re-runs: keep the first footer rather than
            # appending one per run.
            if grep -qF "<!-- outfitter-transcript -->" /tmp/body.md; then
              echo "Transcript footer already present; skipping."
              exit 0
            fi
            printf '%s' "$footer" >> /tmp/body.md
            gh api -X PATCH "repos/$REPO/issues/comments/$comment_id" -F body=@/tmp/body.md > /dev/null
          else
            printf '%s' "$footer" | gh issue comment "$ISSUE_NUMBER" --repo "$REPO" --body-file -
          fi

      # A green agent run is not proof of work: the model can exit
      # successfully having done nothing. Assert the side effects —
      # exactly one triage label and a comment. Pinned to a release tag
      # of ai-outfitter/actions.
      - name: Validate triage side effects
        env:
          GH_TOKEN: ${{ github.token }}
        run: |
          # Authenticated fetch: unauthenticated raw.githubusercontent.com
          # requests from runners get 429'd.
          gh api -H "Accept: application/vnd.github.raw" \
            "repos/ai-outfitter/actions/contents/scripts/validate-triage.sh?ref=v1.2.1" \
            > /tmp/validate-triage.sh
          chmod +x /tmp/validate-triage.sh
          /tmp/validate-triage.sh \
            --repo "${{ github.repository }}" \
            --issue "$ISSUE_NUMBER" \
            --labels feat,fix
