fix(responses): compile a recognized apply_patch wrapper from the body it validated - #5052
codingbooo wants to merge 1 commit into
Conversation
…y it validated `resolveCodeModeHelperName` accepts several wrapper shapes for a bare `exec` body (lidge-jun#4983): the `{input}` function wrapper, exactly one of exec's fallback fields, and one complete outer Markdown fence. It decides the body is an apply_patch call by reading it through `unwrapFreeformToolInput(..., "exec")` and testing that reading for a complete envelope. Compilation was handed the original text instead, and its apply_patch branch unwrapped only `input` and `patch`, so the wrapper the body arrived in reached the tool as the patch: {code} fallback -> tools.apply_patch("{\"code\":\"*** Begin Patch...") outer fence -> tools.apply_patch("```diff\n*** Begin Patch...\n```") The generated JavaScript passes values as data and never interpolates them as source, so this was a wrong patch rather than an escape. It was still the edit the model asked for turning into a rejected one, and the failure was silent: recognition had already committed to the apply_patch helper. Recognition and compilation now read one body. When the recognizer's own reading is a complete envelope, that reading is the canonical patch; when it is not, compilation keeps the name-based path's narrower `input`/`patch` unwrap, byte for byte. The envelope test gates that choice deliberately, so `{patch}` (not an exec fallback key, so never recognized from the body) and a lone fallback field that is not a patch keep their previous answers. Putting the canonical reading inside the compile boundary rather than at each of the four call sites is what stops a future caller from reintroducing the same gap by forgetting to pass it down. Closes lidge-jun#5046. Co-Authored-By: Claude Code <noreply@anthropic.com>
|
✅ Deterministic PR hygiene checks passed. |
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: ASSERTIVE Plan: Advanced Run ID: 📒 Files selected for processing (4)
Included review availability: Your plan provides up to 10 included reviews per hour; 9 remain after this review. 📝 WalkthroughWalkthroughThe compiler now consumes the same canonical body that recognizes repaired ChangesApply_patch compatibility
Priority: ➖ Normal Estimated code review effort: 3 (Moderate) | ~25 minutes Change: Bug fix · Severity of issue fixed: Medium Possibly related PRs
Merge Risk: ⚪ Minimal · up to The compatibility change preserves ordinary code and caller-defined tools while correctly forwarding recognized patch wrappers. No actionable merge risk remains. 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
Full details: Docstring CoverageExplanation Docstring coverage is 66.67% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 6 functions across 3 files. (1 skipped: 1 unsupported.)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
⏳ DRAFT
What to do
Review readiness checklist
0/4 boxes ticked. This PR stays in draft until every box above is ticked. Hygiene✅ Deterministic PR hygiene checks passed. |
리뷰 · 우선순위 75 / 80이 PR은 code-mode에서 고치는 위치는 컴파일 경계 안입니다. 테스트가 두 층입니다. 다만 같은 버그(#5046)를 고치는 열린 PR이 하나 더 있습니다. 메인테이너 본인 PR #5051( 라인 canonicalApplyPatchBody - tests/responses/apply-patch-envelope.test.ts / tests/adapters/bridge-legacy-shell-normalization.test.ts - fallback 키 목록( tests/adapters/bridge-legacy-shell-normalization.test.ts - 메인테이너의 판단이 필요한 지점
너의 추천 이 댓글은 grok-bot이 작성했습니다 |
Summary
resolveCodeModeHelperNamerecognizes several wrapper shapes for a bareexecbody (#4983) — the{input}function wrapper, exactly one of exec's fallback fields, and one complete outer Markdownfence — by reading the body through
unwrapFreeformToolInput(..., "exec")and testing that readingfor a complete envelope. Compilation was handed the pre-repair text instead, and its
apply_patch branch unwrapped only
inputandpatch. So the wrapper the body arrived in reachedthe tool as the patch:
The generated JavaScript passes values as data and never interpolates them as source, so this was a
wrong patch rather than an escape — but it was still the edit the model asked for turning into a
rejected one, and the failure was silent, because recognition had already committed to the
apply_patch helper.
Recognition and compilation now read one body. When the recognizer's own reading is a complete
envelope, that reading is the canonical patch; when it is not, compilation keeps the name-based
path's narrower
input/patchunwrap, byte for byte. An envelope test gates that choicedeliberately:
{patch}is not an exec fallback key so it is never recognized from the body, and alone fallback field that is not a patch keeps its previous answer.
Where I deviated from the review's suggestion, so you can push back. The review recommended
option A — each of the four call sites passing the unwrapped value into the compiler. I put the
canonical reading inside the compile boundary (
canonicalApplyPatchBody) instead. Both satisfy"one canonical repaired body", but option A leaves the boundary open for a fifth caller to
reintroduce exactly this gap by forgetting to pass it down, and forgetting to pass it down is what
this bug is. It unpacks back to option A in place if you prefer the caller-owned shape.
Closes #5046
Verification
Reproduced before touching anything — on
dev, four of six accepted shapes compiled the wrapper:All five required regressions are added to existing files, so no new test file needed registering:
tests/responses/apply-patch-envelope.test.ts— all seven fallback fields compile to the sameraw patch; fenced and unfenced compile identically; decorated delimiters normalize on every path
and not only the bare one; an ambiguous or non-envelope body stays byte-exact; a normal
code-mode JavaScript body is never compiled; a caller-defined non-code-mode
execis neverreinterpreted.
tests/adapters/bridge-legacy-shell-normalization.test.ts— the required bridge-levelregression. It drives the real bridge, reads the delivered
execbody back out of the SSE, andruns it with a stub
tools, asserting whattools.apply_patchactually received. Arecognizer-level assertion cannot see this gap, which is why the issue asked for it.
Reverse-verified, so these are not tautologies: with the source change stashed, 7 of the new
tests fail; with it, all pass.
bun x tsc --noEmitbun scripts/test.ts --changed=upstream/devbun scripts/structure-ssot.tsstructure/ SSOT checks passedbun scripts/privacy-scan.tsPrivacy scan passedbun scripts/file-size-ratchet.tsfile-size ratchet passedThe 9 failures are not from this change: they are
provider management validation(7), a Windowsicaclsspill case, and the large history index case. I ran the same three files on a pristineupstream/devworktree and got the identical 9, so they are pre-existing on this machine.Checklist
structure/transports/responses.mdrecords the one-body rule at the wrapper-recovery boundary it already documents.
remain data, never interpolated source; the envelope predicate still gates the wider reading,
so no non-patch body is reinterpreted.
🤖 Generated with Claude Code
Review readiness checklist
This PR stays in draft until every box below is ticked. Tick all four boxes once the requirements are met:
All CI tests are green on my local testing.
I pushed my PR to the latest dev commit.
I resolved all correct Codex and CodeRabbit findings.
My PR is ready for review.
Summary by CodeRabbit
Bug Fixes
apply_patchrequests wrapped in supported function-call formats or Markdown fences.Documentation