Repository navigation
[auto-review] Reviewer reuses the persona-injected model route & history → emits prose instead of the JSON protocol → every tool call fails closed (Auto preset unusable under custom personas) #10525
Replies: 1 comment
|
Both halves check out, and they are separate causes that happen to meet in the same call. The route is the session's: The history is real too, which is the part I would not have guessed from the call site alone: Two fixes, in order of how much they buy:
The second one matters even without personas: a model that prepends "Sure," is enough to fail this, and the user experiences it as Auto being broken rather than as one malformed reply. |
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
@deepseek-ai/dsh-experimental-auto-review(experimental,packages/experimental/auto-review), version seen in the packaged app: 0.2.1-rc.2TL;DR
The Auto reviewer is instructed to return exactly one JSON object (
REVIEW_POLICY), and the response is parsed with a strictJSON.parseinparseDecision. ButclassifyRisk:provider/modelcome straight fromsession.requestHeader()), andFILTERED_HISTORYsection — including persona / memory injections that are tagged ashuman-instruction.When the active model route has a strong persona system context (here: a Chinese "whale-girl maid" persona with
只输出简体中文/ "reply in Simplified Chinese only" / self-referential roleplay), that persona overrides the JSON-only output contract. The reviewer replies in in-character Chinese prose,JSON.parsethrows on the very first CJK token,readDecision→parseDecisionthrows,classifyRiskrejects, and the gate returns:Because a reviewer failure is materialized as
kind: "deny", the tool never executes and the whole task stalls — not because the action is dangerous, but because the judge was role-playing.Exact code path (from
packages/experimental/auto-review/src/index.ts@ master)REVIEW_POLICY— fixed system text; correctly says "Return exactly one JSON object and no other text" and "never by … message tone". This is fine.classifyRisk()buildsGenerateOptions:LANG_ZH_CN_ONLYbehavior that route exhibits leaks into the reviewer.snapshotAutoReview()→filteredUserEntries()pushes every non-tooluser/messageintohistory, andtextRole()classifies real human user messages ashuman-instruction. Persona/memory content delivered as user-role context is therefore fed to the reviewer as an authoritative instruction.reviewUserText()serializessnapshot.historyverbatim into theFILTERED_HISTORYsection.readDecision()→parseDecision():message, and:Observed evidence (this session)
Repeated
pwsh/ops_bashcalls all returnedAuto review … failed; its body was not executed: Unexpected token '<CJK>', "<persona prose>"... is not valid JSON, with a different in-character Chinese sentence each time (本鲸 / 呜 / 主人别急 / 好的主人 …), confirming it is live model output being role-played, not corrupted static data. Setting the approval policy tonever(which bypasses this reviewer gate entirely) made the identical call succeed immediately — isolating the gate as the cause.Why it matters
dsh-plugin, etc.). Auto mode silently breaks for any user using them.SyntaxErrorstring; there is no retry, no "output wasn't JSON" re-prompt, and no fallback.Suggested fixes (any one helps; 1+3 together are robust)
classifyRiskthrough a dedicated, neutral authorization route (ownprovider/model, no session persona). The reviewer is a mechanical judge; it must not inherit role-play.FILTERED_HISTORY. Style/instruction injections are irrelevant to effect-based risk classification. Either drop agent-instructions/persona blocks that aren't genuine human turn text, or tag them with a role (e.g.style-context) that the policy explicitly states must not affect output format or tone.JSON.parse, extract the first balanced top-level JSON object from the text (tolerate leading/trailing prose). Only treat it as a hard failure if no parseable object exists.Repro
pwshGet-ChildItem).Auto review of tool "…" failed; … is not valid JSON, and the tool body never runs.never(bypassing the gate) makes the same call succeed.Environment: Windows 11, DSH Desktop build (packaged
app.asar), reviewer plugin@deepseek-ai/dsh-experimental-auto-review@0.2.1-rc.2.All reactions