# Issue tracker: Gitea (self-hosted) Issues and specs for this repo live as issues on Gitea (`https://git.crkc.xyz/Apps/ImageApi`). Use the `tea` CLI for all operations. ## Conventions - **Create an issue**: `tea issues create --title "..." --description-file -` (read the body from a heredoc on stdin), or `--description "..."` for a one-liner. Add labels at creation with `--labels "..."` (the labels must already exist — see below). - **Read an issue**: `tea issues --comments`. Use `tea issues list -f index,title,body,labels,comments -o json` for machine-readable output. - **List issues**: `tea issues list --state open` (default state is open) with appropriate `--labels` / `--keyword` filters. - **Comment on an issue**: `tea comments add "..."` (alias: `tea comments "..."`). - **Apply / remove labels**: `tea issues edit --add-labels "..."` / `--remove-labels "..."`. - **Labels must exist first.** Neither `issues create --labels` nor `issues edit --add-labels` creates a missing label: an unknown name is **silently dropped** — the command succeeds and the issue ends up unlabelled (verified against this server, tea 0.16). Check with `tea labels list`; create with `tea labels create --name "..." --color "#rrggbb" --description "..."`, then apply. After labelling, confirm it stuck (`tea issues `). The triage labels (`triage-labels.md`) and the `wayfinder:*` labels below all exist; any new label must be created before first use. - **Close**: `tea issues close `. It does not accept a closing comment, so post the explanation first with `tea comments add "..."`, then close. - **Raw API access** (for anything the `tea` subcommands don't cover): `tea api ` makes an authenticated request to the Gitea API (prefixes `/api/v1/` when the path doesn't start with `/api/`). Placeholders `{owner}` and `{repo}` are replaced from the current repo context. Use `-F` for typed fields (numbers, booleans) and `-d` for raw JSON bodies. Infer the repo from the `git remote` (`-R` lets `tea` discover the Gitea login from the remote); `tea` does this automatically when run inside a clone. Confirm the acting user with `tea whoami`. Unlike GitHub, Gitea numbers issues and pull requests separately, so a bare `#42` is unambiguous once you know which surface it refers to. ## Pull requests as a triage surface **PRs as a request surface: no.** _(Set to `yes` if this repo treats external PRs as feature requests; `/triage` reads this flag.)_ When set to `yes`, PRs run through the same labels and states as issues, using the `tea pulls` equivalents (`tea pulls list/view/edit`, `tea pulls close`, plus `tea comments` which covers PRs). Keep only PRs from outside collaborators (drop the repo owner and team members) when listing external PRs for triage. ## When a skill says "publish to the issue tracker" Create a Gitea issue. ## When a skill says "fetch the relevant ticket" Run `tea issues --comments`. ## Wayfinding operations Used by `/wayfinder`. The **map** is a single issue with **child** issues as tickets. - **Map**: a single issue labelled `wayfinder:map`, holding the Notes / Decisions-so-far / Fog body. `tea issues create --title "..." --labels wayfinder:map --description-file -`. - **Child ticket**: an issue carrying `Part of #` at the top of its description, labelled `wayfinder:` (`research`/`prototype`/ `grilling`/`task`). Once claimed, the ticket is assigned to the driving dev. - **Blocking**: Gitea's **native issue dependencies** (enabled on this server), the canonical, UI-visible representation. Add an edge with `tea api --method POST repos/{owner}/{repo}/issues//dependencies -d '{"index": , "owner": "", "repo": ""}'` (201 on success). Gotchas, verified against Gitea 1.27: - The route is `.../dependencies` — there is **no** `blocked_by` subpath (that 404s). - The JSON body **must** name the blocker's repo (`owner` + `repo`); omitting them yields a misleading `404 repository does not exist` even though the child's path is correct. - `index` is the visible `#number`, not an internal database id. Verify with `tea api repos/{owner}/{repo}/issues//dependencies` (lists blockers); remove with `--method DELETE` and the same body. Where dependencies aren't available, fall back to a `Blocked by: #, #` line at the top of the child description. A ticket is unblocked when every blocker is closed. - **Frontier query**: list the map's open children (issues whose description carries `Part of #`), drop any with an open blocker (dependency or `Blocked by` line) or an assignee; first in map order wins. - **Claim**: `tea issues edit --add-assignees ` (the session's first write; `` from `tea whoami`). - **Resolve**: `tea comments add ""`, then `tea issues close `, then append a context pointer (gist + link) to the map's Decisions-so-far.