feat: add label commands (task 0015) #15

Merged
alexion merged 2 commits from task-0015-label-commands into main 2026-07-14 09:32:47 -04:00
Owner

Implements .claude/tasks/0015-label-commands.md.

Summary

Adds the label command group — label list, label create, label edit, label delete — to the CLI, following the sibling issue/pr command patterns.

  • label list (--limit, default 500): count line + labels: block of names, with the explicit empty state.
  • label create --name --color (optional --description): prepends # to the color, idempotent via a case-insensitive existence check (create: already_exists instead of failing).
  • label edit <name> / label delete <name>: resolve the positional name via the standard case-insensitive lookup, VALIDATION_ERROR when not found; delete is deliberately not idempotent (ADR 0010).

Shared reuse: extracted findLabel/resolveLabel/labelNotFound into src/lookup.ts (reused by the existing resolveLabelIds), a flat-output renderObject into src/render.ts, and a parseSinglePositional helper into src/flags.ts.

Deviations (see the task file's Implementation Notes for the full list):

  • label edit requires at least one change (empty PATCH refused), mirroring issue edit.
  • The create: already_exists vs created: ok key split and the flat top-level output shape are both spec-mandated (spec lines 342–343), not free choices.
  • label list uses a single-page --limit fetch (reading X-Total-Count) rather than exhaustive pagination; the spec asks only for --limit.

All 330 unit tests pass (8 new in test/label.test.ts, written test-first).

Review

Risk

Overall: Low

  • Blast radius: Low — new label.ts plus additive helpers; the only existing-code touch is extracting labelNotFound, wired via one line in cli.ts.
  • Reversibility: Low — pure addition, no schema or persisted state.
  • Test coverage: Low (well-covered) — list/create/edit/delete incl. idempotency, color-hash, unknown-name rejection with no-mutation assertions.
  • Sensitive domain: Low — no auth/permissions/concurrency; delete is user-driven and guarded by explicit name resolution.
  • Size & complexity: Low — flat, linear handlers following the existing pattern.
  • Runtime criticality: Low — dev-facing CLI tooling.

Unaddressed findings

Standards:

  • create vs created output-key split in label create — kept: spec-mandated (spec lines 342–343 fix both keys), not the already: true shape the dependency no-ops use.
  • New renderObject (flat top-level fields) vs the sibling renderDetail (nests under a noun: block) — kept: the label outputs are flat sibling fields per the spec, a shape renderDetail cannot produce.

Spec: none.

(The other two Standards findings — the parsePositionalName duplication and the LABEL_LIST_FIELDS typing style — were fixed in this diff.)

Implements `.claude/tasks/0015-label-commands.md`. ## Summary Adds the `label` command group — `label list`, `label create`, `label edit`, `label delete` — to the CLI, following the sibling `issue`/`pr` command patterns. - `label list` (`--limit`, default 500): count line + `labels:` block of names, with the explicit empty state. - `label create --name --color` (optional `--description`): prepends `#` to the color, idempotent via a case-insensitive existence check (`create: already_exists` instead of failing). - `label edit <name>` / `label delete <name>`: resolve the positional name via the standard case-insensitive lookup, `VALIDATION_ERROR` when not found; delete is deliberately not idempotent (ADR 0010). Shared reuse: extracted `findLabel`/`resolveLabel`/`labelNotFound` into `src/lookup.ts` (reused by the existing `resolveLabelIds`), a flat-output `renderObject` into `src/render.ts`, and a `parseSinglePositional` helper into `src/flags.ts`. Deviations (see the task file's Implementation Notes for the full list): - `label edit` requires at least one change (empty PATCH refused), mirroring `issue edit`. - The `create: already_exists` vs `created: ok` key split and the flat top-level output shape are both spec-mandated (spec lines 342–343), not free choices. - `label list` uses a single-page `--limit` fetch (reading `X-Total-Count`) rather than exhaustive pagination; the spec asks only for `--limit`. All 330 unit tests pass (8 new in `test/label.test.ts`, written test-first). ## Review ### Risk **Overall: Low** - Blast radius: Low — new `label.ts` plus additive helpers; the only existing-code touch is extracting `labelNotFound`, wired via one line in `cli.ts`. - Reversibility: Low — pure addition, no schema or persisted state. - Test coverage: Low (well-covered) — list/create/edit/delete incl. idempotency, color-hash, unknown-name rejection with no-mutation assertions. - Sensitive domain: Low — no auth/permissions/concurrency; delete is user-driven and guarded by explicit name resolution. - Size & complexity: Low — flat, linear handlers following the existing pattern. - Runtime criticality: Low — dev-facing CLI tooling. ### Unaddressed findings Standards: - `create` vs `created` output-key split in `label create` — kept: spec-mandated (spec lines 342–343 fix both keys), not the `already: true` shape the dependency no-ops use. - New `renderObject` (flat top-level fields) vs the sibling `renderDetail` (nests under a `noun:` block) — kept: the label outputs are flat sibling fields per the spec, a shape `renderDetail` cannot produce. Spec: none. (The other two Standards findings — the `parsePositionalName` duplication and the `LABEL_LIST_FIELDS` typing style — were fixed in this diff.)
alexion added 1 commit 2026-07-14 07:25:02 -04:00
feat: add label commands (task 0015)
Some checks failed
CI / test (pull_request) Failing after 38s
0bf914cbdd
alexion added 1 commit 2026-07-14 07:35:57 -04:00
test: add label e2e coverage and fixture-tier backfill (task 0015)
Some checks failed
CI / test (pull_request) Successful in 50s
CI / test (push) Has been cancelled
03937a8f6e
alexion merged commit 03937a8f6e into main 2026-07-14 09:32:47 -04:00
alexion deleted branch task-0015-label-commands 2026-07-14 09:32:47 -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#15