feat: add issue delete, pin, and unpin (task 0006) #7

Merged
alexion merged 1 commits from task-0006-issue-delete-pin-unpin into main 2026-07-12 19:12:01 -04:00
Owner

Task: .claude/tasks/0006-issue-delete-pin-unpin.md

Summary

Adds the remaining simple issue mutations:

  • issue delete <n> — hard-deletes via the DELETE endpoint. Deliberately not idempotent: a nonexistent issue yields ISSUE_NOT_FOUND (exit 1) rather than reporting a deletion that never happened (ADR 0010). Output: issue: { number, status: "deleted" }.
  • issue pin <n> / issue unpin <n> — read the current pin state and short-circuit to an idempotent no-op (Already pinned / Already unpinned, exit 0) when there is nothing to do. Output: issue: { number, state, pinned }.

Pin state is derived from Gitea's pin_order field (positive = pinned) via a small isPinned helper — Gitea has no boolean pinned flag on the issue struct. issue lock/unlock, transfer, and subissue remain excluded per the spec.

Fixture-server tests cover delete success, delete-missing refusal, and both pin/unpin no-ops (plus the happy paths and --help). Full unit suite: 197 passing.

Deviations

  • issue delete runs no confirmation prompt. This is an agent-facing CLI with structured TOON output where interactive prompts don't fit, and the spec specifies a hard, non-idempotent delete without one. Left unguarded by design.
  • issuePin/issueUnpin are kept as two near-identical functions per the repo's established one-function-per-subcommand convention (as issueClose/issueReopen already do).

Review

Risk

Overall: High

  • Blast radius — Low: confined to src/commands/issue.ts plus two new test files; new switch cases don't alter existing paths.
  • Reversibility — Medium: code rollback is trivial, but issue delete performs an irreversible hard delete of remote data (ADR 0010 confirms non-idempotent).
  • Test coverage — Low: delete and pin/unpin each have fixture-server tests covering success, no-op/missing, and --help.
  • Sensitive domain — High: issueDelete is a destructive data-deletion operation with no confirmation prompt.
  • Size & complexity — Low: three small, near-parallel handlers with linear control flow.
  • Runtime criticality — Medium: user-facing CLI wrapping the Gitea API, not a server hot path.

The High rating is inherent to the hard-delete operation, not a code defect. See the deviation note above for why no --yes guard was added.

Standards & Spec findings left unaddressed

  • Standards (judgement call): issuePin/issueUnpin are near-identical mirrors — Duplicated Code. Left as-is because the repo's one-function-per-subcommand convention (issueClose/issueReopen) overrides the baseline smell.

No Spec findings.

Task: `.claude/tasks/0006-issue-delete-pin-unpin.md` ## Summary Adds the remaining simple issue mutations: - `issue delete <n>` — hard-deletes via the DELETE endpoint. Deliberately **not** idempotent: a nonexistent issue yields `ISSUE_NOT_FOUND` (exit 1) rather than reporting a deletion that never happened (ADR 0010). Output: `issue: { number, status: "deleted" }`. - `issue pin <n>` / `issue unpin <n>` — read the current pin state and short-circuit to an idempotent no-op (`Already pinned` / `Already unpinned`, exit 0) when there is nothing to do. Output: `issue: { number, state, pinned }`. Pin state is derived from Gitea's `pin_order` field (positive = pinned) via a small `isPinned` helper — Gitea has no boolean `pinned` flag on the issue struct. `issue lock`/`unlock`, `transfer`, and `subissue` remain excluded per the spec. Fixture-server tests cover delete success, delete-missing refusal, and both pin/unpin no-ops (plus the happy paths and `--help`). Full unit suite: 197 passing. ### Deviations - `issue delete` runs no confirmation prompt. This is an agent-facing CLI with structured TOON output where interactive prompts don't fit, and the spec specifies a hard, non-idempotent delete without one. Left unguarded by design. - `issuePin`/`issueUnpin` are kept as two near-identical functions per the repo's established one-function-per-subcommand convention (as `issueClose`/`issueReopen` already do). ## Review ### Risk **Overall: High** - Blast radius — Low: confined to `src/commands/issue.ts` plus two new test files; new switch cases don't alter existing paths. - Reversibility — Medium: code rollback is trivial, but `issue delete` performs an irreversible hard delete of remote data (ADR 0010 confirms non-idempotent). - Test coverage — Low: delete and pin/unpin each have fixture-server tests covering success, no-op/missing, and `--help`. - Sensitive domain — High: `issueDelete` is a destructive data-deletion operation with no confirmation prompt. - Size & complexity — Low: three small, near-parallel handlers with linear control flow. - Runtime criticality — Medium: user-facing CLI wrapping the Gitea API, not a server hot path. The High rating is inherent to the hard-delete operation, not a code defect. See the deviation note above for why no `--yes` guard was added. ### Standards & Spec findings left unaddressed - **Standards (judgement call):** `issuePin`/`issueUnpin` are near-identical mirrors — Duplicated Code. Left as-is because the repo's one-function-per-subcommand convention (`issueClose`/`issueReopen`) overrides the baseline smell. No Spec findings.
alexion added 1 commit 2026-07-12 19:02:31 -04:00
feat: add issue delete, pin, and unpin (task 0006)
All checks were successful
CI / test (pull_request) Successful in 29s
CI / test (push) Successful in 32s
7a41807a8a
Add the remaining simple issue mutations. `issue delete` hard-deletes via
the DELETE endpoint and is deliberately not idempotent — a nonexistent
issue yields ISSUE_NOT_FOUND rather than reporting success. `issue pin`
and `issue unpin` read the current pin state (Gitea's pin_order field) and
short-circuit to an idempotent no-op with an Already pinned/unpinned
message when there is nothing to do.
alexion merged commit 7a41807a8a into main 2026-07-12 19:12:01 -04:00
alexion deleted branch task-0006-issue-delete-pin-unpin 2026-07-12 19:12:01 -04:00
Sign in to join this conversation.
No Reviewers
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: alexion/gitea-axi#7