Skip to content

ci(review): fold real-world test evidence into the PR review comment via the gaia-testing skill (strix-halo) #2413

Open

Description

@itomek

Problem

GAIA's automated PR review (claude.yml → claude-run.yml) posts a comment based only on reading the diff — it never runs the code, because it executes on ubuntu-latest under pull_request_target with secrets in scope (running fork code there would leak them) and has no Lemonade/GPU. Meanwhile the real tests (test_*.yml, some on self-hosted strix-halo via install-lemonade) run separately and only report pass/fail status checks. The two never meet, so the review comment carries no real-world evidence — exactly what the gaia-testing contract (#2375 / PR #2376) says every change must show.

Outcome

The PR review posts one comment = code review + real test evidence the reviewer evaluated, produced by driving each changed surface through the gaia-testing skill on capable runners. UI/agent surfaces → embedded screenshots; CLI/API/MCP → command output / request traces / tool responses. Automatic for same-repo PRs; all surfaces the PR touches.

Design (primary: two jobs, one comment)

  1. Evidence job (new, in claude.yml) on [self-hosted, strix-halo] for real inference/UI (falls back to ubuntu-latest for pure CLI/API when no inference is needed): brings up the stack via the install-lemonade action + gaia chat --ui, then a Claude-code-action invocation runs the gaia-testing skill against the PR's changed surfaces — Playwright for the Agent UI, CLI/API/MCP per the contract — captures evidence (screenshots → raw …-evidence branch per the skill's raw-URL rule; text traces → an evidence bundle), and uploads the bundle as an artifact.
  2. Review job (existing pr-review) gains needs: the evidence job, downloads the bundle, and its prompt is extended: read the evidence bundle, evaluate it, and fold it into the single review comment (embedding the raw-URL screenshots). It still never executes PR code — it evaluates evidence + diff.

Alternative (if you prefer the literal "one agent tests then reviews"): run the whole review on strix-halo so a single Claude uses the skill to test and then comments — simpler, but couples every review to the self-hosted box's uptime and moves review off cheap ubuntu. Primary keeps review cheap + available.

Acceptance criteria

  • A PR that changes a UI surface gets a review comment with an embedded, rendering Agent UI screenshot (raw.githubusercontent.com) produced by the gaia-testing skill on strix-halo
  • A PR that changes CLI/API/MCP gets the matching text evidence (command+output / request+response / tool call+response) in the same comment
  • Exactly one comment carries both the code review and the evaluated evidence (no second bot comment)
  • Evidence generation invokes the gaia-testing skill (not a hand-rolled reimplementation) so the contract and its extraction stay single-sourced
  • Same-repo PRs run automatically; fork PRs do not execute on self-hosted runners without a maintainer label (untrusted-code gate) — their comment says tests were gated
  • The review job's security boundary is unchanged (it reads evidence + diff, never runs PR code); rubric/skill still sourced from the base branch, never the PR head
  • Surfaces the PR doesn't touch are marked N/A, not silently skipped

Scope & expectations

  • Where: .github/workflows/claude.yml (new evidence job + needs: wiring + review-prompt extension), the install-lemonade action, the gaia-testing skill (add a "CI runner mode" section: strix Windows specifics, evidence sinks that work without R2 secrets on forks, the label gate)
  • Depends on: PR docs(testing): bind real-world evidence contract to the changed surface #2376 (the gaia-testing skill + raw-URL evidence rule) merging first
  • Out of scope: replacing the existing test_*.yml status-check suites; NPU-specific matrices; non-GAIA repos
  • Constraints: do not weaken the pull_request_target boundary; strix-halo is a Windows self-hosted runner (PowerShell, install-lemonade/ensure-lemonade-running.ps1); real-inference runs are slow — keep the evidence run scoped to changed surfaces, not the whole suite

How to verify

Open a throwaway PR touching (a) an Agent UI path and (b) a CLI path; confirm the single review comment embeds a rendering screenshot for the UI change and shows command output for the CLI change, and that the evidence run logs show the gaia-testing skill being invoked on strix-halo. (Same disposable-PR method we used to validate the contract itself.)

