Files
command-center/agent/managed-skills/gitea-silent-ignore-patch-trap/SKILL.md
T

1.9 KiB

name, description
name description
gitea-silent-ignore-patch-trap Gitea API answers success codes while silently ignoring mutation bodies: labels in PATCH /issues/N, and any JSON body sent without Content-Type: application/json. Verify mutations with a follow-up GET, never the status code.

Gitea silent-ignore family (issue mutations)

Two verified failure modes on the Dankclaw Gitea API (1.27.3, verified live 2026-10-21 on dank/franksign); both return a success code and change nothing:

  1. PATCH /repos/{o}/{r}/issues/{n} with {"labels":[...]} — 200, labels untouched, even with a proper JSON Content-Type. Labels move only via the dedicated endpoints:
    • add: POST /issues/{n}/labels with {"labels":[<id>]}
    • replace: PUT /issues/{n}/labels with {"labels":[ids]} (works without Content-Type)
    • remove: DELETE /issues/{n}/labels/{id}
  2. Any JSON body without header = "Content-Type: application/json" in the curl config — e.g. closing with PATCH {"state":"closed"} returns 201 and no-ops; identical request with the header closes. curl's default -d type (application/x-www-form-urlencoded) makes this silent.

Rules

  • Mutating JSON calls: always send Content-Type: application/json alongside Authorization: token in the same -K config file.
  • Never trust the status code for mutations — follow up with GET and read the field (labels, state). Both traps look like success otherwise.
  • Token stays out of -H args (world-readable /proc/<pid>/cmdline): extract from ~/.config/secrets/gitea into a 600-perm curl config, use -K.

Quick verification idiom

curl -sK "$cfg" "http://192.168.0.143:3000/api/v1/repos/dank/franksign/issues/22" \
  | jq '{state, labels: [.labels[].name]}'

Franksign's vault page franksign-docs/agents/issue-tracker.md owns the repo-local copy of this law; this skill exists so other repos (serverAppConfigs, command-center) don't re-burn the cycle.