--- name: gitea-merge-form-encoded description: "Use when a Gitea API merge on Dankclaw (192.168.0.143:3000) returns HTTP 422 \"[Do]: Required\" — the merge endpoint needs form-encoded fields, not the JSON body that PR creation accepts." --- Gitea on Dankclaw (192.168.0.143:3000, `dank/serverAppConfigs`) — merge quirk, measured 2026-10-19. Creating a PR accepts a JSON body. **Merging does not**: `POST /api/v1/repos/{owner}/{repo}/pulls/{n}/merge` with a JSON body (`{"merge_style":"no-ff", "Do-Not-Reply-From":…, "Reply-To":…}`) or with those values as request headers returns `422 {"message":"[Do]: Required"}` — four variants of that all fail identically, so do not "fix" it by changing the style name or moving the headers around. Working call (form-encoded): ```bash tok=$(sed -n 's|http://[^:]*:\([^@]*\)@.*|\1|p' ~/.config/secrets/gitea | head -1) # git credential.helper store file curl -sS -X POST -K <(printf 'header = "Authorization: token %s"\n' "$tok") \ --data-urlencode 'do=merge' \ --data-urlencode 'merge_style=no-ff' \ --data-urlencode 'Do-Not-Reply-From=chief@franksdank.cloud' \ --data-urlencode 'Reply-To=chief@franksdank.cloud' \ http://192.168.0.143:3000/api/v1/repos/dank/serverAppConfigs/pulls//merge # 200 with an empty body == merged ``` - `do=merge` is the field the 422 was demanding (the web-UI form field name, not an API doc field). - `merge_style` values are the dashed names: `no-ff`, `merge`, `rebase`, `squash`. - Keep the token out of argv: `-K <(printf …)` feeds the `Authorization` header through stdin (a `-H "Authorization: token …"` lands in `/proc//cmdline`, world-readable — the 2026-09-16 HF-token leak class). - Verify by fast-forwarding a checkout (`git fetch && git merge --ff-only origin/main`) rather than re-reading the PR. - Fleet law still applies: never merge without an explicit current OK from Frank, and open the PR URL in his browser (`xdg-open`) the moment it exists.