Conversation
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. 🗂️ Base branches to auto review (2)
Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: ASSERTIVE Plan: Advanced Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
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 |
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
리뷰 · 우선순위 78 / 80이 PR은 CodeBuddy 경로에서 벤더 CLI가 도구 채널이 꺼진 채로( 중요한 설계 선택은 “마커만 보이면 거절”이 아니라 관측된 두 줄 문법일 때만 거절한다는 점입니다. 줄 맨 앞(column zero)이고, 마크다운 펜스 밖이며, 원본 기여자 PR #4627(Ingwannu)을 리뷰 반영해 가져왔고, Co-authored-by가 커밋에 남아 있습니다. 파일은 가드·어댑터 한 줄 연결· 라인 단위로 보면 큰 구멍은 거의 없고, 운영·스택 쪽 주의가 더 큽니다.
메인테이너의 판단이 필요한 지점
너의 추천 이 댓글은 grok-bot이 작성했습니다 |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: aef65bde8c
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| const fenceMarkers = fence ? [fence.repeat(3)] : ["```", "~~~"]; | ||
| const completeFence = fenceMarkers.find(marker => text.startsWith(marker, index)); | ||
| if (completeFence) { | ||
| fence = fence ? null : (completeFence[0] as "`" | "~"); |
There was a problem hiding this comment.
Track the full Markdown fence delimiter
When an answer uses a valid four-backtick outer fence to quote a three-backtick fenced example, this scanner consumes only the first three opening backticks and then treats the inner ```text line as the closing fence, even though it has trailing content. The subsequent DSML example is therefore parsed as live control markup and the turn incorrectly ends with vendor_scaffold_detected, contradicting the intended guarantee that fenced examples pass unchanged. Record the opening delimiter length and only close on a delimiter of at least that length with a valid closing-fence suffix.
Useful? React with 👍 / 👎.
|
✅ Deterministic PR hygiene checks passed. |
cbcd0e2 to
e3d5e7f
Compare
0ba11ef to
6cece6b
Compare
e3d5e7f to
cf8969f
Compare
6cece6b to
55afd15
Compare
a85315a to
441dc16
Compare
55afd15 to
3d39704
Compare
The CodeBuddy route launches the vendor CLI with --tools "" and --strict-mcp-config, so the routed model has no native tool channel and writes its call as prose. The shared coding-agent projection forwards text_delta unrepaired, so that markup reached the client as an ordinary assistant answer. Qoder's guard does not match it. The leaked tags are wrapped in FULLWIDTH VERTICAL LINE (U+FF5C), which none of the shipped UNREPAIRABLE_MARKERS cover, so this needed a signature of its own rather than a port. Refusal requires the observed two-line grammar: a calls control line at column zero, outside a Markdown fence, immediately followed by an invoke line naming a functions.* tool. A lone tag, a quoted or inline-code literal, a fenced example, a blockquote, indented source, or prose discussing the markup all carry extra syntax before the tag and are forwarded untouched. Matching the marker alone would refuse a legitimate answer that merely explains this protocol, which is why the detector is narrower than the marker spelling. A detected leak preserves the answer text already proven safe, emits one non-retryable vendor_scaffold_detected error, and suppresses the vendor's later success terminal so the client never sees a completed turn. Markers split across streamed deltas are caught by holding only a bounded suffix that could still complete a control sequence or a fence; unrelated pending text is released at the next mismatch or terminal. The reasoning channel is guarded independently. Leaked prose is never promoted into a real tool call. The text channel carries no authenticated call envelope and no validated arguments, so converting it would manufacture execution authority out of model output. Kept CodeBuddy-owned rather than lifted into the shared coding-agent path, the same containment #4234 chose for Qoder: the contract observed here is this vendor's, and #4190's lane packet asked for a report rather than symmetry. Co-authored-by: Ingwannu <ingwannu@users.noreply.github.com>
3d39704 to
915af60
Compare
441dc16 to
99c977d
Compare
|
Landing the provider wire-compatibility lane, top layer first. Routed tool-call markup no longer reaches the client as assistant text. The detector is deliberately scoped to the two-line syntax actually reported in #4596; widening it to hypothetical variants would trade away the guarantee that ordinary code and prose are never over-blocked. Evidence at the verified tip 49f815d (tree
Maintainer integration decision under MAINTAINERS.md / AGENTS.md: a maintainer with maintain or admin access may integrate into |
2e590fe
into
codex/pw5-bounded-tool-wire-names
Summary
Carries #4627 by @Ingwannu for #4596, with review changes described below.
The CodeBuddy route launches the vendor CLI with
--tools ""and--strict-mcp-config, so the routed model has no native tool channel and writes its tool call as prose.src/adapters/coding-agent/protocol.tsfilters frame types but never inspects frame contents, so that markup was forwarded as an ordinary assistant answer — the same single line of trust #4190 found for Qoder.Qoder's shipped guard does not match this leak. The tags are wrapped in FULLWIDTH VERTICAL LINE (U+FF5C), e.g.
<||DSML|| invoke name="functions.exec">, which none of the shippedUNREPAIRABLE_MARKERScover. A signature extension was required, not a port of the existing filter.The hard requirement was not over-blocking
Refusing on the marker alone would reject a legitimate answer that merely explains this protocol — a user asking what the tag means, a documentation answer containing a fenced example, or source code carrying the literal. That is a worse failure than the one being fixed, because it breaks correct answers.
Refusal therefore requires the observed two-line grammar, not the marker:
callscontrol line at column zero,invokeline naming afunctions.*tool.Every quotation form carries extra syntax before the tag — inline code, a quoted string, a blockquote, indented source, a fenced block, or surrounding prose — so all of them are forwarded untouched. A lone
callstag with no invoke line is harmless and passes. Both directions are tested.A detected leak preserves the answer text already proven safe, emits one non-retryable
vendor_scaffold_detectederror, and suppresses the vendor's later success terminal so the client never sees a completed turn. Markers split across streamed deltas are caught by holding only a bounded suffix that could still complete a control sequence or a fence; unrelated pending text is released at the next mismatch or at the terminal, so normal output is never withheld indefinitely. The reasoning channel is guarded independently of text.Leaked prose is never promoted into a real tool call. The text channel carries no authenticated call envelope and no validated arguments, so converting it would manufacture execution authority out of model output. Failing closed is the right answer here, matching the Qoder precedent.
Kept CodeBuddy-owned rather than lifted into the shared
coding-agentpath — the same containment #4234 chose for Qoder, and what #4190's lane packet explicitly asked for: driven by a report, not by symmetry.Review disposition from #4627
Accepted: the adapter-local placement, the fail-closed non-retryable error contract, the preserved answer prefix, the independent reasoning guard, split-delta buffering, success-terminal suppression, and CodeRabbit's findings on cross-channel terminal ordering, replacement-tail ordering, queuing events behind unresolved tails, and empty-delta slot preservation.
Rejected, with reasons: the original marker-only detector, because it refuses legitimate discussion and code examples and so fails the over-blocking requirement outright; promoting leaked prose into a real tool call; and lifting the filter into the shared coding-agent path.
Closes #4596
Verification
Static source review only, plus hosted CI. No local suite, typecheck, or build was run — the repository owner prohibits local suite execution in this lane after a past local run deleted real
~/.opencodexdata. The verification claims in #4627's description are that author's, not re-asserted here.Static checks performed:
git diff --checkclean.Regression coverage in
tests/providers/codebuddy-adapter.test.ts, covering both directions:Refusal —
refuses a full-message DSML calls-and-invoke scaffold,detects a DSML control sequence split across streamed text deltas,refuses DSML calls-and-invoke scaffolding from reasoning independently.Non-refusal (the over-blocking controls) —
delivers a lone discussed DSML calls tag unchanged,delivers quoted and inline-code DSML literals unchanged,delivers a fenced DSML source example unchanged across deltas,delivers source strings containing both DSML literals unchanged,delivers an unquoted invoke line when no calls container precedes it.Ordering and streaming —
releases a lone control-line candidate at the terminal,queues later events behind an unresolved marker prefix,keeps an existing pending slot when its channel receives an empty delta,moves a replaced pending marker prefix to its new arrival position.This is the tip of a stacked lane and deliberately carries no
[skip ci]. Under the maintainer-approved DEV-STACK-08 tip-only policy, the CI run on this branch is the gate for every layer beneath it, and this branch contains all of them:codex/pw1-vision-sidecar-truncation(#4752),codex/pw2-deepseek-reasoning-replay(#4769),codex/pw3-kimi-tool-adjacency(#4770),codex/pw4-custom-baseurl-join(#4773),codex/pw5-bounded-tool-wire-names(#4774).Known limitation: the detector is deliberately narrow and would not catch a future vendor variant that indents the control lines or inserts blank lines between them. Neither shape appears in #4596, and widening it would cost the over-blocking guarantee, so that is left for a report rather than speculation.
Checklist
docs-siteprovider guide andstructure/providers/chat-compat.mdboth record the refusal contract and the tools-disabled ownership boundary)