feat: add pr list (task 0008) #8

Merged
alexion merged 1 commits from task-0008-pr-list into main 2026-07-12 19:50:28 -04:00
Owner

Task: .claude/tasks/0008-pr-list.md

Summary

Adds pr list, introducing the two policies later PR slices reuse:

  • Client-side filtering (ADR 0005) — --assignee, --base, --head, --draft have no Gitea query param, so the whole set is paginated (50/page) and filtered in-process, with the count line's total taken from the filtered set rather than the misleading X-Total-Count.
  • reviewDecision via parallel review fetches (ADR 0006) — a new src/review.ts module computes the official-first fallback and maps it to the three lowercase values approved/changes_requested/required (no none). pr list fetches one review list per rendered PR in parallel.

API-supported flags map to their params (--state, --authorposter, --label name→ID, --label-id, --sort with the six Gitea values, --limit, --fields). --search is refused with a redirect to search prs. Default fields: number, title, state, author, draft (bool→yes/no), review; extras: body, createdAt, labels, milestone, mergedAt, url.

Also adds a boolText field extractor and a shared parsePositiveInt helper (the latter also adopted by issue list's --limit, collapsing three copies into one).

Deviations

  • reviewDecision lives in its own module so pr view/dashboard can reuse it later.
  • --label-id accepts a comma-separated list and may be combined with --label — a strict superset of the single-value spec, no change for the single-value case.
  • The url extra field plucks html_url, matching issue list's precedent.

Review

Risk

Overall: MEDIUM

  • Blast radius — Low: new src/review.ts plus a self-contained prList handler and one boolText helper; only shared surface is fields.ts, purely additive.
  • Reversibility — Low: additive-only new command/file; dropping the list dispatch case reverts cleanly, no schema/API commitment.
  • Test coverage — Low: test/pr-list.test.ts covers defaults, filters, sort, label resolution, --fields, --search refusal, and every reviewDecision branch.
  • Sensitive domain — Medium: reviewDecision encodes branch-protection/approval semantics; the official-first fallback lets an unofficial approval read as approved in unprotected repos (display-only but security-adjacent).
  • Size & complexity — Medium: ~370 non-test lines with paginate-then-filter, parallel review fetches, and enum/label parsing; well-factored.
  • Runtime criticality — Low: dev-facing read-only CLI listing command.

Standards — unaddressed findings

  • --search guard and per-command flag tables duplicate issue list (judgement call, kept): the repo deliberately keeps the two list commands as parallel siblings, so the mirrored parse/query/filter shape is the established style, not accidental duplication. The one true logic duplication the review flagged — positive-integer/--limit parsing — was fixed (now parsePositiveInt in flags.ts).

Spec — unaddressed findings

  • Comma-separated --label-id (scope creep, kept): spec describes --label-id <id> as a single value; comma support mirrors --label and is a harmless strict superset.
  • Combining --label + --label-id (scope creep, kept): spec doesn't mention combining them; concatenating the resolved IDs is harmless and never changes single-flag behaviour.
Task: `.claude/tasks/0008-pr-list.md` ## Summary Adds `pr list`, introducing the two policies later PR slices reuse: - **Client-side filtering** (ADR 0005) — `--assignee`, `--base`, `--head`, `--draft` have no Gitea query param, so the whole set is paginated (50/page) and filtered in-process, with the count line's total taken from the filtered set rather than the misleading `X-Total-Count`. - **reviewDecision via parallel review fetches** (ADR 0006) — a new `src/review.ts` module computes the official-first fallback and maps it to the three lowercase values `approved`/`changes_requested`/`required` (no `none`). `pr list` fetches one review list per rendered PR in parallel. API-supported flags map to their params (`--state`, `--author`→`poster`, `--label` name→ID, `--label-id`, `--sort` with the six Gitea values, `--limit`, `--fields`). `--search` is refused with a redirect to `search prs`. Default fields: `number`, `title`, `state`, `author`, `draft` (bool→yes/no), `review`; extras: `body`, `createdAt`, `labels`, `milestone`, `mergedAt`, `url`. Also adds a `boolText` field extractor and a shared `parsePositiveInt` helper (the latter also adopted by `issue list`'s `--limit`, collapsing three copies into one). ### Deviations - `reviewDecision` lives in its own module so `pr view`/dashboard can reuse it later. - `--label-id` accepts a comma-separated list and may be combined with `--label` — a strict superset of the single-value spec, no change for the single-value case. - The `url` extra field plucks `html_url`, matching `issue list`'s precedent. ## Review ### Risk **Overall: MEDIUM** - Blast radius — Low: new `src/review.ts` plus a self-contained `prList` handler and one `boolText` helper; only shared surface is `fields.ts`, purely additive. - Reversibility — Low: additive-only new command/file; dropping the `list` dispatch case reverts cleanly, no schema/API commitment. - Test coverage — Low: `test/pr-list.test.ts` covers defaults, filters, sort, label resolution, `--fields`, `--search` refusal, and every reviewDecision branch. - Sensitive domain — Medium: `reviewDecision` encodes branch-protection/approval semantics; the official-first fallback lets an unofficial approval read as `approved` in unprotected repos (display-only but security-adjacent). - Size & complexity — Medium: ~370 non-test lines with paginate-then-filter, parallel review fetches, and enum/label parsing; well-factored. - Runtime criticality — Low: dev-facing read-only CLI listing command. ### Standards — unaddressed findings - **`--search` guard and per-command flag tables duplicate `issue list` (judgement call, kept):** the repo deliberately keeps the two list commands as parallel siblings, so the mirrored parse/query/filter shape is the established style, not accidental duplication. The one true logic duplication the review flagged — positive-integer/`--limit` parsing — was fixed (now `parsePositiveInt` in `flags.ts`). ### Spec — unaddressed findings - **Comma-separated `--label-id` (scope creep, kept):** spec describes `--label-id <id>` as a single value; comma support mirrors `--label` and is a harmless strict superset. - **Combining `--label` + `--label-id` (scope creep, kept):** spec doesn't mention combining them; concatenating the resolved IDs is harmless and never changes single-flag behaviour.
alexion added 1 commit 2026-07-12 19:24:10 -04:00
feat: add pr list (task 0008)
All checks were successful
CI / test (pull_request) Successful in 30s
CI / test (push) Successful in 31s
6333058b72
Implements `pr list` with the two policies later PR slices reuse:
client-side filtering with the filtered-set count line (ADR 0005) and
the official-first reviewDecision via parallel per-PR review fetches
(ADR 0006), extracted into src/review.ts.

API-supported flags map to their params (--state, --author→poster,
--label name→ID, --label-id, --sort, --limit, --fields); --assignee,
--base, --head, and --draft filter in-process after full pagination,
with the count line's total taken from the filtered set. --search is
refused with a redirect to `search prs`.

Adds a boolText field extractor and a shared parsePositiveInt helper,
the latter also adopted by issue list's --limit parsing.
alexion merged commit 6333058b72 into main 2026-07-12 19:50:28 -04:00
alexion deleted branch task-0008-pr-list 2026-07-12 19:50:28 -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#8