Frontmatter
| id | 10109 |
| title | PR comment hygiene — update existing self-review vs. add new comment per lifecycle stage |
| state | Closed |
| labels | enhancementai |
| assignees | tobiu |
| createdAt | Apr 19, 2026, 7:48 PM |
| updatedAt | Apr 21, 2026, 6:37 PM |
| githubUrl | https://github.com/neomjs/neo/issues/10109 |
| author | tobiu |
| commentsCount | 2 |
| parentIssue | null |
| subIssues | [] |
| subIssuesCompleted | 0 |
| subIssuesTotal | 0 |
| blockedBy | [] |
| blocking | [] |
| closedAt | Apr 21, 2026, 6:37 PM |
PR comment hygiene — update existing self-review vs. add new comment per lifecycle stage

Input from Claude Opus 4.7 (Claude Code):
❋ # Extension: PR body hygiene + substrate-awareness rules
Following session discussion (session ID
07f601dc-353a-44d2-a373-18da2a0d305a), this comment proposes additions to the ticket's scope. None of it reframes the ticket's core polish-vs-pivot distinction — that rule is accepted as-is. The additions cover PR body structure (not just comments), substrate awareness for the swarm/multi-harness reality, and an authorship-respect rule that applies across every surface.Several of these refinements came from in-session pushbacks from @tobiu correcting earlier drafts. The refinement arc is preserved below for future agent context.
1. Accept the ticket's core rule
The polish/pivot distinction is sound:
- Polish (same direction, better execution) → update in place
- Pivot (direction change) → new comment preserving the architectural reasoning
An earlier draft of this comment pushed back on "new comment for pivot," arguing for update-in-place +
## Evolutionsubsection. That pushback was wrong — it silently depended on Memory Core being a shared substrate (it isn't cross-contributor). The append-for-pivot rule stands.2. Add: PR body hygiene
The ticket as filed covers comments; PR bodies have their own redundancy problem that belongs under the same hygiene umbrella.
Observed redundancy in recent PRs (#10111, #10114, #10115, #10116):
Relatedsections duplicated verbatim between ticket body and PR bodyAvoided Trapsoften repeated unchanged from ticketArchitectural Impactpreamble tables that restate the ticket'sThe FixsectionProposed minimum-viable PR body structure:
Resolves #N<one-paragraph outcome summary — what actually shipped, not restating ticket>
Deltas from ticket (if any)
<scope additions, better solutions, discovered edge cases>
Test Evidence
<commands run, results, coverage>
Post-Merge Validation
- <items verifiable only after merge>
Commits (if multi-commit)
- <sha> — <purpose>
Evolution (optional, only if pivots occurred during implementation)
<one compressed paragraph per pivot — why direction changed, not the old text>
What does NOT go in the PR body: restating
The Problem/The Architectural Reality/Relatedlist /Avoided Trapsunless those are deltas from the ticket's originals. Those are the ticket's property; the PR links to the ticket.Heuristic: length proportional to architectural weight, not diff size. A 1-line CI change unlocking empirical validation deserves context; a 500-line mechanical rename doesn't need a Fat PR body.
3. Authorship respect rule (critical — applies across all surfaces)
You update your own authored artifacts in place. You never override another author's. Your contribution to their artifact is always a NEW comment.
Surface Own artifact Other author's artifact PR body Update in place Respond via comment (never rewrite) Self-review comment Update (polish) / new comment (pivot) Respond via NEW comment Ticket body Update in place Comment on the ticket Ticket AC list during execution Extend own "Evolution" trail Comment — do NOT mutate their AC list Why this matters beyond human etiquette:
- Attribution collapse — rewriting someone else's prose loses who-said-what-when, which is load-bearing for review and Native Edge Graph ingestion
- Quality preservation in swarm context — agents vary in capability; a shallower model overriding a deeper model's reasoning is signal regression, not update
- Trust boundary — GitHub permissions allow maintainers to edit collaborators' PR bodies; the cultural norm is we don't. Agents have write permissions too. The restraint is cultural, not technical. Codifying it prevents agent-driven erosion.
Exceptions (document explicitly in the workflow):
- PR author explicitly invites co-authorship on the body → permission-bounded, OK
- Abandoned PR salvaged by a maintainer → takeover documented in a comment first, then edit
- Default: never touch another author's content. Comment instead.
4. Origin Session ID: MANDATORY in tickets AND PR bodies
Origin Session ID: <uuid>is the Neo Memory Core session identifier. It is swarm-shared on the same machine — any MCP-speaking agent (Claude Code, Antigravity, Gemini, future sub-agents) can queryquery_raw_memories(sessionId=<uuid>)against the same Memory Core instance and retrieve the originating session's context.Value profile:
- Primary reader (99%+ self-resolution rate): direct A2A anchor for next session
- Cross-harness same-machine agents: queryable — this is the swarm-shared substrate
- External contributor: opaque UUID, but low-cost subtle signal that neo.mjs runs its own Memory Core infrastructure
- Cost: ~40 characters per artifact
Include unconditionally.
5. Don't cite harness-private memory as load-bearing in public artifacts
Clarification on memory substrates (corrected mid-session):
Substrate Scope Multi-harness? Cross-machine? Claude Code harness memory ( ~/.claude/projects/.../memory/feedback_*.md)Claude Code only No No Neo Memory Core (MCP server + ChromaDB) MCP-accessible Yes (same machine) No (#9999 optional) Committed repo files ( .agent/skills/,learn/, etc.)Git-durable Yes Yes GitHub tickets / PRs Public Yes Yes
feedback_*.mdfilename references (e.g., "Memory evidence:feedback_no_title_prefix_duplicating_labels.md") are harness-AND-user-specific — an Antigravity agent on the same machine cannot resolve them; a Claude Code agent on a different Mac cannot either.Rule: don't cite harness-private memory paths as load-bearing evidence in public tickets/PRs. Gesture at the session via
Origin Session ID(cross-harness resolvable). If the lesson is universal, promote it to a committed repo file (next rule).6. Lesson promotion path
Session lessons have a promotion path — make it explicit in the workflow:
- Session observes a pattern → save as feedback memory (
feedback_*.mdin Claude Code harness / equivalent in other harnesses)- Save session transcript via
add_memory→ Neo Memory Core (cross-harness, swarm-shared on machine)- If the lesson is universal → promote to a committed repo file — either:
- A new
.agent/skills/<skill>/references/<topic>.mdif it warrants skill-scope- A section in an existing skill reference file (e.g.,
ticket-create-workflow.md§9 Anti-Patterns pattern)- A
learn/guide update- Tickets and PRs cite the repo-committed location as load-bearing, NOT the Memory Core filename
The skill system IS the multi-contributor knowledge-transfer substrate. Personal memory files are productivity enhancement; repo files are shared durable rules.
7. "Assume no private memory" stance for public artifacts
When writing public artifacts (tickets, PRs, comments), assume the reader has access to nothing private — no Claude Code memory, no other harness's memory, no local files outside the repo.
Fair-game references in public artifacts:
- Committed repo paths (
learn/...,.agent/skills/...,apps/.../*.mjs)- GitHub resources (
#N, PR URLs, commit SHAs)- Neo Memory Core session IDs (swarm-shared on machine, resolvable via MCP)
Not fair-game as load-bearing citations:
- Harness-private filenames (
feedback_*.md,CLAUDE.mdper-project notes, Antigravity private stores)- Local filesystem paths outside the repo
- Machine-specific identifiers
Suggested AC additions to the ticket
pull-request-workflow.mdextended with PR body hygiene section (§2 above) including minimum-viable structure- Authorship respect rule documented as its own section covering all surfaces (§3 above)
- Origin Session ID requirement codified for both tickets AND PR bodies (§4 above)
- Substrate-awareness rule documented in
pull-request-workflow.mdor a cross-cutting skill reference (§5, §6, §7 above)create-skillmeta-skill updated to reference the lesson promotion path (§6) — ties to the spirit of #10118No retroactive edits to closed PRs
Aligning with the ticket's existing AC. The authorship respect rule (§3) strengthens this — even on closed OWN PRs, historical record is preserved; update-in-place applies to ACTIVE PRs only.
Refinement arc preserved here rather than collapsed, because several of these rules emerged from corrections to earlier drafts of this comment — that reasoning chain has value for future agents picking up the ticket.

Input from Claude Opus 4.7 (Claude Code):
❋ # Extension: Review Response Protocol (author-side post-review comment)
Following the cross-review pilot this session (Gemini reviewing PR #10161; the new
pr-review§7.1 Depth Floor active-challenge caught a real latent bug I had self-triaged as non-blocking), one dimension surfaced that sits just outside this ticket's current scope but belongs under the same hygiene umbrella:What happens AFTER a reviewer posts
Status: Request Changeswith Required Actions?Current state: author pushes a fix commit → reviewer has to discover commits + diff + match-against-their-own-Required-Actions manually. No structured per-item acknowledgment on the PR thread.
Gap vs. existing ticket scope
The ticket's "bug-fix rounds → NEW comment per round" row is close but not the same — that row is about the author's own polish/fix cycles on their own initiative. This is about the author's response to another reviewer's Required Actions, which needs item-by-item status tags so re-review is ack-checking rather than diff-diving.
Proposed addition
New §6 "Review Response Protocol" in
pull-request-workflow.md, covering the cross-review scenario:Per-item status tags (mirror
pr-review§4 Graph Ingestion)
[ADDRESSED]— fix pushed in commit X; 1-2 sentences on what changed[DEFERRED]— not addressed in this PR; follow-up ticket # cited + rationale[REJECTED_WITH_RATIONALE]— author disagrees with the reviewer; rationale documented for the reviewer's potential counter-challengeTemplate
## Addressed Review FeedbackResponding to review [comment URL or "above"]:
[ADDRESSED]<Required Action N text> Commit: <sha> Details: <1-2 sentences>
[DEFERRED]<Required Action M text> Follow-up ticket: #<number> Rationale: <why deferred>
[REJECTED_WITH_RATIONALE]<Required Action K text> Rationale: <why rejected>Re-review requested.
Origin Session ID: <uuid>
Why author-side comment matters beyond commits
- Multi-item reviews — 3+ Required Actions need explicit per-item status or re-review drifts (silently skipped items)
- Deferred items — follow-up ticket provenance belongs on the PR thread, not buried only in commits
- Rejected items — author-vs-reviewer architectural disagreement needs visible comment-thread negotiation, not silent omission
- Cross-model attribution — when the GitHub author is a relay (tobiu for both Claude and Gemini PRs in this session), structured comments make the actual model-author's response visible
- Retrospective daemon —
[ADDRESSED]/[DEFERRED]/[REJECTED_WITH_RATIONALE]cycles become mineable PR-lifecycle signalAlignment with existing ticket rules
- Polish vs. pivot (original): a follow-up commit addressing a Required Action is author polish on own work in response to external feedback — NEW comment (not update-in-place) because the reviewer is a distinct author; preserves the review-negotiation thread.
- Authorship respect (§3 of prior extension): the reviewer's comment is their artifact and must not be edited; the author's response is a NEW comment on their own PR thread — aligned.
- Origin Session ID (§4 of prior extension): included in the template.
- "No private memory" stance (§7 of prior extension): commit SHA and follow-up ticket # are fair-game repo-resolvable references; template only uses these.
Definition of Done reframe
Current
pull-request-workflow.md§5 says "The agent's task is strictly considered 'Done' once the PR is opened." Adding §6 subtly reframes this:Donemeans "first handoff complete." If the reviewer posts Request Changes, the author re-enters the loop via §6 → posts Addressed comment → halts again for re-review. Done-ness is per-handoff, not per-lifetime. Worth a one-line clarification in §5 referencing §6.Dogfood
Posted a retroactive Addressed comment on PR #10161 this session using this exact structure — demonstrates pattern concretely and provides an empirical anchor for the skill's eventual §8.3-style "empirical example" section.
Suggested AC additions
.agent/skills/pull-request/references/pull-request-workflow.md§6 "Review Response Protocol" section with per-item tag taxonomy.agent/skills/pull-request/assets/review-response-template.mdcreated (mirrors the shape ofpr-review-template.md)- §5 Definition of Done clarified: "first handoff complete" + cross-reference §6 for re-review cycles
pr-review§4 Graph Ingestion Notes cross-references the author-side tags so the Retrospective daemon sees a unified taxonomy- Empirical example: PR #10161 Addressed comment cited as the first observed instance
Origin Session ID: 71dc3cd8-d39d-48e1-ac62-e240ca67d1a5
Summary
Observation from recent sessions (PRs #10100, #10101, #10102, #10105 all closed with mixed comment patterns): no canonical rule for when a follow-up should update the existing self-review comment vs. create a new one.
Impacts:
ConceptDiscoveryService#10105 or future gap-mining tools), repeated / obsolete comment context dilutes signal.sandman_handoff.mdand Memory Core both ingest PR review prose; hygiene affects downstream digestion quality.Proposed Rule (quick-win; open to challenge)
Codify in
.agent/skills/pull-request/references/pull-request-workflow.md:Rationale — why distinguish polish vs. pivot:
Acceptance Criteria
.agent/skills/pull-request/references/pull-request-workflow.mdextended with the rule table.agent/skills/ticket-create/once that skill lands (#10104)pull-requestskillSKILL.mdreferences the new sectionRelated
Origin Session ID: 1db25bbe-f39d-4dcd-bb0e-bc125ce91326