## What & why
The runner's `capacity` was raised to 2. The six CI jobs have no `needs:` between them, so they already schedule concurrently now — this PR makes that safe and tidy rather than enabling it.
- **Keep the two memory-heavy jobs apart.** `verify-stack` now `needs: [mutation]` — not a data dependency, but so Stryker and the full-stack-bring-up + Playwright browser never run at once on the one host and re-trigger the e2e OOM (#126, commit d5e5fa2). `if: ${{ !cancelled() }}` keeps verify-stack running even when the mutation ratchet fails, so we don't lose its signal, while still honouring cancellation.
- **Light jobs stay dependency-free** (lint / build / unit / frontend) → they parallelise up to runner capacity.
- **Supersede stale runs** via a workflow `concurrency` group, so a new push cancels the previous run and frees the slot instead of piling up.
Net effect at capacity 2: the light jobs pair up (and overlap `mutation`), then `verify-stack` runs alone — shorter wall-clock, no heavy-heavy collision.
Closes #127
## Definition of Done
- [x] Linked issue (#127).
- [x] Conventional Commit referencing it.
- [ ] CI green — this PR **is** the test: it exercises `needs`, `if: !cancelled()`, and the `concurrency` group on Gitea. Watch that (a) verify-stack starts only after mutation, (b) verify-stack still runs, (c) the workflow parses (concurrency accepted).
- [x] No app/docs/ADR impact (CI-only).
## Notes for reviewers
- **One thing to watch on this first run:** if this Gitea version doesn't support the top-level `concurrency` key, drop that hunk — the `needs`/`if` guard is the load-bearing part and is plain job-graph syntax.
- **Cross-run collisions** (two different PRs' `verify-stack` on the 2-capacity runner) aren't controllable via intra-workflow `needs`. If that becomes a problem, the clean fix is a second runner (or a dedicated capacity-1 label for the stack job) rather than ordering — out of scope here.
Reviewed-on: #128