WI-003: Build the CI gate and GitHub scaffolding
WI-003: Build the CI gate and GitHub scaffolding
Problem
ADR-0015 gives agents full autonomy on a branch and none to merge. That only holds up if the gate is real and main is protected. Without this, “done” stays self-assessed — the failure mode the whole delivery system is designed against.
In scope
.github/workflows/ci.ymlimplementing the gate in../standards/ci-and-gates.md, as far as the current packages allow..github/pull_request_template.mdrequiring gate output and per-line DoD evidence..github/ISSUE_TEMPLATE/work-item.ymlprompting for the spec path, size, area, dependencies..github/labels.ymldefining the closed label vocabulary, applied to the repo.- The docs-diff check (gate step 6) and migration-safety check (step 7).
Out of scope
- Gate steps with no subject yet —
drizzle-kit check(WI-006), Workers tests andwrangler deploy --dry-run(WI-012), the contract check (WI-011). Each is added by the work item that introduces its subject; leave a clearly-marked placeholder. - Neon branch provisioning in CI — WI-006.
- Deployment workflows — WI-004 covers the docs site.
Definition of done
- CI runs on every PR and reproduces
pnpm gatelocally with the same result. - With
core.hooksPathset,git push origin mainis rejected by the pre-push hook — verified by attempting one. Note this is advisory only (ADR-0018); server-side protection is unavailable on private + free, so do not write a DoD line claimingmainis protected. - The label set from
.github/labels.ymlexists on the repo;gh label listmatches it exactly, with no extras. -
gh issue list --label status:readyruns and returns a well-formed (possibly empty) result. - Seeded failure 1: a PR touching
apps/orpackages/with nodocs/change fails the docs-diff step; addingdocs:n-amakes it pass. - Seeded failure 2: a PR containing
DROP COLUMNfails the migration-safety step without themigration:destructivelabel. - Seeded failure 3: a lint error fails the gate.
- The PR template is used by the PR that delivers this item, with real evidence in it.
- Placeholder gate steps are commented with the WI number that will implement them.
Verification
gh label listgh api repos/:owner/:repo/branches/main/protection | jq '.required_status_checks'git push origin main # must be rejectedThen open three throwaway PRs, one per seeded failure above, and confirm each fails for the stated reason and no other. Close them without merging.
Notes
The three seeded failures are the actual deliverable. A gate nobody has watched fail is a gate nobody knows works — this is the same reasoning as WI-002’s negative check, applied to CI.