Problem
Today buildReviewPrompt in plugins/opencode/scripts/lib/prompts.mjs unconditionally embeds the full git diff output into the review prompt:
// prompts.mjs:32-36
diff = await getDiff(cwd, { base: opts.base });
status = await getStatus(cwd);
changedFiles = await getChangedFiles(cwd, { base: opts.base });
// ...
if (diff) {
sections.push(`<diff>\n${diff}\n</diff>`);
}
For moderate/large changesets (upstream repro: ~4500-line markdown corpus, also 148 files / ~19.5k LOC) this blows out the prompt, triggers HTTP 400 / content-too-large errors on the OpenCode backend, or silently causes the model to skim and return shallow findings.
Fix (from upstream PR)
Classify the review scope before embedding, and fall back to a lightweight "self-collect" context when either the file count or total diff byte size exceeds thresholds:
DEFAULT_INLINE_DIFF_MAX_FILES = 2
DEFAULT_INLINE_DIFF_MAX_BYTES = 256 * 1024
When the scope is small, include the full diff as today. When it's larger, emit a lightweight context (status + diff stat + changed-files list + untracked-file pointers only) and add a guidance line to the prompt telling the model to inspect the diff itself via read-only git commands:
The repository context below is a lightweight summary. Inspect the target diff yourself with read-only git commands before finalizing findings.
Implementation sketch for opencode
This is cleaner than the upstream Codex version because opencode doesn't have the broker/app-server layering. Concrete changes:
-
lib/git.mjs: add a measureDiffBytes(cwd, base, maxBytes) helper that uses git diff --shortstat and git diff with maxBuffer to cap the read.
-
lib/prompts.mjs::buildReviewPrompt: compute { diffBytes, fileCount } before building the context. If fileCount > 2 or diffBytes > 256 KB, set includeDiff = false and switch to the lightweight branch.
-
lib/prompts.mjs::buildReviewContext: accept an includeDiff flag. When false, emit <diff_stat> and <changed_files> only, skip <diff>, and append the self-collect guidance.
-
prompts/adversarial-review.md: add a {{REVIEW_COLLECTION_GUIDANCE}} placeholder so the lightweight mode can inject its guidance line.
Reference code from upstream
// lib/git.mjs additions
const DEFAULT_INLINE_DIFF_MAX_FILES = 2;
const DEFAULT_INLINE_DIFF_MAX_BYTES = 256 * 1024;
function measureGitOutputBytes(cwd, args, maxBytes) {
const result = git(cwd, args, { maxBuffer: maxBytes + 1 });
if (result.error?.code === "ENOBUFS") return maxBytes + 1;
if (result.status !== 0) throw new Error(formatCommandFailure(result));
return Buffer.byteLength(result.stdout, "utf8");
}
// In the review-context builder:
const diffBytes = measureGitOutputBytes(cwd, ["diff", base ? `${base}...HEAD` : "HEAD"], DEFAULT_INLINE_DIFF_MAX_BYTES);
const includeDiff = changedFiles.length <= DEFAULT_INLINE_DIFF_MAX_FILES
&& diffBytes <= DEFAULT_INLINE_DIFF_MAX_BYTES;
const collectionGuidance = includeDiff
? "Use the repository context below as primary evidence."
: "The repository context below is a lightweight summary. Inspect the target diff yourself with read-only git commands before finalizing findings.";
Test plan
- Small diff (1 file, 10 LOC) -> inline mode,
<diff> present.
- 3-file diff -> self-collect mode, no
<diff>, guidance line present, <changed_files> present.
- 1-file diff >256 KB -> self-collect mode.
- PR review via
--pr N -> threshold evaluated against PR diff size (keep the existing gh pr diff path, just measure its output).
Upstream reference
openai/codex-plugin-cc#179 (merged 2026-04-08), closes upstream #11.
Port of openai/codex-plugin-cc#179 (merged)
Problem
Today
buildReviewPromptinplugins/opencode/scripts/lib/prompts.mjsunconditionally embeds the fullgit diffoutput into the review prompt:For moderate/large changesets (upstream repro: ~4500-line markdown corpus, also 148 files / ~19.5k LOC) this blows out the prompt, triggers HTTP 400 / content-too-large errors on the OpenCode backend, or silently causes the model to skim and return shallow findings.
Fix (from upstream PR)
Classify the review scope before embedding, and fall back to a lightweight "self-collect" context when either the file count or total diff byte size exceeds thresholds:
DEFAULT_INLINE_DIFF_MAX_FILES = 2DEFAULT_INLINE_DIFF_MAX_BYTES = 256 * 1024When the scope is small, include the full diff as today. When it's larger, emit a lightweight context (status + diff stat + changed-files list + untracked-file pointers only) and add a guidance line to the prompt telling the model to inspect the diff itself via read-only git commands:
Implementation sketch for opencode
This is cleaner than the upstream Codex version because opencode doesn't have the broker/app-server layering. Concrete changes:
lib/git.mjs: add ameasureDiffBytes(cwd, base, maxBytes)helper that usesgit diff --shortstatandgit diffwithmaxBufferto cap the read.lib/prompts.mjs::buildReviewPrompt: compute{ diffBytes, fileCount }before building the context. IffileCount > 2ordiffBytes > 256 KB, setincludeDiff = falseand switch to the lightweight branch.lib/prompts.mjs::buildReviewContext: accept anincludeDiffflag. When false, emit<diff_stat>and<changed_files>only, skip<diff>, and append the self-collect guidance.prompts/adversarial-review.md: add a{{REVIEW_COLLECTION_GUIDANCE}}placeholder so the lightweight mode can inject its guidance line.Reference code from upstream
Test plan
<diff>present.<diff>, guidance line present,<changed_files>present.--pr N-> threshold evaluated against PR diff size (keep the existinggh pr diffpath, just measure its output).Upstream reference
openai/codex-plugin-cc#179 (merged 2026-04-08), closes upstream #11.