Skip to content

fix: coder.solve() PR bodies now carry the coder's own summary (v0.29.2)#68

Merged
mabry1985 merged 1 commit into
mainfrom
fix/coder-solve-pr-summary
Jul 4, 2026
Merged

fix: coder.solve() PR bodies now carry the coder's own summary (v0.29.2)#68
mabry1985 merged 1 commit into
mainfrom
fix/coder-solve-pr-summary

Conversation

@mabry1985

Copy link
Copy Markdown
Contributor

Summary

Caught live: portfolio-plugin#38's PR body was literally "[coder.solve rung=greedy gens=1] solved 1-shot" — a diagnostic string, not a description.

Root cause: _WorktreeSolveAdapter.generate() dispatches the coder into its worktree but discards the reply, keeping only the worktree path. Every coder dispatch is promised "your FINAL message becomes the PR description, verbatim" (loop._build_prompt) — but dispatch() had nothing real to report for a coder.solve()-ladder win, so it fell back to its own [coder.solve rung=... gens=...] {note} string. Same failure class as #62 ("coder's final reply becomes the PR body verbatim"), just on a different dispatch path that #62 never touched.

Worse than cosmetic: _verify_goal's NO_TEST_NEEDED escape hatch reads this same text — so a legitimate no-test-needed change (pure refactor, docs-as-code) dispatched through the solve() ladder would always look like a missing test, forcing an unnecessary re-dispatch/escalation cycle.

Fix:

  • generate() now captures each candidate's reply (adapter._replies[wt]).
  • dispatch() uses the winning candidate's own reply as the result, falling back to the diagnostic string only when there isn't one (a fusion win returns file content, not a natural-language summary — nothing to fall back FROM).

Test plan

  • ruff check . / ruff format --check . — clean
  • pytest tests/ -q — 281 passed (2 new: winner's reply is used verbatim + the fusion-win fallback still produces the diagnostic string)

🤖 Generated with Claude Code

… diagnostic string (v0.29.2)

_WorktreeSolveAdapter.generate() dispatched the coder into its worktree but
discarded the reply, keeping only the worktree path. Every coder dispatch is
promised "your FINAL message becomes the PR description" (loop._build_prompt),
but dispatch() had nothing real to report for a solve()-ladder win, so it fell
back to its own diagnostic string (e.g. "[coder.solve rung=greedy gens=1]
solved 1-shot") — which became the PR body verbatim. Same failure class as
#62, on a different path.

Worse than cosmetic: _verify_goal's NO_TEST_NEEDED escape hatch reads this
same text, so a legitimate no-test-needed change dispatched through the
solve() ladder would always look like a missing test, forcing an unnecessary
re-dispatch/escalation cycle.

Fix: generate() now captures the coder's reply per candidate; dispatch()
uses the WINNING candidate's own reply as the result, falling back to the
diagnostic string only when there isn't one (a fusion win, which returns
file content, not a summary).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@protoquinn

protoquinn Bot commented Jul 4, 2026

Copy link
Copy Markdown

👀 Quinn is reviewing — verdict (PASS / WARN / FAIL) + findings to follow.

@mabry1985 mabry1985 merged commit 0e027cf into main Jul 4, 2026
1 check passed
@mabry1985 mabry1985 deleted the fix/coder-solve-pr-summary branch July 4, 2026 08:48

@protoquinn protoquinn Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

QA Audit — PR #68 | fix: coder.solve() PR bodies now carry the coder's own summary (v0.29.2)

VERDICT: WARN (CI still queued — re-review once terminal)


CI Status

  • test: queued

Diff Review

  • coder_seam.py: Adds _replies dict to capture each candidate coder's final reply in generate(); dispatch() now uses the winning candidate's own reply as result_text, falling back to the rung/gens diagnostic string for fusion wins. Clean, minimal change — 2 sites touched.
  • Version bumps: 0.29.10.29.2 in protoagent.plugin.yaml and pyproject.toml.
  • Tests: Existing test updated to assert the winner's reply is used verbatim; new test_dispatch_falls_back_to_a_diagnostic_string_when_the_winner_has_no_reply covers the fusion-win fallback. Both well-structured.

Observations

  • LOW: clawpatch structural review unavailable (500 — repo not in cache). Manual review of the diff found no cross-file issues. The change is scoped entirely within _WorktreeSolveAdapter — no callers modified, no API contract changes.
  • The (reply or "").strip() guard in generate() correctly prevents storing empty/whitespace-only replies, ensuring the fallback fires when the coder produces nothing useful.

— Quinn, QA Engineer

@protoquinn

protoquinn Bot commented Jul 4, 2026

Copy link
Copy Markdown

Submitted COMMENT review on #68.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant