The runs produced five green PRs and no way to land them without a person. What makes that safe to automate is not CI — the author writes the tests — but a reviewer in a fresh context: last night's caught two guards that left the whole suite green when deleted, an over-narrow sweep, and an overlay covering the artwork it was editing. So the gate is seven conditions, and a Kind/Feature is never one of them. It can exist at all because a push to main publishes nothing here: release.yml is workflow_dispatch and the four publishers key on v* tags, so a wrong merge costs a revert rather than a package nobody can unpublish. The section says so, and says it is void if that changes.
204 lines
9.3 KiB
Markdown
204 lines
9.3 KiB
Markdown
---
|
|
description: Take on the next actionable backlog issue end to end, and stop
|
|
---
|
|
Take on exactly one issue from the YellowJacket backlog, end to end, and stop.
|
|
|
|
Repo: yonlu/yellowjacket at https://git.ljones.me — API base
|
|
https://git.ljones.me/api/v1/repos/yonlu/yellowjacket, auth with
|
|
`-H "Authorization: token $GITEA_TOKEN"`. Default branch is `main`.
|
|
|
|
## 1. Orient before you pick
|
|
|
|
Read, in this order: `CLAUDE.md` (the architecture and the reasons behind
|
|
it), `.pi/journal.md` (what happened last), `.planning/NOTES.md` (what was
|
|
already considered and rejected), and `.planning/plans/active/`. Do not skip
|
|
this because the issue looks small — most of this codebase's traps are
|
|
written down in exactly one of those four places, and the ones that bite are
|
|
the ones you didn't read.
|
|
|
|
## 2. Pick the issue
|
|
|
|
List open issues. Choose the single highest-value one that is *actionable
|
|
right now*:
|
|
|
|
- Order by `Priority/Critical` → `High` → `Medium` → `Low`. Within a tier,
|
|
prefer `Reviewed/Confirmed`, then `Kind/Bug` over `Kind/Enhancement` over
|
|
`Kind/Feature`.
|
|
- Consult issue #73 (the roadmap) — if it sequences the candidates, that
|
|
ordering wins over the label ordering.
|
|
- **Skip** anything labelled `Status/Blocked`, `Status/In Progress`,
|
|
`Status/Abandoned`, `Reviewed/Won't Fix`, `Reviewed/Duplicate`,
|
|
`Reviewed/Invalid`, or already carrying an open PR.
|
|
- **Skip anything someone else is already on.** The label is not the only
|
|
claim, because a concurrent session may not have applied it — several pi
|
|
sessions run against this repo from separate worktrees under
|
|
`~/.paseo/worktrees/`. Run `git ls-remote --heads origin` and skip any
|
|
issue whose number or slug matches an existing branch (`60-…`,
|
|
`fix/<slug>`). A duplicated fix costs more than a skipped issue.
|
|
- **Skip** anything that cannot be verified without hardware you do not
|
|
have: physical-device Android behaviour (audio output, on-device file
|
|
writes, real gesture input). A browser at 424px is not a phone — see the
|
|
Chrome 113 section of `CLAUDE.md`.
|
|
- **Skip** intermittent-failure issues unless you can reproduce the failure
|
|
on demand within a few minutes. Chasing a 1-in-3 flake is an unbounded
|
|
task and does not belong in a scheduled run.
|
|
- If nothing qualifies, say so, do nothing, and stop. An empty run is a
|
|
correct outcome.
|
|
|
|
## 3. Claim it
|
|
|
|
Add `Status/In Progress` to the issue and comment that you are picking it
|
|
up. Then branch:
|
|
|
|
```
|
|
git fetch origin && git checkout -b <type>/<short-slug> origin/main
|
|
```
|
|
|
|
`<type>` matches the issue's `Kind` (`fix/`, `feat/`, `refactor/`, `test/`,
|
|
`docs/`, `ci/`). Branch from `origin/main`, never by checking out `main`
|
|
itself — this repo is worked from several git worktrees at once and `main`
|
|
is checked out in one of them, so `git checkout main` fails outright.
|
|
|
|
## 4. Do the work
|
|
|
|
Fix the issue that was reported and nothing else. Match the surrounding
|
|
code's style. Follow the constraints in `CLAUDE.md` rather than reasoning
|
|
from first principles — where it explains why something is shaped the way it
|
|
is, that shape is load-bearing and there is usually a test pinning it.
|
|
|
|
**Anything else you discover becomes a new issue, not a bigger diff.** File
|
|
it with the right `Area/`, `Kind/`, `Priority/` labels, describe the
|
|
symptom before the theory, and link it from your PR. Scope creep is the
|
|
failure mode this instruction exists to prevent.
|
|
|
|
If the work turns out to be materially larger than the issue implied, stop:
|
|
comment on the issue with what you found and what it would actually take,
|
|
remove `Status/In Progress`, push nothing, and end the run.
|
|
|
|
## 5. Verify — the right tier, not the cheapest one
|
|
|
|
Run `make generate` if you touched `.sql` or `.templ`, and `make bindings`
|
|
if you changed a bound Go signature. Then run what the change actually
|
|
demands:
|
|
|
|
- Go change → `make lint` and `make test` (both cover all three build
|
|
configurations).
|
|
- Frontend component or store → `make ui-test`.
|
|
- User-visible flow → `make e2e` against `make dev-headless`. **Check the
|
|
port first**: `ss -ltn | grep 34115`. If it is occupied, another worktree
|
|
is already running the app — do not start a second one and do not run
|
|
`make e2e`. Attaching to someone else's build produces a green result
|
|
about code that is not yours, which is worse than no result. Either
|
|
choose an issue that does not need this tier, or stop and say why.
|
|
- Anything cosmetic or layout-related → look at a screenshot. Several bugs
|
|
in this repo's history were invisible to every assertion and obvious in an
|
|
image.
|
|
|
|
A tier you skipped is a claim you did not check. If a tier fails for reasons
|
|
unrelated to your change, say so explicitly rather than quietly moving on.
|
|
|
|
## 6. Keep the documentation true
|
|
|
|
If you changed structure, behaviour, or a constraint, update `CLAUDE.md` in
|
|
the same commit. That file is this project's memory; a change that leaves it
|
|
describing the old shape is worse than no change. Append a short entry to
|
|
`.pi/journal.md` covering what you did, what you verified, and what you left
|
|
open.
|
|
|
|
## 7. Commit and open the PR
|
|
|
|
Conventional Commits, imperative subject, ≤72 chars, scope optional. The
|
|
body explains *why*. Push the branch — never push to `main`, never
|
|
force-push.
|
|
|
|
Open the PR:
|
|
|
|
```
|
|
curl -sS -X POST \
|
|
-H "Authorization: token $GITEA_TOKEN" \
|
|
-H "Content-Type: application/json" \
|
|
https://git.ljones.me/api/v1/repos/yonlu/yellowjacket/pulls \
|
|
-d '{"head":"<branch>","base":"main","title":"<subject>","body":"<body>"}'
|
|
```
|
|
|
|
The body states: what the issue was, what you changed and why, **which
|
|
verification tiers you ran and their results**, anything you deliberately
|
|
did not do, and `Closes #<n>`.
|
|
|
|
Then wait for CI (`ci.yml`, jobs `check` and `e2e`) and report the result on
|
|
the PR. If it fails, read the log — `gitea_ci`'s `job_logs` 404s on this
|
|
Gitea build, so use
|
|
`GET /api/v1/repos/yonlu/yellowjacket/actions/runs/<run>/jobs` for per-step
|
|
status and `GET /api/v1/repos/yonlu/yellowjacket/actions/jobs/<id>/logs` for
|
|
the log — and fix it. Two consecutive failed CI runs on the same cause: stop,
|
|
comment what you know on the PR, and leave it for a human.
|
|
|
|
**Do not merge, and do not review your own work.** Comment on the issue
|
|
linking the PR, leave `Status/In Progress` on, and end the run. Whether
|
|
this merges is decided by a reviewer that did not write it — see below.
|
|
A CI run is not a review: it proves the tests you wrote pass, which is
|
|
exactly the thing an author is worst placed to judge.
|
|
|
|
## Finally
|
|
|
|
Report in three lines: which issue you took, what state it is in
|
|
(PR open / CI green / stopped and why), and any issues you filed.
|
|
|
|
---
|
|
|
|
# The merge gate
|
|
|
|
This half is **not** run by the author. It is run against a PR by
|
|
someone who has not seen the branch before, and it decides whether the
|
|
work lands on its own or waits for a human.
|
|
|
|
A push to `main` publishes nothing here — `release.yml` is
|
|
`workflow_dispatch` only and all four publishers key on `v*` tags — so
|
|
the cost of a wrong merge is a bad commit on `main` and the time to
|
|
revert it. That is the whole reason this gate can exist. If that ever
|
|
changes, this section is void.
|
|
|
|
**Merge only when every one of these is true.** Any single no means
|
|
leave it open.
|
|
|
|
1. An independent review of the diff returns **MERGE** or **MERGE WITH
|
|
NITS**. `CHANGES NEEDED`, or a review that could not reach a verdict,
|
|
means a human looks.
|
|
2. `CI / check (pull_request)` **and** `CI / e2e (pull_request)` are
|
|
`success` on the PR's current head. Ignore the `(push)` contexts —
|
|
they are `skipped` by design and Gitea folds `skipped` into a
|
|
combined state of `pending` that never clears.
|
|
3. The PR is mergeable with no conflicts, rebased onto current `main`.
|
|
4. The diff touches **none** of: `.gitea/workflows/`, `.releaserc.yml`,
|
|
`packaging/`, `build/`, `scripts/gitea-release.sh`,
|
|
`backend/database/sql/schemas/`, `backend/database/staleshape*.go`,
|
|
`go.mod`, `go.sum`. These either publish to somewhere a mistake
|
|
cannot be taken back from, or can destroy a database that a user
|
|
cannot rebuild.
|
|
5. The issue is `Kind/Bug`, `Kind/Testing`, `Kind/Documentation` or
|
|
`Kind/Enhancement`. **A `Kind/Feature` is a design decision and is
|
|
never auto-merged**, however green it is.
|
|
6. The diff is under ~600 changed lines across under ~15 files. Past
|
|
that, "a reviewer read it" stops being a claim anyone should take on
|
|
trust.
|
|
7. The PR does not claim to have verified something no tier here can
|
|
see. A change whose evidence would have to come from a physical
|
|
device is reported, not merged.
|
|
|
|
**When it merges**, use `{"Do":"merge"}` on
|
|
`POST /api/v1/repos/yonlu/yellowjacket/pulls/<n>/merge`. Then **check
|
|
the issue actually closed** — a squash or an edited merge message drops
|
|
the `Closes` footer — and close it by hand with a comment naming the
|
|
commit if it did not. `unclaim.yml` strips `Status/In Progress` on
|
|
close; if the label is still there a minute later, strip it yourself.
|
|
|
|
**When it does not merge**, say so on the PR in one paragraph: which
|
|
condition failed and what would satisfy it. Leave the PR open, leave
|
|
the label on, and file the review's substantive findings as issues so
|
|
they are searchable rather than buried in a PR comment.
|
|
|
|
**A nit is not a blocker, and it is not free either.** A `MERGE WITH
|
|
NITS` merges, and each nit worth keeping becomes an issue. Do not fix
|
|
nits on the branch: that is a second author pass with no second review,
|
|
which is the thing this gate exists to prevent.
|