chore(devex): route queue triage at Trunk's own reasons - #95249
Conversation
An agent asked why a PR was kicked had no documented way to get Trunk's answer, so it reconstructed one from shadow PRs and the Actions API. That produces a confident narrative that can be wrong on every attempt-level cause: it cannot see a merge conflict, a PR that skipped the line, or a human cancellation, because none of those reach GitHub. `trunk merge status <n>` prints the full state machine with a reason per transition. The triage and merging skills now read that first and use the GitHub side to corroborate. Three places also told agents to watch a `Trunk Merge Queue (master)` check run. The trunk-io app publishes no check runs in this repository, so that predicate matches nothing and reads as "Trunk never picked the PR up" whatever the queue is doing. They now watch Trunk's state instead. Entry 3 of the chart treated every cancelled run as harmless teardown. A job killed by timeout-minutes also reports `cancelled`, never `timed_out`, so an infrastructure outage was classified as "nothing is broken, requeue once". It now separates the two by job duration against the cap. Also records that a shadow PR's ref is named after the batch leader, so a batched PR never appears in a search for its own number while queued.
|
😎 Merged successfully - details. |
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
|
/trunk merge |
🤖 CI report✅ Trunk lane — non-backend laneThis PR is assigned to the non-backend lane. It does not run backend Python tests and may merge in parallel with PRs in other lanes. |
There was a problem hiding this comment.
🟡 Changes recommended
.agents/skills/merging-prs/SKILL.md still contains inconsistent “check run”/details_url guidance in a changed region despite the PR’s shift to trunk merge status as the source of truth.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Pull request overview
This PR updates the repo’s agent/skill documentation to treat trunk merge status <n> as the primary source of truth for merge-queue state and (critically) Trunk’s own “reason” text, replacing prior guidance that referenced a non-existent Trunk Merge Queue (master) check run in this repository.
Changes:
- Update merge-queue triage guidance to start from Trunk’s own transition reasons (
trunk merge status) and only use GitHub artifacts (sticky comment/shadow PR/Actions) for corroboration and log access. - Update merge/babysit guidance to watch Trunk’s state machine rather than a phantom check run, and clarify that PR-head checks don’t reflect queue CI.
- Refine the “cancelled” classification guidance to distinguish infra teardown vs job timeout using job durations.
File summaries
| File | Description |
|---|---|
AGENTS.md |
Removes/clarifies merge-queue progress guidance to reflect that Trunk publishes no check run; points readers to trunk merge status / Trunk bot sticky comment. |
.agents/skills/triaging-merge-queue-failures/SKILL.md |
Reframes “establish the facts” around trunk merge status reasons and documents the three GitHub surfaces (CLI/sticky/shadow PR) and their limitations. |
.agents/skills/merging-prs/SKILL.md |
Updates enqueue confirmation and watch loop to rely on trunk merge status instead of check runs. |
.agents/skills/debugging-ci-failures/SKILL.md |
Updates merge-queue failure targeting guidance to reference trunk merge status rather than a queue check run. |
Review details
Suppressed comments (1)
.agents/skills/merging-prs/SKILL.md:132
- This block still references verifying a "check run" app/identity and using
details_url/ "workflow URL ... from the check run", but the skill no longer uses check runs at all. It should instead point readers to the Trunk terminal transition reason, then to thetrunk-io[bot]sticky comment and/or the shadow PR to locate the GitHub Actions run URL/logs.
Confirm `app` is `trunk-io` — the same identity as the `trunk-io[bot]` commenter. If some other app wrote a check run by that name, stop and report it rather than acting on it.
From there, `details_url` and the workflow runs on Trunk's `trunk-merge/**` branch lead to the real logs. `/debugging-ci-failures` covers reading them.
Optionally, Trunk's MCP server (`https://mcp.trunk.io/mcp`, OAuth or bearer token, org slug `posthog-inc`) has an experimental `investigate-ci-failure` tool that turns a GitHub Actions run URL into structured test failures with quarantined flakes filtered out. It's a convenience, not a dependency — it needs a workflow URL you already have from the check run, it returns nothing when the job failed before tests ran, and it only has data while `TRUNK_UPLOAD_ENABLED` is on. Don't block on it; if it's not authed, read the logs directly.
- Files reviewed: 4/4 changed files
- Comments generated: 2
- Review effort level: Lite
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
There was a problem hiding this comment.
Approved.
Documentation-only fix to internal agent skill files correcting stale/incorrect instructions about querying Trunk's merge-queue state; no code, workflows, or risky-territory surface touched, and the author owns this area.
Gate mechanics and policy version
| Gate | Result | |
|---|---|---|
| prerequisites | ✓ | all clear |
| deny-list | ✓ | no deny categories matched |
| size | ✓ | 0L, 0F substantive, 81L/4F incl. docs/generated/snapshots — within ceiling |
| tier | ✓ | T0 auto-approve: T0-deterministic (81L, 4F, single-area, chore) |
| stamphog 2.0.0b4 | .stamphog/policy.yml @ 18dd4f2 · reviewed head 18dd4f2 |
The failure-handling intro in /merging-prs still keyed on a check run conclusion, which the rest of the skill had just established does not exist here. It now keys on Trunk's terminal state, and says why the distinction matters: a conflict needs a rebase, a failed check needs a fix, a cancellation was a person. Also uses American spelling, per the repo convention.
A new stamphog review started for this PR — the fresh verdict replaces this approval.
There was a problem hiding this comment.
Not approved — escalated to a human reviewer.
Re-add the stamphog label to request another review once you have addressed this.
Copilot's review flagged that .agents/skills/merging-prs/SKILL.md still tells the reader to "confirm app is trunk-io" on a check run and cites details_url, even though the same file now states Trunk publishes no check run at all in this repo — and the current diff leaves that exact paragraph untouched, so the inconsistency Copilot called out is still present on the head commit.
- Unresolved Copilot review comment on .agents/skills/merging-prs/SKILL.md (~line 111-113): the 'Confirm app is trunk-io ... details_url ... from the check run' guidance still presumes a check run exists, contradicting the PR's own premise (stated elsewhere in the same file and in AGENTS.md) that Trunk publishes no check run in this repo. Since this file is an operational runbook agents execute literally, the leftover check-run-based verification step would send an agent looking for something that doesn't exist.
Gate mechanics and policy version
| Gate | Result | |
|---|---|---|
| prerequisites | ✓ | all clear |
| deny-list | ✓ | no deny categories matched |
| size | ✓ | 0L, 0F substantive, 86L/4F incl. docs/generated/snapshots — within ceiling |
| tier | ✓ | T0 auto-approve: T0-deterministic (86L, 4F, single-area, chore) |
| stamphog 2.0.0b4 | .stamphog/policy.yml @ 4a68875 · reviewed head 4a68875 |
Problem
An agent asked why a PR was kicked from the merge queue had no documented way to get Trunk's answer, so it reconstructed one from shadow PRs and the Actions API.
Trunk Merge Queue (master)check run. Thetrunk-ioapp publishes no check runs in this repository, so that predicate matches nothing and reads as "Trunk never picked the PR up" whatever the queue is doing.This came out of a real triage on #93911 that took hours and landed on the wrong causes.
trunk merge statusanswers it in one call.Changes
/triaging-merge-queue-failuresopens withtrunk merge status <n>and says plainly that reconstructing from shadow PRs is the expensive mistake./merging-prswatches Trunk's state instead of a check run that does not exist. Its confirm step, watch loop, and "read the check run, not the PR comments" section all change.cancelled, andconclusion == "timed_out"never matches./debugging-ci-failuresand AGENTS.md drop the same phantom check run.Documentation only. No code, no workflows.
Note
trunk merge statushas no--json;--output json,--jsonand--format jsonare all rejected. The Trunk MCP server has no merge-queue tools at all. So the skill tells an agent to strip ANSI, and to ask a human for the dashboard's JSON export when it cannot run the CLI.How did you test this code?
Verified each claim against the live repo rather than reasoning about it:
What was checked
trunk merge status 93911returns 40 state transitions with a reason each, including the conflict and line-skip reasons that no GitHub API surface carries.trunk*app exists on that PR's head across all pages ofcheck-runs. The phantom predicate returns nothing.Build Packagewascancelledat 605s against a 10 minute cap, which is the timeout shape entry 3 now teaches.hogli ci:preflight --strictpasses. No tests are affected; nothing here is executable.Automatic notifications
🤖 Agent context
Autonomy: Human-driven (agent-assisted)
Written by Claude Code (Opus 5) at @webjunkie's direction, at the end of a session that began as a merge queue investigation and turned into a post-mortem of the investigation's own method.
Skills invoked:
/triaging-merge-queue-failures,/merging-prs,/writing-pr-descriptions,/babysit-pr.The corrections here are ones the session earned the hard way. The first analysis of #93911 attributed its failures to batch teardown and to other PRs' breakage. Trunk's own timeline showed two of them never started testing at all, because of merge conflicts, and that the author's rebases were what Trunk had explicitly asked him for. Every attempt-level cause in that first analysis was wrong.
No customer data or internal systems informed this change. Everything cited is public GitHub and the Trunk CLI.