ci: validate a pull request before it can become a red main #288

Merged
coilysiren merged 2 commits from aos/claude/xu59-pr-ci into main 2026-08-16 04:08:23 +00:00
Member

The gap

This repository had no pull-request CI. release.yml is the only workflow and triggers on push: branches: [main] and workflow_dispatch, so grep -rn pull_request .forgejo/ returned nothing and every pull request showed no checks. Kai noticed it on #287.

Validation did run, but only after the merge, in the same job that tags and publishes. A bad merge landed and took the release pipeline with it.

The other PR-lane repositories all gate against that:

infrastructure    2 of  6 workflows trigger on pull_request
agentic-os        3 of  8
deploy            2 of 25
sirens-echo       1 of  2
agent-compose     0 of  1     <- this

That is the "main is red and the merge lane is paused behind it" failure that coilyco-gaming/sirens-echo has filed three times, in a repository where nothing catches it first.

The workflow

Runs ward exec test, which is exactly what the release job runs, rather than a lighter approximation. A cheaper check that disagrees with the gate is worse than no check, because it reports green on something that fails after merge. That script runs go test ./..., the release-impact and packaging tests, the palette suite, the context budget, evalkit-check, and pre-commit run --all-files.

Three deliberate choices:

  • pull_request only. release.yml already validates every main push. Adding push here would run the whole suite twice per merge.
  • Cancels superseded runs, which release.yml deliberately does not. A superseded pull request has nothing left to prove, a release does.
  • Caches pre-commit environments the way the release job does, since ward exec test ends with pre-commit run --all-files and hook envs dominate a cold run.

No FEATURES entry

The rule excludes CI and build changes from FEATURES, so the entry I first wrote is reverted in the second commit.

Worth flagging separately: docs/FEATURES.md is 3,996 of its 4,000-character cap. Any future entry breaks it. That is a real constraint on the next feature that lands, not something this pull request should fix.

Verification

pre-commit run --all-files passes, including actionlint, forgejo-runner-validate, and actions-run-one-line.

I have not seen this workflow execute, and cannot: it only runs on a pull request, and a workflow added by a pull request does not run on the pull request that adds it. The first real execution will be the next pull request opened after this merges, which is #287.

Order

Independent of #287 and #851. Merging this first means #287 gets checks once rebased.

🤖 Generated with Claude Code

## The gap This repository had **no pull-request CI**. `release.yml` is the only workflow and triggers on `push: branches: [main]` and `workflow_dispatch`, so `grep -rn pull_request .forgejo/` returned nothing and every pull request showed no checks. Kai noticed it on #287. Validation did run, but only **after** the merge, in the same job that tags and publishes. A bad merge landed and took the release pipeline with it. The other PR-lane repositories all gate against that: ``` infrastructure 2 of 6 workflows trigger on pull_request agentic-os 3 of 8 deploy 2 of 25 sirens-echo 1 of 2 agent-compose 0 of 1 <- this ``` That is the "main is red and the merge lane is paused behind it" failure that `coilyco-gaming/sirens-echo` has filed three times, in a repository where nothing catches it first. ## The workflow Runs **`ward exec test`**, which is exactly what the release job runs, rather than a lighter approximation. A cheaper check that disagrees with the gate is worse than no check, because it reports green on something that fails after merge. That script runs `go test ./...`, the release-impact and packaging tests, the palette suite, the context budget, evalkit-check, and `pre-commit run --all-files`. Three deliberate choices: * **`pull_request` only.** `release.yml` already validates every main push. Adding `push` here would run the whole suite twice per merge. * **Cancels superseded runs**, which `release.yml` deliberately does not. A superseded pull request has nothing left to prove, a release does. * **Caches pre-commit environments** the way the release job does, since `ward exec test` ends with `pre-commit run --all-files` and hook envs dominate a cold run. ## No FEATURES entry The rule excludes CI and build changes from FEATURES, so the entry I first wrote is reverted in the second commit. Worth flagging separately: **`docs/FEATURES.md` is 3,996 of its 4,000-character cap.** Any future entry breaks it. That is a real constraint on the next feature that lands, not something this pull request should fix. ## Verification `pre-commit run --all-files` passes, including `actionlint`, `forgejo-runner-validate`, and `actions-run-one-line`. I have not seen this workflow execute, and cannot: it only runs on a pull request, and a workflow added by a pull request does not run on the pull request that adds it. **The first real execution will be the next pull request opened after this merges**, which is #287. ## Order Independent of #287 and #851. Merging this first means #287 gets checks once rebased. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
This repository had no pull-request CI. release.yml is the only workflow
and triggers on push to main and workflow_dispatch, so `grep -rn
pull_request .forgejo/` returned nothing and every pull request showed no
checks.

Validation did run, but only after the merge, in the same job that tags
and publishes. A bad merge landed and took the release pipeline with it,
which is the failure the other PR-lane repositories gate against: of
their workflows, infrastructure has 2 of 6 on pull_request, agentic-os 3
of 8, deploy 2 of 25, sirens-echo 1 of 2. This repository was 0 of 1.

Runs `ward exec test`, which is what the release job runs, rather than a
lighter approximation. A cheaper check that disagrees with the gate is
worse than none, because it reports green on something that will fail
after merge.

pull_request only. release.yml already validates every main push, so
adding push here would run the whole suite twice per merge.

Cancels superseded runs, which release.yml deliberately does not. A
superseded pull request has nothing left to prove and a release does.

Caches pre-commit environments the way the release job does, since
`ward exec test` ends with `pre-commit run --all-files`.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-authored-by: Kai Siren <coilysiren@gmail.com>
Co-authored-by: Claude <noreply@anthropic.com>
docs(features): drop the CI entry, which the rule excludes
All checks were successful
ci / test (pull_request) Successful in 59s
4d68009f86
FEATURES is the coarse inventory of shipped capability and explicitly
excludes CI and build changes. Pull-request validation is one.

It also did not fit: the file was 3,996 of its 4,000 characters before
the entry, so any addition breaks the cap. Worth knowing before the next
feature lands rather than at the next commit.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-authored-by: Kai Siren <coilysiren@gmail.com>
Co-authored-by: Claude <noreply@anthropic.com>
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
coilyco-flight-deck/agent-compose!288
No description provided.