Summary
A survey of the four product repos' CI, done while shipping the design-system rollout on 2026-08-18. The governance layer is already uniform. The job layer is not, and some of the divergence is accidental rather than product-driven.
The goal of this issue is to name which jobs should exist everywhere, which are legitimately product-specific, and which are simply drift — so a future session can converge the first group and stop treating the third as intentional.
Already uniform — no action
Verified byte-identical or equal across seed, stem, niac-go and trellis:
pull_request_template.md — identical in all four.
pr-body-lint.yml — identical. Same required headings, same Fixes|Closes|Resolves|Related to #N rule, same "Testing Evidence needs a fenced block or an explicit not-run reason", same bot exemption.
- PR title lint — present in all four.
- Required status checks —
CI Complete, Lint PR Title, Lint PR Body in all four.
- Merge queue — enabled in all four.
release-please.yml — same workflow_run-gated-on-CI-success wiring in all four.
- Shared building blocks from this repo —
apt-install, semgrep.yml, and the ci-conformance check that keeps them honest.
So the PR and issue process is one process with four instances. Nothing to harmonize there.
The job matrix
✓ present · — absent · bold = the gap worth closing
| Job |
seed |
stem |
niac-go |
trellis |
Verdict |
| Changed paths |
✓ |
✓ |
✓ |
— |
should be everywhere — it is what lets a docs-only PR skip cleanly |
| Backend (Go) |
✓ |
✓ |
✓ |
✓ |
universal, done |
| Backend (race detector) |
✓ |
✓ |
✓ |
— |
should be everywhere |
| Frontend |
✓ |
✓ |
✓ |
✓ |
universal, done |
| Quality Checks |
✓ |
✓ |
✓ |
✓ |
universal, done |
| Semgrep SAST |
✓ |
✓ |
✓ |
✓ |
universal, done |
| CI Conformance |
✓ |
✓ |
✓ |
✓ |
universal, done |
| Security Scanning |
✓ |
✓ |
✓ |
— |
should be everywhere |
| govulncheck |
in Security |
in Security |
in Security |
standalone |
harmonize the shape, not the coverage |
| Workflow Lint |
✓ |
✓ |
✓ |
— |
should be everywhere |
| Documentation Quality |
✓ |
✓ |
✓ |
— |
should be everywhere |
| Build Verification |
✓ |
✓ |
✓ |
— |
should be everywhere |
| Build UI (shared artifact) |
✓ |
✓ |
— |
— |
an optimization — niac-go rebuilds the UI per job for no reason |
| i18n Validation |
✓ |
✓ |
✓ |
— |
correct: trellis deliberately ships no i18n (see #54) |
| E2E Browser Tests |
✓ |
✓ |
✓ |
— |
trellis has none at all — trellis#57 |
| E2E Smoke (separate fast job) |
✓ |
— |
— |
— |
worth adopting: it is the job that gives a fast signal before the sharded suite |
| Storybook interactions + a11y |
✓ |
— |
— |
n/a |
stem has 39 stories and niac-go has 19 that no CI ever renders |
| C Lint (C23) |
✓ |
✓ |
— |
— |
seed has zero .c/.h files — this job lints nothing |
| Dataplane Safety (ASAN + fuzz) |
— |
✓ |
— |
— |
correct: stem owns the C dataplane (40 C sources) |
| Darwin compile check |
— |
✓ |
— |
— |
correct: stem's CGO/darwin path is real |
Should be everywhere — accidental gaps
trellis is missing seven jobs the other three run: Changed paths, race detector, Security Scanning, Workflow Lint, Documentation Quality, Build Verification, and E2E. None of these absences is a product decision; trellis is simply younger. Its ci.yml is 7 jobs against seed's 18.
This is not cosmetic. trellis was the only repo that passed the design rollout without a single CI failure — not because its changes were safer, but because almost nothing was checking.
Genuinely product-specific — leave alone
- Dataplane Safety (ASAN + fuzz) and Darwin compile check — stem only. stem is the only repo with a C dataplane and a CGO/darwin build path. Correct as-is.
- i18n Validation absent from trellis — deliberate, recorded in #54: trellis ships no i18n subsystem, and standing one up for a single page fails the feature-scope gate. Revisit when trellis gains locales, not before.
Drift to correct
- seed runs
C Lint (C23) with zero C sources. find . -name '*.c' -o -name '*.h' returns nothing in seed. The job either lints an empty set or is a copy from stem. Delete it, or state what it is meant to cover.
- Storybook CI is seed-only, but stem and niac-go have stories. 39 and 19 respectively, none of them rendered by CI. Either run the job in all three or delete the stories — untested stories rot silently, and the fleet has already been bitten by that class of thing.
Build UI (shared artifact) is missing in niac-go, so its jobs rebuild the frontend independently. Pure waste.
- govulncheck is standalone in trellis, folded into Security Scanning elsewhere. Same coverage, different shape; converge for readability.
Related defects already filed
These came out of the same survey and are tracked separately:
- Playwright browser install has no retry, flakes
exit 100 — seed#1950, stem#661, niac-go#1341
- A flaky CI run on
main silently skips release-please — stem#662 (all four share the wiring)
- PRs leave the merge queue after successful
merge_group runs — stem#664
- E2E locators match accessible names by substring — stem#663, niac-go#1344
- trellis has no Playwright coverage — trellis#57
One correction, so nobody chases it
There was a suspicion that stem failed to merge because of a permissions/rights difference between repos. That is not what happened, and it is worth recording plainly:
gh pr merge --admin on stem#660 was refused by the agent's own tool-permission policy, which blocks bypassing branch protection. It was not a GitHub rights error, and the repo's settings were never the obstacle — the PR merged normally once re-enqueued through the merge queue.
There is no evidence of any rights asymmetry between the four repos. The real merge-queue oddity is stem#664.
Suggested order
- Bring trellis up to the fleet baseline (the seven missing jobs), largest gap and lowest risk.
- Delete or justify seed's
C Lint.
- Decide Storybook: run it in stem and niac-go, or remove the stories.
- Add
Build UI (shared artifact) to niac-go and converge trellis's govulncheck shape.
- Consider promoting seed's split
E2E Smoke job to the others — a fast signal before the sharded suite is worth having everywhere.
Steps 2–5 are small. Step 1 is the one that changes the fleet's actual risk profile.
Summary
A survey of the four product repos' CI, done while shipping the design-system rollout on 2026-08-18. The governance layer is already uniform. The job layer is not, and some of the divergence is accidental rather than product-driven.
The goal of this issue is to name which jobs should exist everywhere, which are legitimately product-specific, and which are simply drift — so a future session can converge the first group and stop treating the third as intentional.
Already uniform — no action
Verified byte-identical or equal across seed, stem, niac-go and trellis:
pull_request_template.md— identical in all four.pr-body-lint.yml— identical. Same required headings, sameFixes|Closes|Resolves|Related to #Nrule, same "Testing Evidence needs a fenced block or an explicit not-run reason", same bot exemption.CI Complete,Lint PR Title,Lint PR Bodyin all four.release-please.yml— sameworkflow_run-gated-on-CI-success wiring in all four.apt-install,semgrep.yml, and theci-conformancecheck that keeps them honest.So the PR and issue process is one process with four instances. Nothing to harmonize there.
The job matrix
✓present ·—absent · bold = the gap worth closing.c/.hfiles — this job lints nothingShould be everywhere — accidental gaps
trellis is missing seven jobs the other three run: Changed paths, race detector, Security Scanning, Workflow Lint, Documentation Quality, Build Verification, and E2E. None of these absences is a product decision; trellis is simply younger. Its
ci.ymlis 7 jobs against seed's 18.This is not cosmetic. trellis was the only repo that passed the design rollout without a single CI failure — not because its changes were safer, but because almost nothing was checking.
Genuinely product-specific — leave alone
Drift to correct
C Lint (C23)with zero C sources.find . -name '*.c' -o -name '*.h'returns nothing in seed. The job either lints an empty set or is a copy from stem. Delete it, or state what it is meant to cover.Build UI (shared artifact)is missing in niac-go, so its jobs rebuild the frontend independently. Pure waste.Related defects already filed
These came out of the same survey and are tracked separately:
exit 100— seed#1950, stem#661, niac-go#1341mainsilently skips release-please — stem#662 (all four share the wiring)merge_groupruns — stem#664One correction, so nobody chases it
There was a suspicion that stem failed to merge because of a permissions/rights difference between repos. That is not what happened, and it is worth recording plainly:
gh pr merge --adminon stem#660 was refused by the agent's own tool-permission policy, which blocks bypassing branch protection. It was not a GitHub rights error, and the repo's settings were never the obstacle — the PR merged normally once re-enqueued through the merge queue.There is no evidence of any rights asymmetry between the four repos. The real merge-queue oddity is stem#664.
Suggested order
C Lint.Build UI (shared artifact)to niac-go and converge trellis's govulncheck shape.E2E Smokejob to the others — a fast signal before the sharded suite is worth having everywhere.Steps 2–5 are small. Step 1 is the one that changes the fleet's actual risk profile.