feat: add issue blocks and blocked-by (task 0007) #10

Merged
alexion merged 1 commits from task-0007-issue-blocks-blocked-by into main 2026-07-13 19:44:17 -04:00
Owner

Task: .claude/tasks/0007-issue-blocks-blocked-by.md

Summary

Adds the two Gitea-specific dependency subcommand groups over Gitea's blocks/dependencies endpoints:

  • issue blocks <list|add|remove> — the issues this issue blocks (downstream dependents; /issues/{index}/blocks).
  • issue blocked-by <list|add|remove> — the issues that block this issue (upstream blockers; /issues/{index}/dependencies).

Both are one config-parameterised implementation differing only in the endpoint calls and the spec-fixed output names (blocked_issues/blocking_issues for list, blocks/blocked_by for add). add/remove are fetch-first against the fully paginated current set: an existing relationship on add returns already: true with no POST, and a nonexistent issue surfaces as ISSUE_NOT_FOUND before any mutation. Self-reference and cycle rejections come back from Gitea as 422 → VALIDATION_ERROR with the server's message.

Deviations (spec was silent on these):

  • remove output. A real deletion reports removed: true; a no-op removal (relationship already absent) reports already: true instead — mirroring add's no-op and honouring the action/entity-block convention rather than claiming a deletion that did not happen.
  • list row fields are number, title, state — the identifying essentials.

Review

Risk

Overall: Low

  • Blast radius — Low: adds two new self-contained subcommands and dispatch cases to issue.ts; existing paths untouched.
  • Reversibility — Low: pure additive feature, trivially removable; no migrations, deletions, or schema changes.
  • Test coverage — Low: new issue-blocks.test.ts parameterizes both groups across list/add/remove, idempotency, silent-remove, validation, cycle rejection, and help.
  • Sensitive domain — Low: issue dependency links only; no auth, permissions, payments, or data migration.
  • Size & complexity — Medium: ~290 new source lines, but flattened via a single config-parameterized implementation with fetch-first idempotency logic in add/remove worth verifying.
  • Runtime criticality — Low: CLI dev tooling, not a production hot path.

Unaddressed findings

Standards (both judgement calls, intentionally left):

  • Duplicated literals across the two GROUP constants and the test's GROUPS array. Inherent to a spec that fixes different output names per direction; the reviewer agreed the parameterised-config approach is the right call and the duplication is by necessity, not accident.
  • Primitive Obsession (minor): DependencyGroup uses bare string for its config fields. Not worth a domain type for a closed set of only two instances.

Spec: no unaddressed findings — the missing ISSUE_NOT_FOUND test and the remove no-op output convention were both fixed in this change.

Task: `.claude/tasks/0007-issue-blocks-blocked-by.md` ## Summary Adds the two Gitea-specific dependency subcommand groups over Gitea's blocks/dependencies endpoints: - `issue blocks <list|add|remove>` — the issues this issue blocks (downstream dependents; `/issues/{index}/blocks`). - `issue blocked-by <list|add|remove>` — the issues that block this issue (upstream blockers; `/issues/{index}/dependencies`). Both are one config-parameterised implementation differing only in the endpoint calls and the spec-fixed output names (`blocked_issues`/`blocking_issues` for `list`, `blocks`/`blocked_by` for `add`). `add`/`remove` are fetch-first against the fully paginated current set: an existing relationship on `add` returns `already: true` with no POST, and a nonexistent issue surfaces as `ISSUE_NOT_FOUND` before any mutation. Self-reference and cycle rejections come back from Gitea as 422 → `VALIDATION_ERROR` with the server's message. Deviations (spec was silent on these): - **`remove` output.** A real deletion reports `removed: true`; a no-op removal (relationship already absent) reports `already: true` instead — mirroring `add`'s no-op and honouring the action/entity-block convention rather than claiming a deletion that did not happen. - **`list` row fields** are `number`, `title`, `state` — the identifying essentials. ## Review ### Risk **Overall: Low** - Blast radius — Low: adds two new self-contained subcommands and dispatch cases to `issue.ts`; existing paths untouched. - Reversibility — Low: pure additive feature, trivially removable; no migrations, deletions, or schema changes. - Test coverage — Low: new `issue-blocks.test.ts` parameterizes both groups across list/add/remove, idempotency, silent-remove, validation, cycle rejection, and help. - Sensitive domain — Low: issue dependency links only; no auth, permissions, payments, or data migration. - Size & complexity — Medium: ~290 new source lines, but flattened via a single config-parameterized implementation with fetch-first idempotency logic in add/remove worth verifying. - Runtime criticality — Low: CLI dev tooling, not a production hot path. ### Unaddressed findings Standards (both judgement calls, intentionally left): - **Duplicated literals across the two `GROUP` constants and the test's `GROUPS` array.** Inherent to a spec that fixes different output names per direction; the reviewer agreed the parameterised-config approach is the right call and the duplication is by necessity, not accident. - **Primitive Obsession (minor): `DependencyGroup` uses bare `string` for its config fields.** Not worth a domain type for a closed set of only two instances. Spec: no unaddressed findings — the missing `ISSUE_NOT_FOUND` test and the `remove` no-op output convention were both fixed in this change.
alexion added 1 commit 2026-07-13 19:41:43 -04:00
feat: add issue blocks and blocked-by (task 0007)
All checks were successful
CI / test (pull_request) Successful in 35s
CI / test (push) Successful in 35s
6c15e6082f
alexion merged commit 6c15e6082f into main 2026-07-13 19:44:17 -04:00
alexion deleted branch task-0007-issue-blocks-blocked-by 2026-07-13 19:44:17 -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#10