Files
command-center/agent/managed-skills/gitea-issue-labels-and-pr-curl-traps/SKILL.md
T
Frank 8af40c402b chore(agent): commit the machine tier and the doctrine text the checkout was already running
Landing blocker for #61 and #63: the deployment checkout is 12 commits behind and
`merge --ff-only` refuses while tracked paths are dirty. Discard is not available here
(workspace policy: no `checkout`/`stash` on shared state), so the dirt is committed.

- `agent/APPEND_SYSTEM.md`: the point-of-use / one-work-log / PR-link doctrine, already
  byte-identical to `origin/main` (`cmp` against the trunk blob: no difference). No new
  prose — the commit exists so the trunk merge can proceed.
- `agent/config.yml` and `agent/managed-skills/**`: the machine-live tier the heartbeat
  owns (AGENTS.md § Live-sync tiers).

`ALLOW_SECRETS=1` was used, deliberately and after auditing the staged diff by hand: the
only credential-shaped strings in it are two copies of `AKIA0000000000000EXAMPLE` — the
inert all-zero AWS example id — and they appear inside the two skill pages that teach
that exact placeholder shape. This checkout is still running the pre-#61 hook; the merged
gate (value-scoped placeholder filter, `71601f7`) exempts this value, so the refusal
dies with this landing. No `--no-verify` was used: the gate ran and its verdict is
recorded here.

Refs #61
2026-10-21 01:44:51 -07:00

2.3 KiB
Raw Blame History

name, description
name description
gitea-issue-labels-and-pr-curl-traps Dankclaw Gitea API curl traps: PR create needs Content-Type application/json (fake "[Head]: Required"), issue labels only via POST /issues/N/labels (PATCH labels silently dropped), token from URL-format secret file.

Operate Dankclaw Gitea (http://192.168.0.143:3000, repo dank/franksign and siblings) with curl without the three traps that produce misleading errors.

Token extraction (URL-format store, NOT key=value)

~/.config/secrets/gitea is one line: http://user:TOKEN@192.168.0.143:3000. cat-ing it yields the whole URL, not the token.

TOK=$(sed -n 's|.*://[^:]*:\([^@]*\)@.*|\1|p' ~/.config/secrets/gitea | head -1)

Never pass the token as a -H argument (world-readable in /proc/<pid>/cmdline). Write a 600-perm curl config:

printf 'header = "Authorization: token %s"\n' "$TOK" > /tmp/g.cfg

Trap 1 — PR create answers "[Head]: Required" when the body is the problem

Two independent causes, both look like a missing field:

  1. No Content-Type: application/json header → Gitea parses the raw JSON as form data, sees no head, returns 422 [Head]: Required.
  2. Putting data = "@/tmp/body.json" inside a -K curl config does not expand the @.

Fix: add header = "Content-Type: application/json" to the config and pass --data @/tmp/body.json on the command line:

curl -s -K /tmp/g.cfg -X POST --data @/tmp/pr.json \
  "http://192.168.0.143:3000/api/v1/repos/dank/franksign/pulls"

Trap 2 — issue label assignment via PATCH /issues/N is silently dropped

PATCH /api/v1/repos/{o}/{r}/issues/{n} with {"labels":[id]} returns 200/201 with the issue JSON, yet a follow-up GET shows labels: [] (it can even clear existing labels). Labels are a subresource:

curl -s -K /tmp/g.cfg -X POST --data '{"labels":[4]}' \
  "http://192.168.0.143:3000/api/v1/repos/dank/franksign/issues/18/labels"

200 returns the assigned label array. Resolve label names→ids via GET /repos/{o}/{r}/labels (franksign canonical five: ids 2–6; ready-for-agent = 4).

Verification law

Both traps fail successfully. After any label/PR write, GET the resource and check the field changed; never trust the status code alone.

Cleanup

rm -f the temp config + body files (config holds the token).