From cf8d08e9850e744d00c166af5f4dacb5d7ae52cc Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 26 Feb 2026 20:20:19 +0000 Subject: [PATCH 1/2] Fix Buildkite detective trigger for status events Switch example workflow trigger to status/check_run failures and add an updated workflow source copy under github/workflows for maintainers to relocate into .github/workflows. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../pr-buildkite-detective/README.md | 5 +- .../pr-buildkite-detective/example.yml | 8 +- .../workflows/gh-aw-pr-buildkite-detective.md | 182 ++++++++++++++++++ 3 files changed, 189 insertions(+), 6 deletions(-) create mode 100644 github/workflows/gh-aw-pr-buildkite-detective.md diff --git a/gh-agent-workflows/pr-buildkite-detective/README.md b/gh-agent-workflows/pr-buildkite-detective/README.md index 0e177d7b..e07d9769 100644 --- a/gh-agent-workflows/pr-buildkite-detective/README.md +++ b/gh-agent-workflows/pr-buildkite-detective/README.md @@ -4,7 +4,7 @@ Analyze failed PR checks backed by Buildkite and report findings (read-only). ## How it works -Triggered automatically when a CI workflow fails on a PR. Looks up the related Buildkite build via MCP, analyzes failed jobs/logs/annotations, and posts a comment with root cause and recommended fixes. Read-only — never pushes changes. +Triggered automatically when a commit status or check run reports a failure. Looks up the related Buildkite build via MCP, analyzes failed jobs/logs/annotations, and posts a comment with root cause and recommended fixes. Read-only — never pushes changes. ## Quick Install @@ -20,7 +20,8 @@ See [example.yml](example.yml) for the full workflow file. | Event | Types | Condition | | --- | --- | --- | -| `workflow_run` | `completed` | CI workflow failed and the run is associated with a PR | +| `status` | N/A | Commit status changed to `failure` | +| `check_run` | `completed` | Check run completed with conclusion `failure` | ## Inputs diff --git a/gh-agent-workflows/pr-buildkite-detective/example.yml b/gh-agent-workflows/pr-buildkite-detective/example.yml index fe6c6d63..85651aa8 100644 --- a/gh-agent-workflows/pr-buildkite-detective/example.yml +++ b/gh-agent-workflows/pr-buildkite-detective/example.yml @@ -1,7 +1,7 @@ name: PR Buildkite Detective on: - workflow_run: - workflows: ["CI", "Build", "Test"] + status: + check_run: types: [completed] permissions: @@ -14,8 +14,8 @@ permissions: jobs: run: if: >- - github.event.workflow_run.conclusion == 'failure' && - toJSON(github.event.workflow_run.pull_requests) != '[]' + (github.event_name == 'status' && github.event.state == 'failure') || + (github.event_name == 'check_run' && github.event.check_run.conclusion == 'failure') uses: elastic/ai-github-actions/.github/workflows/gh-aw-pr-buildkite-detective.lock.yml@v0 with: buildkite-org: "elastic" diff --git a/github/workflows/gh-aw-pr-buildkite-detective.md b/github/workflows/gh-aw-pr-buildkite-detective.md new file mode 100644 index 00000000..c8e8fe47 --- /dev/null +++ b/github/workflows/gh-aw-pr-buildkite-detective.md @@ -0,0 +1,182 @@ +--- +inlined-imports: true +description: "Analyze failed Buildkite PR checks and report findings" +imports: + - gh-aw-fragments/elastic-tools.md + - gh-aw-fragments/runtime-setup.md + - gh-aw-fragments/formatting.md + - gh-aw-fragments/rigor.md + - gh-aw-fragments/mcp-pagination.md + - gh-aw-fragments/messages-footer.md + - gh-aw-fragments/safe-output-add-comment-pr.md + - gh-aw-fragments/network-ecosystems.md +engine: + id: copilot + model: ${{ inputs.model }} +on: + workflow_call: + inputs: + model: + description: "AI model to use" + type: string + required: false + default: "gpt-5.3-codex" + additional-instructions: + description: "Repo-specific instructions appended to the agent prompt" + type: string + required: false + default: "" + setup-commands: + description: "Shell commands to run before the agent starts (dependency install, build, etc.)" + type: string + required: false + default: "" + allowed-bot-users: + description: "Allowlisted bot actor usernames (comma-separated)" + type: string + required: false + default: "github-actions[bot]" + messages-footer: + description: "Footer appended to all agent comments and reviews" + type: string + required: false + default: "" + buildkite-org: + description: "Buildkite organization slug" + type: string + required: false + default: "elastic" + buildkite-pipeline: + description: "Buildkite pipeline slug (optional; auto-discovered from repository if empty)" + type: string + required: false + default: "" + secrets: + COPILOT_GITHUB_TOKEN: + required: true + BUILDKITE_API_TOKEN: + required: true + roles: [admin, maintainer, write] + bots: + - "${{ inputs.allowed-bot-users }}" +concurrency: + group: pr-buildkite-detective-${{ github.run_id }} + cancel-in-progress: false +permissions: + actions: read + contents: read + issues: read + pull-requests: read +tools: + github: + toolsets: [repos, issues, pull_requests, search, actions] + bash: true + web-fetch: +mcp-servers: + buildkite: + url: "https://mcp.buildkite.com/mcp/readonly" + headers: + Authorization: "Bearer ${{ secrets.BUILDKITE_API_TOKEN }}" +network: + allowed: + - "mcp.buildkite.com" +safe-outputs: + activation-comments: false +strict: false +timeout-minutes: 30 +steps: + - name: Repo-specific setup + if: ${{ inputs.setup-commands != '' }} + env: + SETUP_COMMANDS: ${{ inputs.setup-commands }} + run: eval "$SETUP_COMMANDS" +--- + +# PR Buildkite Detective + +Analyze failed Buildkite CI builds for pull requests in ${{ github.repository }}. Identify root causes from build logs, trace failures to source code, and provide actionable fix recommendations via PR comments. This workflow is read-only. + +## Context + +- **Repository**: ${{ github.repository }} +- **Event Name**: ${{ github.event_name }} +- **Event ID**: ${{ github.event_name == 'status' && github.event.id || github.event.check_run.id }} +- **Failure State**: ${{ github.event_name == 'status' && github.event.state || github.event.check_run.conclusion }} +- **Commit SHA**: ${{ github.event_name == 'status' && github.event.sha || github.event.check_run.head_sha }} +- **Buildkite Organization**: ${{ inputs.buildkite-org }} + +## Constraints + +- **CAN**: Read files, search code, run tests and commands, query Buildkite via MCP, comment on PRs +- **CANNOT**: Push changes, merge PRs, or modify `.github/workflows/` + +## Investigation Tools + +Use the right tool for each task: + +- **Buildkite MCP** (`list_pipelines`, `list_builds`, `get_build`, `get_job_logs`, `search_logs`, `tail_logs`, `list_annotations`): Query build information, job logs, and annotations +- **`search_code`**: Search code in *other* public GitHub repositories — use for finding upstream API changes, reference implementations, or migration guides. Use `grep` and file reading for the local codebase. +- **`web-fetch`**: Fetch documentation pages, changelogs, or API references for libraries and tools involved in the failure +- **`bash`**: Run tests locally to verify your analysis, reproduce failures, or check dependency versions + +## Failure Categories + +Classify each failure to guide your investigation: + +- **Code bug**: Logic error, syntax error, type mismatch, nil/null dereference — trace to the specific source file and line +- **Test failure**: Assertion mismatch, test timeout, flaky test — check if the test itself is wrong or if the code under test changed +- **Dependency issue**: Missing package, version conflict, lockfile drift, network fetch failure — check dependency files and lockfiles +- **Infrastructure**: Resource exhaustion, service unavailability, timeout, Docker pull failure — often transient; recommend retry if so +- **Configuration**: Invalid settings, missing secrets/env vars, incorrect paths — check CI config, environment setup, and workflow definitions + +## Instructions + +### Step 1: Gather Context + +1. Call `generate_agents_md` to get the repository's coding guidelines and conventions. If this fails, continue without it. +2. Resolve the failed commit SHA from the triggering event (`github.event.sha` for `status`, `github.event.check_run.head_sha` for `check_run`). +3. Call `list_pull_requests` for the repository (open PRs), then call `pull_request_read` with method `get` on candidates and keep PRs where `head.sha` matches the failed commit SHA. If none match, call `noop` with message "No pull request associated with failed commit status; nothing to do" and stop. +4. For each matching PR, keep author, branches, and fork status for downstream analysis. + +### Step 2: Find the Buildkite Build + +> **If Buildkite MCP is unavailable** (connection error, 401, timeout): The build failure may come from GitHub checks/status contexts outside Buildkite. Fall back to analyzing the failing status/check context directly — use the GitHub API (`pull_request_read` status endpoints), `web-fetch`, or `bash` with `gh` to inspect related checks/jobs. Proceed to Step 3 using whatever evidence is available and note in your comment that Buildkite data was unavailable. + +1. **Resolve the pipeline**: If `${{ inputs.buildkite-pipeline }}` is provided, use it. Otherwise, call `list_pipelines` for organization `${{ inputs.buildkite-org }}` and find the pipeline whose slug matches the repository name (extract the repo name from `${{ github.repository }}`). If multiple pipelines match, prefer an exact slug match. +2. **Find the failed build**: Call `list_builds` for the resolved pipeline, filtering by the failed commit SHA resolved in Step 1. If no match by SHA, use the PR's head branch (from the `pull_request_read` response in Step 1) to filter builds and select the most recent failed one. +3. **Collect failure evidence**: + - Call `get_build` for the matched build to get overall status and job list. + - For each **failed** job: + - `get_job_logs` — retrieve the full log + - `search_logs` with patterns: `error|Error|ERROR`, `failed|Failed|FAILED`, `panic|exception|traceback` + - `tail_logs` — get the last 100 lines (often contains the final error and exit code) + - Call `list_annotations` to capture any warnings, errors, or context the pipeline attached to the build. + +### Step 3: Analyze + +1. **Identify the failure**: Which job(s) and step(s) failed? What is the specific error message or stack trace? +2. **Trace to source code**: Use `grep` and file reading to find the relevant source files. Check recent changes in the PR diff that may have introduced the failure. +3. **Classify the failure**: Use the failure categories above to determine the type. This guides your fix recommendation. +4. **Research if needed**: If the error involves an external library, API, or tool, use `web-fetch` to check documentation or changelogs for known issues, breaking changes, or migration guides. +5. **Propose a fix**: Provide a concrete, minimal fix or remediation plan. If you can run tests locally to verify your theory, do so. +6. **Handle inconclusive cases**: If logs are insufficient to determine root cause, state exactly what additional data is needed and suggest next steps the author can take. + +### Step 4: Respond + +Call `add_comment` on the PR with the following structure: + +**Build**: Link to the Buildkite build + +**What failed**: Which job(s) and step(s) failed + +**Error**: The key error message(s) or stack trace + +**Root cause**: What caused the failure and why (with file paths and line numbers where applicable) + +**Recommended fix**: Specific steps to resolve, with code snippets if applicable + +**Verification**: Tests you ran locally (if any) and their results + +Use `
` blocks for long log excerpts or stack traces to keep the comment scannable. + +${{ inputs.additional-instructions }} From 00d02f330f17058602add8d711fca7b568afebc0 Mon Sep 17 00:00:00 2001 From: William Easton Date: Thu, 26 Feb 2026 14:26:46 -0600 Subject: [PATCH 2/2] move workflow --- .../workflows/gh-aw-pr-buildkite-detective.md | 18 +- .../trigger-pr-buildkite-detective.yml | 8 +- .../workflows/gh-aw-pr-buildkite-detective.md | 182 ------------------ 3 files changed, 14 insertions(+), 194 deletions(-) delete mode 100644 github/workflows/gh-aw-pr-buildkite-detective.md diff --git a/.github/workflows/gh-aw-pr-buildkite-detective.md b/.github/workflows/gh-aw-pr-buildkite-detective.md index 049023a6..c8e8fe47 100644 --- a/.github/workflows/gh-aw-pr-buildkite-detective.md +++ b/.github/workflows/gh-aw-pr-buildkite-detective.md @@ -60,7 +60,7 @@ on: bots: - "${{ inputs.allowed-bot-users }}" concurrency: - group: pr-buildkite-detective-${{ github.event.workflow_run.id }} + group: pr-buildkite-detective-${{ github.run_id }} cancel-in-progress: false permissions: actions: read @@ -99,9 +99,10 @@ Analyze failed Buildkite CI builds for pull requests in ${{ github.repository }} ## Context - **Repository**: ${{ github.repository }} -- **Workflow Run ID**: ${{ github.event.workflow_run.id }} -- **Conclusion**: ${{ github.event.workflow_run.conclusion }} -- **Commit SHA**: ${{ github.event.workflow_run.head_sha }} +- **Event Name**: ${{ github.event_name }} +- **Event ID**: ${{ github.event_name == 'status' && github.event.id || github.event.check_run.id }} +- **Failure State**: ${{ github.event_name == 'status' && github.event.state || github.event.check_run.conclusion }} +- **Commit SHA**: ${{ github.event_name == 'status' && github.event.sha || github.event.check_run.head_sha }} - **Buildkite Organization**: ${{ inputs.buildkite-org }} ## Constraints @@ -133,15 +134,16 @@ Classify each failure to guide your investigation: ### Step 1: Gather Context 1. Call `generate_agents_md` to get the repository's coding guidelines and conventions. If this fails, continue without it. -2. Identify the PRs associated with the workflow run using `github.event.workflow_run.pull_requests`. If there are none, call `noop` with message "No pull request associated with workflow run; nothing to do" and stop. -3. For each PR, call `pull_request_read` with method `get` to capture the author, branches, and fork status. +2. Resolve the failed commit SHA from the triggering event (`github.event.sha` for `status`, `github.event.check_run.head_sha` for `check_run`). +3. Call `list_pull_requests` for the repository (open PRs), then call `pull_request_read` with method `get` on candidates and keep PRs where `head.sha` matches the failed commit SHA. If none match, call `noop` with message "No pull request associated with failed commit status; nothing to do" and stop. +4. For each matching PR, keep author, branches, and fork status for downstream analysis. ### Step 2: Find the Buildkite Build -> **If Buildkite MCP is unavailable** (connection error, 401, timeout): The build failure may come from GitHub Actions CI, not Buildkite. Fall back to analyzing the GitHub Actions workflow run directly — use `web-fetch` to retrieve the run page, `bash` to call `gh run view`, or the GitHub API to read job logs. Proceed to Step 3 using whatever evidence is available and note in your comment that Buildkite data was unavailable. +> **If Buildkite MCP is unavailable** (connection error, 401, timeout): The build failure may come from GitHub checks/status contexts outside Buildkite. Fall back to analyzing the failing status/check context directly — use the GitHub API (`pull_request_read` status endpoints), `web-fetch`, or `bash` with `gh` to inspect related checks/jobs. Proceed to Step 3 using whatever evidence is available and note in your comment that Buildkite data was unavailable. 1. **Resolve the pipeline**: If `${{ inputs.buildkite-pipeline }}` is provided, use it. Otherwise, call `list_pipelines` for organization `${{ inputs.buildkite-org }}` and find the pipeline whose slug matches the repository name (extract the repo name from `${{ github.repository }}`). If multiple pipelines match, prefer an exact slug match. -2. **Find the failed build**: Call `list_builds` for the resolved pipeline, filtering by commit SHA `${{ github.event.workflow_run.head_sha }}`. If no match by SHA, use the PR's head branch (from the `pull_request_read` response in Step 1) to filter builds and select the most recent failed one. +2. **Find the failed build**: Call `list_builds` for the resolved pipeline, filtering by the failed commit SHA resolved in Step 1. If no match by SHA, use the PR's head branch (from the `pull_request_read` response in Step 1) to filter builds and select the most recent failed one. 3. **Collect failure evidence**: - Call `get_build` for the matched build to get overall status and job list. - For each **failed** job: diff --git a/.github/workflows/trigger-pr-buildkite-detective.yml b/.github/workflows/trigger-pr-buildkite-detective.yml index 7c8a2487..9df61b69 100644 --- a/.github/workflows/trigger-pr-buildkite-detective.yml +++ b/.github/workflows/trigger-pr-buildkite-detective.yml @@ -2,8 +2,8 @@ # Edit gh-agent-workflows/pr-buildkite-detective/example.yml and run 'make compile' to regenerate. name: Trigger PR Buildkite Detective on: - workflow_run: - workflows: ["CI", "Build", "Test"] + status: + check_run: types: [completed] permissions: @@ -16,8 +16,8 @@ permissions: jobs: run: if: >- - github.event.workflow_run.conclusion == 'failure' && - toJSON(github.event.workflow_run.pull_requests) != '[]' + (github.event_name == 'status' && github.event.state == 'failure') || + (github.event_name == 'check_run' && github.event.check_run.conclusion == 'failure') uses: ./.github/workflows/gh-aw-pr-buildkite-detective.lock.yml with: buildkite-org: "elastic" diff --git a/github/workflows/gh-aw-pr-buildkite-detective.md b/github/workflows/gh-aw-pr-buildkite-detective.md deleted file mode 100644 index c8e8fe47..00000000 --- a/github/workflows/gh-aw-pr-buildkite-detective.md +++ /dev/null @@ -1,182 +0,0 @@ ---- -inlined-imports: true -description: "Analyze failed Buildkite PR checks and report findings" -imports: - - gh-aw-fragments/elastic-tools.md - - gh-aw-fragments/runtime-setup.md - - gh-aw-fragments/formatting.md - - gh-aw-fragments/rigor.md - - gh-aw-fragments/mcp-pagination.md - - gh-aw-fragments/messages-footer.md - - gh-aw-fragments/safe-output-add-comment-pr.md - - gh-aw-fragments/network-ecosystems.md -engine: - id: copilot - model: ${{ inputs.model }} -on: - workflow_call: - inputs: - model: - description: "AI model to use" - type: string - required: false - default: "gpt-5.3-codex" - additional-instructions: - description: "Repo-specific instructions appended to the agent prompt" - type: string - required: false - default: "" - setup-commands: - description: "Shell commands to run before the agent starts (dependency install, build, etc.)" - type: string - required: false - default: "" - allowed-bot-users: - description: "Allowlisted bot actor usernames (comma-separated)" - type: string - required: false - default: "github-actions[bot]" - messages-footer: - description: "Footer appended to all agent comments and reviews" - type: string - required: false - default: "" - buildkite-org: - description: "Buildkite organization slug" - type: string - required: false - default: "elastic" - buildkite-pipeline: - description: "Buildkite pipeline slug (optional; auto-discovered from repository if empty)" - type: string - required: false - default: "" - secrets: - COPILOT_GITHUB_TOKEN: - required: true - BUILDKITE_API_TOKEN: - required: true - roles: [admin, maintainer, write] - bots: - - "${{ inputs.allowed-bot-users }}" -concurrency: - group: pr-buildkite-detective-${{ github.run_id }} - cancel-in-progress: false -permissions: - actions: read - contents: read - issues: read - pull-requests: read -tools: - github: - toolsets: [repos, issues, pull_requests, search, actions] - bash: true - web-fetch: -mcp-servers: - buildkite: - url: "https://mcp.buildkite.com/mcp/readonly" - headers: - Authorization: "Bearer ${{ secrets.BUILDKITE_API_TOKEN }}" -network: - allowed: - - "mcp.buildkite.com" -safe-outputs: - activation-comments: false -strict: false -timeout-minutes: 30 -steps: - - name: Repo-specific setup - if: ${{ inputs.setup-commands != '' }} - env: - SETUP_COMMANDS: ${{ inputs.setup-commands }} - run: eval "$SETUP_COMMANDS" ---- - -# PR Buildkite Detective - -Analyze failed Buildkite CI builds for pull requests in ${{ github.repository }}. Identify root causes from build logs, trace failures to source code, and provide actionable fix recommendations via PR comments. This workflow is read-only. - -## Context - -- **Repository**: ${{ github.repository }} -- **Event Name**: ${{ github.event_name }} -- **Event ID**: ${{ github.event_name == 'status' && github.event.id || github.event.check_run.id }} -- **Failure State**: ${{ github.event_name == 'status' && github.event.state || github.event.check_run.conclusion }} -- **Commit SHA**: ${{ github.event_name == 'status' && github.event.sha || github.event.check_run.head_sha }} -- **Buildkite Organization**: ${{ inputs.buildkite-org }} - -## Constraints - -- **CAN**: Read files, search code, run tests and commands, query Buildkite via MCP, comment on PRs -- **CANNOT**: Push changes, merge PRs, or modify `.github/workflows/` - -## Investigation Tools - -Use the right tool for each task: - -- **Buildkite MCP** (`list_pipelines`, `list_builds`, `get_build`, `get_job_logs`, `search_logs`, `tail_logs`, `list_annotations`): Query build information, job logs, and annotations -- **`search_code`**: Search code in *other* public GitHub repositories — use for finding upstream API changes, reference implementations, or migration guides. Use `grep` and file reading for the local codebase. -- **`web-fetch`**: Fetch documentation pages, changelogs, or API references for libraries and tools involved in the failure -- **`bash`**: Run tests locally to verify your analysis, reproduce failures, or check dependency versions - -## Failure Categories - -Classify each failure to guide your investigation: - -- **Code bug**: Logic error, syntax error, type mismatch, nil/null dereference — trace to the specific source file and line -- **Test failure**: Assertion mismatch, test timeout, flaky test — check if the test itself is wrong or if the code under test changed -- **Dependency issue**: Missing package, version conflict, lockfile drift, network fetch failure — check dependency files and lockfiles -- **Infrastructure**: Resource exhaustion, service unavailability, timeout, Docker pull failure — often transient; recommend retry if so -- **Configuration**: Invalid settings, missing secrets/env vars, incorrect paths — check CI config, environment setup, and workflow definitions - -## Instructions - -### Step 1: Gather Context - -1. Call `generate_agents_md` to get the repository's coding guidelines and conventions. If this fails, continue without it. -2. Resolve the failed commit SHA from the triggering event (`github.event.sha` for `status`, `github.event.check_run.head_sha` for `check_run`). -3. Call `list_pull_requests` for the repository (open PRs), then call `pull_request_read` with method `get` on candidates and keep PRs where `head.sha` matches the failed commit SHA. If none match, call `noop` with message "No pull request associated with failed commit status; nothing to do" and stop. -4. For each matching PR, keep author, branches, and fork status for downstream analysis. - -### Step 2: Find the Buildkite Build - -> **If Buildkite MCP is unavailable** (connection error, 401, timeout): The build failure may come from GitHub checks/status contexts outside Buildkite. Fall back to analyzing the failing status/check context directly — use the GitHub API (`pull_request_read` status endpoints), `web-fetch`, or `bash` with `gh` to inspect related checks/jobs. Proceed to Step 3 using whatever evidence is available and note in your comment that Buildkite data was unavailable. - -1. **Resolve the pipeline**: If `${{ inputs.buildkite-pipeline }}` is provided, use it. Otherwise, call `list_pipelines` for organization `${{ inputs.buildkite-org }}` and find the pipeline whose slug matches the repository name (extract the repo name from `${{ github.repository }}`). If multiple pipelines match, prefer an exact slug match. -2. **Find the failed build**: Call `list_builds` for the resolved pipeline, filtering by the failed commit SHA resolved in Step 1. If no match by SHA, use the PR's head branch (from the `pull_request_read` response in Step 1) to filter builds and select the most recent failed one. -3. **Collect failure evidence**: - - Call `get_build` for the matched build to get overall status and job list. - - For each **failed** job: - - `get_job_logs` — retrieve the full log - - `search_logs` with patterns: `error|Error|ERROR`, `failed|Failed|FAILED`, `panic|exception|traceback` - - `tail_logs` — get the last 100 lines (often contains the final error and exit code) - - Call `list_annotations` to capture any warnings, errors, or context the pipeline attached to the build. - -### Step 3: Analyze - -1. **Identify the failure**: Which job(s) and step(s) failed? What is the specific error message or stack trace? -2. **Trace to source code**: Use `grep` and file reading to find the relevant source files. Check recent changes in the PR diff that may have introduced the failure. -3. **Classify the failure**: Use the failure categories above to determine the type. This guides your fix recommendation. -4. **Research if needed**: If the error involves an external library, API, or tool, use `web-fetch` to check documentation or changelogs for known issues, breaking changes, or migration guides. -5. **Propose a fix**: Provide a concrete, minimal fix or remediation plan. If you can run tests locally to verify your theory, do so. -6. **Handle inconclusive cases**: If logs are insufficient to determine root cause, state exactly what additional data is needed and suggest next steps the author can take. - -### Step 4: Respond - -Call `add_comment` on the PR with the following structure: - -**Build**: Link to the Buildkite build - -**What failed**: Which job(s) and step(s) failed - -**Error**: The key error message(s) or stack trace - -**Root cause**: What caused the failure and why (with file paths and line numbers where applicable) - -**Recommended fix**: Specific steps to resolve, with code snippets if applicable - -**Verification**: Tests you ran locally (if any) and their results - -Use `
` blocks for long log excerpts or stack traces to keep the comment scannable. - -${{ inputs.additional-instructions }}