steward · git:20261107.ef21817 · 2026-11-07 · sha256 bebca0bc7a5aaa82

steward git:20261107.ef21817A

Immutable. This exact content never changes and is served at /api/v1/blob/bebca0bc7a5aaa82.

---
name: steward
description: Drive an mxcli pull request Claude opened to green and merge it. Covers when to open it, the local gate to pass before every push (make ci-local), which CI failure is a known runner flake, how to resolve the conflicts this repo keeps hitting, how to read the AI PR Review comment, and the merge-on-green default. Read before acting on a CI, review or conflict event on such a PR.
---
<!-- skill-index: generated by scripts/skill-index.py; make check-skill-index -->
## Find it fast

`sed -n '<from>,<to>p' SKILL.md` one section rather than reading the file;
`./mxcli syntax <topic>` answers *how do I write this* for a fraction of either.

| lines | section |
|---|---|
| 27-55 | Merge on green is the default |
| 56-73 | Before every push: `make ci-local` |
| 74-88 | Reading a red CI job |
| 89-104 | Conflicts this repo keeps hitting |
| 105-122 | The AI PR Review comment |

<!-- /skill-index -->
# Steward: Driving a PR to Merged

This is a **contributor** skill (dev-only); it is not synced to user projects.
It holds this repository's conventions for the loop after a PR is opened. How
to make the change itself is `/mxcli-dev:fix-issue` and the CLAUDE.md working
rules; this file starts where they stop.

## Merge on green is the default

The user reviews a change **in the session, before the PR exists**. So:

- Open a PR only after the user has seen the change summarized in the session
  and asked for it. Never open one to get a review.
- Once it is open, merge it without asking again as soon as all of these hold
  on the **current head**:
  - every job of `Build, Test & Lint` (`.github/workflows/push-test.yml`) is
    green, `integration-passed` included. That workflow runs once per commit,
    on the pull_request event only (#1886), and a new push cancels the
    previous commit's run: a **cancelled** run on an older head is expected and
    never blocks — only the current head's run counts. A branch push with no
    PR gets no run; trigger one with `workflow_dispatch` if you need it;
  - GitHub reports no merge conflict;
  - no human review thread or changes-requested review is open;
  - no Critical item from the AI PR Review comment is unanswered (see below).
- Merge with a **merge commit** (not squash, not rebase), passing the head SHA
  you checked as `expectedHeadSha`, so a push that lands in between is not
  merged unseen.
- After the merge, unsubscribe from the PR, cancel its pending check-in, and
  restart the working branch from the new main:
  `git fetch origin main && git checkout -B <branch> origin/main`, then push.
  The next PR starts from there; never stack new work on merged history.

Ask instead of merging when a human reviewer has commented or requested
changes, or when the PR is someone else's. Never merge a red head, whatever
the reason it is red.

## Before every push: `make ci-local`

`make build test lint` is a subset of the gate CI applies. `make ci-local`
runs what the `build-and-test` job runs, in its order, minus `govulncheck`.
Run it before the first push and before every push that changes code, and
push only on a clean exit. It takes a while; run it in the background.

- **Formatting:** `make fmt` is the fixer. `fmt-check` uses the toolchain's
  gofmt (`go env GOROOT`), because the gofmt on `PATH` can be an older Go than
  the `toolchain` line in `go.mod`, and its verdict differs from CI's.
- **Integration suites** need mxbuild, so `ci-local` does not run them. When
  the change touches a package with integration tests, run that suite:
  `make test-integration-<executor|roundtrip|parity|upgrade|other>`.
- **When the job gains a step,** add it to `ci-local` in the same PR.
- **A failure in code the change does not touch:** run the same target on
  `origin/main`. If it fails there too, it is main's: fix it in its own PR
  (it can go first), and never skip or disable the test to get past it.

## Reading a red CI job

The workflow is the source of truth for what runs; these are the jobs whose
failures need reading differently.

- **`build-and-test`:** reproduce with `make ci-local`.
- **`integration (<suite>)`:** reproduce with `make test-integration-<suite>`.
- **`tunnel-seam-cross-platform (windows-latest)`:** runs the tunnel seam's
  own tests on Windows (ADR-0009), so a failure is real. The macOS leg runs
  only in the nightly (`tunnel-seam-macos`): its hosted queue often never
  delivers a runner (runner id 0, no step ran, cancelled after ~15 min). If
  that job is red there with no step run, re-run it once; it is no PR's
  concern.
- **`AI PR Review`** is always green: it posts a comment, it does not gate.

## Conflicts this repo keeps hitting

While the PR is open, merge `origin/main` into its head. Do not rebase or
force-push it.

| File | Resolution |
|---|---|
| `CHANGELOG.md` `[Unreleased]` | Keep **both** sides: every entry is one line, so a conflict is two fixes landing at once. Afterwards check for a stray blank line or a duplicated entry. |
| A `SKILL.md` section index | Keep either side, then `make skill-index`. |
| `cmd/mxcli/skills/` | Never resolve by hand: `make sync-skills` regenerates it from `.claude/skills/mendix/`. |
| `docs-site/src/language/versions.md` tables | `make gen-migration-reference`. |
| `mdl/conformance/allowlist.txt` | Take the higher count on each conflicting line, then `make conformance-shrink`, which lowers every count to what the gate finds and never raises one. |
| Bug findings | They do not conflict: each finding is its own new file. |

Run `make ci-local` on the merge result before pushing it.

## The AI PR Review comment

`ai-review.yml` posts **one PR comment** headed `## AI Code Review`, not review
threads. It has sections Critical Issues, Moderate Issues, Minor Issues, What
Looks Good and Recommendation. On a large PR the model sees only a selected
part of the diff, so a claim that something is missing may only mean that file
was outside the selection.

| Section | How to treat it |
|---|---|
| Critical | Blocking. Verify each item against the code: fix and push it, or answer it with the path you traced and why it does not hold. |
| Moderate | A claim to verify, not an order. Fix it when a real caller reaches the failure and the fix is in proportion to it; otherwise say why not. |
| Minor | Optional. Never start a push for one. Carry the plainly correct ones into a push that already touches those files. |

Answer it with **one** PR comment that gives the outcome for each Critical and
Moderate item. Sometimes nothing is posted at all: the workflow skips posting
when its API key is missing or the API call fails, and still reports success.
A missing comment is neither an approval nor a blocker.