--- name: gitea-api-pr-operations description: "\"Open, list, merge, and diagnose issues/PRs on the Dankclaw Gitea API (192.168.0.143:3000, repo dank/command-center) with the token stored in ~/.config/secrets/gitea — incl. the required merge payload, where review comments actually live on 1.27.3, and how to recover the session id for the mandatory body footer.\"" --- # Gitea API PR operations (Dankclaw `dank/command-center`) ## Where - Token: `~/.config/secrets/gitea` (`http://user:TOKEN@192.168.0.143` single line). Extract WITHOUT echoing: `tok=$(sed -nE 's#^http://[^:/@]+:([^@]+)@192\.168\.0\.143.*#\1#p' ~/.config/secrets/gitea | head -1)` - Build a 600-perm temp curl config and use `curl -K`: `cfg=$(mktemp) && chmod 600 "$cfg" && printf 'header = "Authorization: token %s"\n' "$tok" > "$cfg"` Delete `$cfg` after use. NEVER pass `-H "Authorization: token $tok"` (the literal header lands in transcript + logs). NEVER echo the token. - Base URL: `http://192.168.0.143:3000/api/v1/repos/dank/command-center`. ## Recipes (all verified live 2026-10-18) - **Open PR** (token only needed for private repos; this one reads publicly but POST needs auth): `POST /pulls` JSON `{title, head, base:"main", body}`. - **PATCH PR title/body**: `PATCH /pulls/` with JSON body `{title}` and/or `{body}`. Returns 201 with the full PR. Use `jq -n --arg` to build JSON; for multi-line bodies write the text to a temp file and `--arg b "$(cat b.txt)"`. (jq CLI: a bare `---` argument after the program is parsed as a flag → error; fold footers into the --arg string instead.) - **List open PRs**: `GET /pulls?state=open` → `jq -r '.[] | "#\(.number) \(.head.ref) \(.title)"'`. - **Read PR**: `GET /pulls/` (no token; public repo) → `jq -c '{state,merged,mergeable,head:.head.ref}'`. `mergeable:false` is often Gitea's *not-yet-checked* state, not a conflict — prove a real conflict locally with `git merge-tree --write-tree HEAD origin/main` before believing it. - **MERGE**: `POST /pulls//merge` with `-H 'Content-Type: application/json'` and body **`{"Do":"merge"}`** — this build REQUIRES the `Do` field: `{}` or `{"DoNotMerge":false,...}` → 422; `{"Do":"merge"}` → 200 + `{"state":"closed","merged":true,"merge_commit_sha":"..."}`. Verify with a plain GET /pulls/ afterwards (merge endpoint's own stdout may not parse). Merge is the `--no-ff` merge commit on main; then `git -C ~/.omp fetch && git merge --ff-only origin/main` propagates the live deployment. - **Issues**: same shape at `/issues` (`POST {title, body}`), `/issues//comments` (`POST {body}`, `PATCH .../comments/`) — both work with the temp-cfg auth. ## Review comments: the API lies on 1.27.3 (learned 2026-10-18) - `GET /pulls//comments` (inline review comments) → **404 `not found` on every route** (token or not, `?pull_request_id=` or not) even when a review with comments exists. - `GET /pulls//reviews` works (shows `state`, `comments_count`) but bodies are empty. - **The comments are readable from the PR HTML**: `curl -sS http://192.168.0.143:3000/dank/command-center/pulls/ -o /tmp/pr.html` then extract `
` blocks (python: `re.finditer(r'comment-content', src)` → widen ±800 chars, strip tags). Duplicates appear (suggested-change UI shows text twice); dedupe mentally. - Per-conversation resolve API also 404s — flag resolutions in an issue comment instead. ## Body-footer law (AGENTS.md) Every issue/PR body ends with `---` line then `cwd: · session: `. Keep it inside the --arg string (not a `---` CLI arg). `cwd` is THIS session's own working directory (note a build worktree separately if they differ). When `/status` is unreachable (headless/subagent context), recover the session id from the session store instead of inventing one: `ls -t ~/.omp/agent/sessions// | head -2` → `_` (the same uuid as `.jsonl`); the slug is the cwd with `/` replaced by `-`. Subagent files live under the **parent** session's directory, so the newest entry there is the parent id. ## Gotchas - Content-Type: POSTs with `-d @file.json` MUST carry `-H 'Content-Type: application/json'` on the command line. `-H` entries put in the curl config file are ignored for this (header ordering quirk). - `xdg-open ` lands the PR in Frank's Firefox the moment it is opened — law, not courtesy. - `jq: cannot index "not found" with "user"` = endpoint 404'd into an error object; check `-w '%{http_code}'` before blaming jq. - The token in `.git/config`'s remote URL is the same secret; the credential file (`~/.config/secrets/gitea`) is the one git actually consults (global credential.helper) and the one to reuse for API calls.