Activity

  1. added
    devopsDevOps/infrastructure changes
    testsTest changes
    on Jul 22, 2026
  2. github-actions commented on Jul 23, 2026

    @github-actions
    Contributor

    This is a solid, well-scoped design — the "two jobs, one comment" split (cheap ubuntu review + strix-halo evidence, folded via needs:) is the right call over coupling every review to the self-hosted box's uptime. It's actionable as written. One security nuance worth pinning down explicitly before implementation, plus a couple of grounding notes below.

    The one thing I'd flag: the evidence job is the first place in this pipeline that executes PR-head code (the review jobs only read the diff). On a self-hosted Windows runner that's a real trust boundary — the maintainer-label gate you list handles forks, but the evidence job must also keep secrets out of scope and clean workspace state between runs, since self-hosted runners persist. Worth making that an explicit acceptance criterion. 🔒 cc @kovtcharov-amd since this touches the pull_request_target security model.

    🔍 Technical details

    Grounding against the current files:

    • .github/workflows/claude.yml — the review jobs (pr-review, pr-rereview) don't run inline; they call the reusable claude-run.yml via uses: ./.github/workflows/claude-run.yml (lines ~126, ~375). A needs:-wired evidence job producing an artifact the review job downloads works, but the review job is a reusable-workflow call, not steps: — so the "download bundle + extend prompt" wiring either needs the bundle passed as an input to claude-run.yml or the review job restructured to inline steps. Worth deciding which in the design.
    • The file header (lines 5–6, 47, 67) already documents that pull_request_target runs with base-repo secrets in scope even on fork PRs, and that the workflow file is sourced from base (main). The evidence job inherits that context, so: (a) it must not expose secrets to PR-head test execution, and (b) the "rubric/skill sourced from base branch" criterion is already the established pattern here — good, keep it.
    • install-lemonade action + ensure-lemonade-running.ps1 are the strix-halo (Windows/PowerShell) bring-up path referenced correctly; the many test_*.yml suites stay as status-check sources per the out-of-scope note.
    • Dependency: this correctly blocks on docs(testing): bind real-world evidence contract to the changed surface #2376 (gaia-testing skill + raw-URL evidence rule) — the gaia-testing skill exists at .claude/skills/gaia-testing, so the "invoke the skill, don't reimplement" criterion is enforceable.

    Suggested added acceptance criterion: the evidence job runs PR-head code with no repo secrets in its environment and resets the self-hosted workspace between runs (untrusted-code isolation on a persistent runner).

  3. itomek commented on Jul 23, 2026

    @itomek
    CollaboratorAuthor

    Phase-1 implementation plan (branch tmi/ci-review-evidence set up off main)

    Security architecture (the crux): the evidence job must run the PR's code, so it runs on pull_request (no secrets, read-only token — fork-safe), uploads the evidence as an artifact, and the existing pull_request_target review job (which keeps the secrets and never runs PR code) pulls that artifact and folds it into its single comment. Cross-trigger artifact hand-off is the part that needs CI validation.

    Phase 1 — wiring + CLI/API lane (ubuntu, validatable without strix)

    1. New pr-evidence job (trigger pull_request, runs-on: ubuntu-latest, no secrets): checkout PR head → set up python/gaia → invoke claude-code-action prompted to use the gaia-testing skill to produce evidence only for the CLI/API/MCP surfaces the diff touches → write evidence-bundle.md → actions/upload-artifact.
    2. claude-run.yml: add optional evidence_artifact input; when set, download-artifact into the repo root before the Claude call so the reviewer sees evidence-bundle.md alongside pr-diff.txt.
    3. pr-review job: pass evidence_artifact; extend the prompt — "if evidence-bundle.md is present, evaluate it and fold its evidence (verbatim command output / request traces) into the single review comment; mark untouched surfaces N/A." Boundary unchanged: it reads evidence + diff, never executes PR code.

    Phase 2 — strix-halo UI/agent lane

    pr-evidence gains a self-hosted [self-hosted, strix-halo] variant (label-gated for forks): install-lemonade + gaia chat --ui + headless Playwright via the skill → screenshots pushed to a …-evidence branch (raw-URL rule) → same bundle. Windows/PowerShell specifics per ensure-lemonade-running.ps1.

    Skill: "CI runner mode" section

    Add to gaia-testing (AFTER #2376 merges, to avoid a SKILL.md conflict): the two-runner split, evidence sinks that work without R2 secrets on forks (artifact + raw evidence branch), the label gate.

    Recommended sequencing

    Merge #2376 first (one approval away) so this builds on the final skill and doesn't conflict; then execute Phase 1 and iterate on CI. Same-repo PRs run automatically; fork PRs label-gated for the code-execution job.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    devopsDevOps/infrastructure changestestsTest changes

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions