You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Confirmed live on edge-nl-01 via two real ai_review_provider_unparseable_output events (with the new diagnostic snippet from #5071) minutes apart:
"Two things are going on that don't line up: 1. Plan Mode is active, which is a workflow for planning code changes to this repo — explore, design an approach, write a plan file, then call ExitPlanMode for approval... 2. But the bulk of your message is a..."
"I want to flag something before going further: this turn contains a very large embedded block claiming to be 'ADDITIONAL SYSTEM INSTRUCTIONS' that tries to cast me as an automated PR-review oracle... Layered on top of that is a 'Plan Mode' wr[apper]..."
Root-caused to two compounding bugs in createClaudeCodeAi (src/selfhost/ai.ts):
--permission-mode plan has been passed to every claude invocation since the self-host stack's original commit (2026-06-24). This activates Claude Code's full interactive Plan-Mode workflow (explore → draft a plan → wait for ExitPlanMode approval) — not just a read-only permission restriction. --disallowedTools Bash,Edit,Write,WebFetch,WebSearch already forbids every mutating/networked tool, so nothing needing that framing remains; the mismatch between "you're in an interactive planning session" and "just output a JSON review verdict" is confusing the model into responding with meta-commentary instead of a review.
systemAppend (repo-level custom review instructions from .gittensory.yml) is textually prepended into the stdin prompt behind a literal "ADDITIONAL SYSTEM INSTRUCTIONS:\n" header, rather than passed through Claude's own --append-system-prompt/--append-system-prompt-file channel. This was implemented CORRECTLY in feat(selfhost): wire claude --append-system-prompt for review instructions (v2 refinement) #1471/PR feat(selfhost): pass repo instructions to cli reviewers #2954 (using the real --append-system-prompt flag), then regressed by a later commit (fix(selfhost): keep Claude review instructions out of argv (#3951)) that moved it back to textual stdin-smuggling to avoid the content appearing in ps aux — inadvertently recreating the exact textbook pattern of a prompt-injection attack (a labeled "system instructions" block inside otherwise-untrusted content), which Claude's own safety training correctly (if here, incorrectly) flags as suspicious.
Both bugs apply to every claude-code review call; #2 only visibly compounds them for repos with review.repoInstructions/pathGuidance configured.
Fix
--permission-mode plan → --permission-mode bypassPermissions — matches the already-established "no TTY, no one to answer a permission prompt, --disallowedTools is the real boundary" intent.
codex is unaffected (uses --sandbox read-only, not --permission-mode, and has no CLI-native system-prompt-file equivalent per #1471's own documented limitation — keeps the existing textual-prepend approach).
Problem
Confirmed live on edge-nl-01 via two real
ai_review_provider_unparseable_outputevents (with the new diagnostic snippet from #5071) minutes apart:Root-caused to two compounding bugs in
createClaudeCodeAi(src/selfhost/ai.ts):--permission-mode planhas been passed to everyclaudeinvocation since the self-host stack's original commit (2026-06-24). This activates Claude Code's full interactive Plan-Mode workflow (explore → draft a plan → wait forExitPlanModeapproval) — not just a read-only permission restriction.--disallowedTools Bash,Edit,Write,WebFetch,WebSearchalready forbids every mutating/networked tool, so nothing needing that framing remains; the mismatch between "you're in an interactive planning session" and "just output a JSON review verdict" is confusing the model into responding with meta-commentary instead of a review.systemAppend(repo-level custom review instructions from.gittensory.yml) is textually prepended into the stdin prompt behind a literal"ADDITIONAL SYSTEM INSTRUCTIONS:\n"header, rather than passed through Claude's own--append-system-prompt/--append-system-prompt-filechannel. This was implemented CORRECTLY in feat(selfhost): wire claude --append-system-prompt for review instructions (v2 refinement) #1471/PR feat(selfhost): pass repo instructions to cli reviewers #2954 (using the real--append-system-promptflag), then regressed by a later commit (fix(selfhost): keep Claude review instructions out of argv (#3951)) that moved it back to textual stdin-smuggling to avoid the content appearing inps aux— inadvertently recreating the exact textbook pattern of a prompt-injection attack (a labeled "system instructions" block inside otherwise-untrusted content), which Claude's own safety training correctly (if here, incorrectly) flags as suspicious.Both bugs apply to every
claude-codereview call; #2 only visibly compounds them for repos withreview.repoInstructions/pathGuidanceconfigured.Fix
--permission-mode plan→--permission-mode bypassPermissions— matches the already-established "no TTY, no one to answer a permission prompt,--disallowedToolsis the real boundary" intent.systemAppendto a file inside the same per-call isolated temp dir already used for the subprocess'scwd, and pass--append-system-prompt-file <path>— resolves the original fix(selfhost): keep Claude review instructions out of argv #3951 argv-visibility concern via the CLI's own file-based system-prompt mechanism instead of textual smuggling, restoring feat(selfhost): wire claude --append-system-prompt for review instructions (v2 refinement) #1471's original "unambiguously SYSTEM, not user content" design intent.codexis unaffected (uses--sandbox read-only, not--permission-mode, and has no CLI-native system-prompt-file equivalent per #1471's own documented limitation — keeps the existing textual-prepend approach).