001 — tp issue: issues on the repo's own forge (#21)

Status: shipped (v0.2.0)

Why

Stories link to a tracker issue and close it on release, so every project needs a way to list, create, comment on, edit and close issues from the command line — and, later, from tp story and tp release. Today that is a shell script beside a Claude skill (forgejo-issue.sh) that re-derives the forge, owner, repo and token from the git remote — the same derivation task-plus already does for tp release (internal/forge: host, owner and repo from the remote URL; token via token_env and the secrets provider). The jeeves pilot (jeeves story 001) needed a raw API call to update an issue body because the script cannot edit. One implementation, in Go, tested, is overdue.

Story 002 ships first: tp issue list with the forge and token resolution. This story adds the rest on top of it.

What changes

  • tp issue (from 002) gains list closed|all, show N, create TITLE [-body FILE|-], edit N [-title T] [-body FILE|-], comment N BODY, close N, reopen N.
  • Forge, owner, repo and token resolution as shipped by 002.
  • Forgejo/Gitea API only (/api/v1/repos/{owner}/{repo}/issues). GitHub is a mirror by convention and never holds issues.
  • Output: one line per issue for list (#N [state] title), the body for show, and #N <url> after a write. -json on every subcommand for callers such as tp story.
  • internal/forge gains the remaining issue calls. docs/issue.md extended.

Acceptance

Forge resolution and the token chain are story 002's tables, unchanged.

Commands, with a working forge and token:

Command Effect Prints
list closed / list all GET issues in that state #N [state] title per issue
show N GET issue + comments title, state, body, comments
create POST #N url
edit N PATCH title and/or body #N url
comment N POST comment comment url
close N / reopen N PATCH state `#N -> closed
any write, no token — error naming token_env; nothing sent
any, API non-2xx — error with status and the API's message; exit 1

Out of scope

  • Labels, milestones, assignees, and pull requests.
  • GitHub and GitLab issue APIs.
  • tp story (creating an issue from a story file) and the tp release hook that closes shipped stories — both call tp issue; separate stories.
  • Replacing the forgejo-issue Claude skill's judgement (collecting several issues, deciding one or many); it will call tp issue for the mechanics once this ships.

Decisions

None expected: reusing the release remote's forge resolution is the obvious default. An ADR would be needed only if a project wanted issues on a different forge from its code — none does today.

Done when

  • tests express the acceptance table and pass (API calls against an httptest server)
  • spec updated (docs/issue.md, README command table)
  • ADR written if a fork was resolved
  • roadmap ticked and stamped; changelog entry
  • issue closed with a link to the release