labctl pr view: include the PR discussion comment thread #191

Closed
opened 2026-07-21 02:25:31 +02:00 by dominik.polakovics · 0 comments

Problem

An agent has no way to READ a PR's discussion comments through labctl. labctl pr view <n> renders number/title/state/head/url/body/reviews — but not the comment thread, even though the write path exists (labctl pr comment, POST /agent/v1/prs/{n}/comments). Meanwhile labctl issue view shows its full thread. A fix agent or lander that needs to catch up on PR conversation (verdict findings, human replies) is blind.

The plumbing already exists below the API layer: tracker.PullComments(ctx, n) (tracker.go:408) is implemented by all backends (forgejo, github, builtin, secretscan passthrough, instrumentation) and is already read internally by the autoland poller (afk/autoland.go:107) and reaper.

Design (grilled 2026-07-21)

  1. CLI: fold comments into labctl pr view <n> — no new verb. Issue/PR symmetry: issue view shows its thread, so does pr view.
  2. API: extend GET /agent/v1/prs/{n} (prDetailResponse, agentapi/handlers.go:752) with a comments array. No separate GET endpoint. Same contract as reviews: always marshals as [], never null. Same no-partial-detail rule: if the PullComments read fails, the whole response fails through writeTrackerError (handlePRGet, handlers.go:818).
  3. Content: raw, unfiltered — every discussion comment verbatim, autoland verdict-marker comments included. The reject body IS the findings a fix agent needs; no server-side filtering or annotation.
  4. Scope: discussion comments only (what PullComments returns). Inline file/line-anchored review comments stay out of scope — no tracker-interface change.

Implementation

  • internal/agentapi/handlers.go: in handlePRGet, after the Reviews read, call tk.PullComments(r.Context(), n); map into a commentResponse (author, body, createdAt — mirror the issue-view comment JSON shape) appended to prDetailResponse as comments. Non-nil slice so zero comments marshals [].
  • internal/labctl/client.go: add Comments []IssueComment-style field to PRDetail (reuse/mirror the existing issue comment client type).
  • internal/labctl/labctl.go: in printPR (line 615), render comments after the reviews block, oldest first, byte-for-byte the printIssue convention: --- comment by <author> (<time>). Update the usage text line for pr view to show PR n (…, body, reviews, comments).
  • Update the generated-context template that documents the labctl surface (the source that produces CLAUDE.local.md's labctl section) so agents learn pr view includes the thread.
  • Tests: handler test for GET /agent/v1/prs/{n} asserting comments present, [] on empty, ordering oldest-first, and whole-response failure when PullComments errors; labctl render test for the comment block.

Semantics notes

  • Built-in binding: a PR shares its issue's comment space, so pr view's thread equals issue view's thread there — consistent with the documented write-path semantics (handlers.go:1230), not a bug.
  • pr list stays PullRef-cheap — no comment count added.
## Problem An agent has no way to READ a PR's discussion comments through labctl. `labctl pr view <n>` renders number/title/state/head/url/body/reviews — but not the comment thread, even though the write path exists (`labctl pr comment`, POST `/agent/v1/prs/{n}/comments`). Meanwhile `labctl issue view` shows its full thread. A fix agent or lander that needs to catch up on PR conversation (verdict findings, human replies) is blind. The plumbing already exists below the API layer: `tracker.PullComments(ctx, n)` (tracker.go:408) is implemented by all backends (forgejo, github, builtin, secretscan passthrough, instrumentation) and is already read internally by the autoland poller (afk/autoland.go:107) and reaper. ## Design (grilled 2026-07-21) 1. **CLI**: fold comments into `labctl pr view <n>` — no new verb. Issue/PR symmetry: `issue view` shows its thread, so does `pr view`. 2. **API**: extend GET `/agent/v1/prs/{n}` (`prDetailResponse`, agentapi/handlers.go:752) with a `comments` array. No separate GET endpoint. Same contract as `reviews`: always marshals as `[]`, never null. Same no-partial-detail rule: if the `PullComments` read fails, the whole response fails through `writeTrackerError` (handlePRGet, handlers.go:818). 3. **Content**: raw, unfiltered — every discussion comment verbatim, autoland verdict-marker comments included. The reject body IS the findings a fix agent needs; no server-side filtering or annotation. 4. **Scope**: discussion comments only (what `PullComments` returns). Inline file/line-anchored review comments stay out of scope — no tracker-interface change. ## Implementation - `internal/agentapi/handlers.go`: in `handlePRGet`, after the `Reviews` read, call `tk.PullComments(r.Context(), n)`; map into a `commentResponse` (author, body, createdAt — mirror the issue-view comment JSON shape) appended to `prDetailResponse` as `comments`. Non-nil slice so zero comments marshals `[]`. - `internal/labctl/client.go`: add `Comments []IssueComment`-style field to `PRDetail` (reuse/mirror the existing issue comment client type). - `internal/labctl/labctl.go`: in `printPR` (line 615), render comments after the reviews block, oldest first, byte-for-byte the `printIssue` convention: `--- comment by <author> (<time>)`. Update the usage text line for `pr view` to `show PR n (…, body, reviews, comments)`. - Update the generated-context template that documents the labctl surface (the source that produces CLAUDE.local.md's labctl section) so agents learn `pr view` includes the thread. - Tests: handler test for GET `/agent/v1/prs/{n}` asserting `comments` present, `[]` on empty, ordering oldest-first, and whole-response failure when `PullComments` errors; labctl render test for the comment block. ## Semantics notes - Built-in binding: a PR shares its issue's comment space, so `pr view`'s thread equals `issue view`'s thread there — consistent with the documented write-path semantics (handlers.go:1230), not a bug. - `pr list` stays PullRef-cheap — no comment count added.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
Cloonar/coding-lab#191
No description provided.