Files
gitea-axi/.claude/tasks/0034-pr-review-anchor-fields.md
alexion 237c10e38b
All checks were successful
CI / test (pull_request) Successful in 53s
feat: surface inline-comment anchor fields on pr view --reviews (task 0034)
Each inline review comment under `pr view <n> --reviews` now renders its
`id` (the handle a reply targets), `resolved` (`yes`/`no`, from whether
Gitea populated the comment's `resolver`), and `diff_hunk`. The hunk is
structurally trimmed to its `@@` header line plus its last two lines by
default (hunks of three lines or fewer are left whole) and emitted
verbatim under `--full`, so the trim never touches the char-based body
truncation path. The raw `position`/`original_position` diff offsets stay
unsurfaced. The fields ride the existing reviews-plus-per-review-comments
fetch — no extra API calls.
2026-07-18 15:46:30 -04:00

3.7 KiB

spec
spec
pr-review-comments

What to build

Extend pr view <n> --reviews so each inline review comment carries the anchoring information an agent needs to answer and reply to it without a second API call. Each inline-comment row gains three fields: id (the comment's own id, the handle replies target), diff_hunk, and resolved (yes/no, derived client-side from whether the comment's resolver user is populated).

diff_hunk renders with a bespoke structural trim, distinct from the char-based body truncation: by default the hunk's @@ header line plus its last two lines, collapsed when the hunk is three lines or fewer. This keeps both the file-line anchor (the header) and the code at the comment (the tail). Under --full the entire diff_hunk is emitted verbatim — the hunk is never run through the body char-truncation path.

The raw position / original_position diff offsets are deliberately not surfaced. These fields ride the existing --reviews fetch (reviews list plus one inline-comments fetch per review); no extra API calls are introduced.

Acceptance criteria

  • Each inline-comment row under --reviews renders id, diff_hunk, and resolved
  • resolved is yes when the comment's resolver is populated and no otherwise
  • Default diff_hunk shows the @@ header line plus the hunk's last two lines; a hunk of three lines or fewer renders in full
  • --full emits the entire diff_hunk verbatim, with no char-truncation applied to it
  • Raw position / original_position are not rendered
  • No additional API calls beyond the existing reviews-plus-per-review-comments fetch
  • Fixture-server tests drive pr view N --reviews and --full against reviews and inline comments carrying id, diff_hunk, and a set/unset resolver, asserting the rendered id, trimmed-vs-full diff_hunk, and resolved: yes/no

Implementation Notes

  • The structural trim lives in src/diff.ts as a pure trimDiffHunk(hunk) beside truncateDiff: for a hunk longer than three lines it returns the first (@@ header) line plus the last two lines joined by newline; three lines or fewer is returned unchanged. buildReviewRows in src/commands/pr.ts calls it for the default path and passes diff_hunk verbatim under --full, so the hunk never touches the char-based body-truncation path.
  • The inline-comment row's field order is id, author, path, resolved, diff_hunk, body, which is the TOON table header the tests assert against.
  • resolved is comment.resolver ? "yes" : "no" — a truthiness check on the SDK's optional resolver user, matching the spec's "set / not set" derivation.
  • No fresh RED for the resolved: yes, --full-verbatim, and ≤3-line-full cases: the cohesive trimDiffHunk helper (and the resolver truthiness branch) implemented in the first GREEN already covered them, so their tests were green on arrival. Each was proven non-vacuous with a sentinel-probe swap (per the TDD skill) and kept as a regression guard rather than dropped.
  • No new API calls: the three fields ride the existing reviews-plus-per-review-comments fan-out that --reviews already performs.

Review follow-ups (/review-uncommitted), both addressed in this branch:

  • Standards flagged id: comment.id ?? 0 as fabricating an identifier — the very handle a reply copies into reply_to. Replaced with a reviewCommentId helper that throws UNKNOWN on a missing id, mirroring the repo's existing pullNumber/headSha "never invent an identifier" convention.
  • Spec flagged the exactly-four-line trim boundary (the shortest hunk the <= 3 guard actually trims) as untested. Added a regression test for it; a <= 4 off-by-one would now fail.