Add `pr review <n>` with the three action switches --approve,
--request-changes, and --comment, plus --body/--body-file. Exactly one
action flag is required; zero or multiple raise VALIDATION_ERROR before
any API call, mirroring the merge shorthand-conflict rule. Body
requirements are left to Gitea: a body-less event it rejects surfaces its
422 as VALIDATION_ERROR carrying the server's message. Output is
`review: { number, action }`.
2.7 KiB
spec, blocked-by
| spec | blocked-by |
|---|---|
| gitea-axi | 0001-scaffold-and-issue-list-core |
What to build
pr review <n> with the three action flags --approve, --request-changes, --comment, plus --body/--body-file.
Exactly one action flag is required: zero or multiple yield VALIDATION_ERROR before any API call, mirroring the merge shorthand-conflict rule.
Body requirements are not pre-validated locally — if Gitea rejects a body-less review event, its 422 surfaces as VALIDATION_ERROR with the server's message.
Output: review: { number, action }.
Acceptance criteria
- Each action flag submits the corresponding review event and outputs
review: { number, action } - Zero action flags, or more than one, yield
VALIDATION_ERROR(exit 2) with no API call - A server-side 422 for a missing body surfaces as
VALIDATION_ERRORcarrying Gitea's message --body-fileworks as everywhere else- Fixture-server tests cover all three actions, the flag-count validations, and the 422 passthrough
Implementation Notes
pr review follows the established pr merge/pr comment shape: resolveReviewAction
collects the set of action switches (--approve/--request-changes/--comment) mapped
through the REVIEW_ACTIONS record and raises VALIDATION_ERROR when the count is not
exactly one — the direct analogue of resolveMergeMethod's conflicting-selector rule the
spec references, adapted from "at most one (with a default)" to "exactly one (no default)".
The action flag count is settled before createClient, so an invalid invocation never
reaches the API. The body flows through the shared resolveBodySource, so --body/
--body-file and their mutual exclusion behave as everywhere else, and no body requirement
is pre-validated locally: a body-less event Gitea rejects returns 422, which the shared
classifyHttpError already maps to VALIDATION_ERROR carrying the server's message.
Deviations from the literal spec, both deliberate:
- The success block appends a
pr view <n> --reviewssuggestion line viarenderDetail'shelp. The spec's output contract names onlyreview: { number, action }; the extra hint is the house style every sibling mutation command (merge,edit,close, …) already follows, so it was kept for consistency rather than trimmed to the bare contract. - A named
ReviewActioninterface was introduced in place of a repeated inline{ event; action }shape, following a Standards-axis review nit — it matches the local convention of naming such types (MergeMethod,UpdateStyle).
Built test-first via the test-driven-development skill (test-writer sub-agent, one
behavior per RED→GREEN cycle); test/pr-review.test.ts holds 10 tests. Full suite: 311
passing, typecheck clean.