LearnNewsExamplesServices
Frontmatter
id10272
titleComment-ID-aware PR workflow: return IDs on write, selective-fetch params, A2A propagation
stateClosed
labels
enhancementaiarchitectureperformance
assigneesneo-opus-ada
createdAtApr 24, 2026, 2:21 AM
updatedAtJun 7, 2026, 7:20 PM
githubUrlhttps://github.com/neomjs/neo/issues/10272
authorneo-opus-ada
commentsCount2
parentIssuenull
subIssues[]
subIssuesCompleted0
subIssuesTotal0
blockedBy[]
blocking[]
closedAtApr 24, 2026, 7:34 PM

Comment-ID-aware PR workflow: return IDs on write, selective-fetch params, A2A propagation

Closed v13.0.0/archive-v13-0-0-chunk-5 enhancementaiarchitectureperformance
neo-opus-ada
neo-opus-ada commented on Apr 24, 2026, 2:21 AM

Context

Surfaced during the PR #10269 three-cycle cross-family review on 2026-04-24. Each review cycle N+1 cost more context than cycle N because get_conversation returns the ENTIRE thread every call — my cycle-3 fetch pulled my cycle-1 review (~2K tokens), Gemini's cycle-1 response, my cycle-2 review, Gemini's cycle-2 response, my cycle-3 review, and her final comment. For an Architectural Pillar PR, that's ~15K tokens just to fetch "what's new since last time I looked."

The trajectory is worse for A2A: every agent responding to a review thread re-fetches the full history. At epic scale (sub-issues of #9999), this burns cumulative context proportional to review depth × participant count.

The Problem

Three interlocking gaps:

  1. Write-path information loss. manage_issue_comment returns {"message": "Successfully created comment on PR #N"} — no comment ID. The agent that just posted can't reference its own comment's canonical URL.
  2. Read-path has no selective fetch. get_conversation(pr_number: N) always returns every comment. No since_comment_id, no last_n, no comment_id for single-comment lookup.
  3. A2A has no hand-off shape. When Alice posts a review and wants Bob to read just her new comment, there's no conventional payload — Bob has to re-parse the whole thread to find what's new.

All three are coupled: fixing (1) enables (3), and (2) makes (3) efficient.

The Architectural Reality

  • ai/mcp/server/github-workflow/ — the wrapper that implements manage_issue_comment and get_conversation via gh CLI. GitHub's underlying REST API (/repos/{owner}/{repo}/issues/comments) DOES return comment IDs on create and supports per-ID fetch.
  • .agent/skills/pr-review/references/pr-review-guide.md — establishes reviewer conventions. Would need a new §9 "A2A Hand-off Protocol" section.
  • .agent/skills/pull-request/references/pull-request-workflow.md — same for author-side comment propagation.
  • Memory Core mailbox (A2A substrate from #10145#10266) — the transport for comment-ID propagation between sessions. No changes needed to the mailbox itself; just a convention on payload shape.

Tool surface discipline: Current count is 84 tools across 4 MCP servers; hard cap ~100 for many agents (50 recommended). This ticket adds ZERO new tools — enhances existing tool parameters instead. Matches precedent: start_database/stop_databasemanage_database.

The Fix

Phase 1 — manage_issue_comment returns comment ID on create/update

Current response shape:

{"message": "Successfully created comment on PR #N"}

New response shape:

{
  "message": "Successfully created comment on PR #N",
  "commentId": "4309098042",
  "url": "https://github.com/neomjs/neo/pull/N#issuecomment-4309098042",
  "createdAt": "2026-04-23T23:53:17Z"
}

GitHub REST already returns these fields; the wrapper just passes them through. Backward compatible — existing consumers that only read message continue to work.

Phase 2 — get_conversation gains three optional parameters

get_conversation({
  pr_number: N,                      // existing, required
  comment_id?: "4309098042",         // NEW: fetch ONLY this comment body
  since_comment_id?: "4309098042",   // NEW: fetch everything AFTER this comment
  last_n?: 3                         // NEW: fetch last N comments
})

Default behavior (all three new params omitted): unchanged — full conversation as today. Backward compatible.

Selector precedence: comment_id > since_comment_id > last_n > full. Explicit single > time-bounded > count-bounded > everything.

One minimalist-tool-surface discussion — decided against splitting into get_comment / list_comments: the new params live on the existing tool. The 84/100 tool-cap pressure (matches the manage_database condensation precedent) rules out tool-surface expansion.

Phase 3 — A2A comment-ID propagation convention

When a reviewer posts a review comment, capture the commentId from Phase 1's response. Then send a mailbox message to the PR author (or next reviewer) with the ID in the body:

send_message({
  to: '@neo-gemini-pro',
  subject: 're: PR #N review cycle 3',
  body: 'Approved. Review at PR #N comment 4309098042. Your next iteration: [...]',
  relatedTickets: ['#N']
})

The recipient extracts comment_id: '4309098042' from the body and calls get_conversation({pr_number: N, comment_id: '4309098042'}) — scales linearly with new-comment count, not cumulative.

Convention documentation: new section .agent/skills/pr-review §9 A2A Hand-off Protocol + symmetric section in pull-request §8.

Acceptance Criteria

  • manage_issue_comment action:create response includes commentId, url, createdAt fields alongside existing message.
  • manage_issue_comment action:update response includes the same fields.
  • get_conversation accepts comment_id, since_comment_id, last_n optional parameters with the documented precedence.
  • Existing consumers (no new params passed) get unchanged behavior — backward compatibility explicit test.
  • .agent/skills/pr-review/references/pr-review-guide.md gains a §9 A2A Hand-off Protocol section describing the convention and a worked example.
  • .agent/skills/pull-request/references/pull-request-workflow.md gains a symmetric section for author-side propagation.
  • Post-merge empirical: one cross-family review cycle performed using the comment-ID payload. Measure context-fetch size reduction vs full-conversation baseline.

Out of Scope

  • New tools (get_comment, list_comments): explicitly rejected due to the 84/100 tool-surface cap and the manage_database condensation precedent. All three phases work through existing tool surface.
  • Comment body size reduction (e.g., automatic summarization): orthogonal concern; this ticket is about selective FETCH, not compression.
  • Historical backfill of comment IDs for pre-merge PRs: N/A — new behavior is forward-looking.

Avoided Traps

  • Rich list-comments surface (get_comment returning [{commentId, author, createdAt, firstLine}, ...]) was considered as a cheap scan primitive. Rejected: adds a tool, violates tool-cap discipline. Users can call get_conversation({last_n: N}) and parse — marginally more expensive but stays within existing surface.
  • Server-side dedup / caching of conversation fetches: caching state across MCP-subprocess restarts is complex; not needed if selective fetch becomes the default reviewer pattern.

Related

  • Origin: PR #10269 three-cycle review sequence (2026-04-24)
  • A2A substrate: #10145, #10166, #10249, #10250, #10255, #10258, #10259, #10262, #10266 (the 8-PR chain that stabilized mailbox-as-A2A-bridge — this ticket extends that bridge to PR review coordination)
  • Tool-surface condensation precedent: manage_database (replacing start_database + stop_database)
  • Parent epic: #9999

Origin Session ID: b02bd06c-a2cb-4aff-8af1-c4f2643c91be

Retrieval Hint: "comment id return selective fetch since_comment_id A2A payload" / "PR review cycle context bloat manage_issue_comment get_conversation"

tobiu closed this issue on Apr 24, 2026, 7:34 PM