From 4312089166eded935d6bc4297b0053d0722accc7 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 12 Jul 2026 21:31:04 +0900 Subject: [PATCH 1/3] Tighten OpenCode peer static-analysis review --- ci-review-prompt.md | 1 + code-reviewer-prompt.md | 1 + 2 files changed, 2 insertions(+) diff --git a/ci-review-prompt.md b/ci-review-prompt.md index 7d3d8188..f4d3207a 100644 --- a/ci-review-prompt.md +++ b/ci-review-prompt.md @@ -133,6 +133,7 @@ before deciding. Do not merely quote, summarize, or defer to the peer reviewer. If you would otherwise approve but cannot source-back either a fix or a false-positive dismissal for each plausible peer finding, request changes with your own line-specific finding and verification direction. +When another review bot reports a plausible current-head static-analysis, linter, compiler, or accessibility defect, verify the claim independently before approving. For JSX/TSX and component templates, duplicate props such as repeated `aria-label`, repeated event handlers, or assignments overwritten later in the same element/object are blocking when they can mask the intended accessible name, event behavior, data binding, or runtime value. Do not approve by merely citing the peer bot; inspect the changed hunk or run the relevant parser/linter/typecheck in a scratch workspace, then either publish your own source-backed finding or explain the source-backed false-positive dismissal. Review the diff first, then inspect surrounding code only when needed to understand impact. Evaluate correctness, API compatibility, security/privacy, diff --git a/code-reviewer-prompt.md b/code-reviewer-prompt.md index a37fba11..af28a828 100644 --- a/code-reviewer-prompt.md +++ b/code-reviewer-prompt.md @@ -134,6 +134,7 @@ between PR intent, code, docs, tests, schemas, generated files, UI rendering, and consumers. For changed scrolling, animation, transition, or motion behavior, verify that `prefers-reduced-motion: reduce` users are not forced through smooth scrolling or animated motion. +Treat peer review bot comments as adversarial seeds, not authority. If a peer bot flags a plausible current-head static-analysis, compiler, linter, or accessibility issue, independently verify it from the source hunk, parser/linter/typecheck output, runtime/library documentation, or a scratch repro before approving. In JSX/TSX and component templates, duplicate props such as repeated `aria-label`, repeated handlers, or assignments overwritten later in the same element/object are material defects when they can mask the intended accessible name, event behavior, data binding, or runtime value; report your own source-backed finding instead of merely quoting the peer bot. Implementation completeness is mandatory. Inspect changed runtime code and connected call sites for placeholder bodies such as `pass`, `...`, From 00e358468464446fe520b5c01d53efbfcb4a13ae Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 12 Jul 2026 23:01:27 +0900 Subject: [PATCH 2/3] Bound OpenCode prompt evidence packet size --- scripts/ci/run_opencode_review_model_pool.sh | 21 +++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/scripts/ci/run_opencode_review_model_pool.sh b/scripts/ci/run_opencode_review_model_pool.sh index 96d41ea4..ac8e3c15 100644 --- a/scripts/ci/run_opencode_review_model_pool.sh +++ b/scripts/ci/run_opencode_review_model_pool.sh @@ -93,7 +93,26 @@ write_prompt() { printf '```\n' if [ -s "$evidence_excerpt_file" ]; then printf '\nCurrent-head evidence packet:\n\n' - cat "$evidence_excerpt_file" + python3 - "$evidence_excerpt_file" "${OPENCODE_PROMPT_EVIDENCE_MAX_BYTES:-120000}" <<'PY' +import pathlib +import sys + +path = pathlib.Path(sys.argv[1]) +max_bytes = int(sys.argv[2]) +data = path.read_bytes() +if len(data) <= max_bytes: + sys.stdout.buffer.write(data) +else: + head = data[: max_bytes // 2] + tail = data[-(max_bytes // 2) :] + sys.stdout.buffer.write(head) + sys.stdout.write( + "\n\n[OpenCode evidence excerpt truncated for provider context window; " + f"showing {len(head)} head bytes and {len(tail)} tail bytes from {len(data)} total bytes. " + "Read the full bounded-review-evidence.md file before making any source-backed conclusion.]\n\n" + ) + sys.stdout.buffer.write(tail) +PY printf '\n' fi } >"$prompt_file" From c1d9ec20f23b3ff07d924da85e6df7575276536b Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Mon, 13 Jul 2026 00:33:20 +0900 Subject: [PATCH 3/3] fix(opencode): keep GitHub Models prompts under context limit --- scripts/ci/run_opencode_review_model_pool.sh | 36 ++++++++++++-- tests/test_opencode_model_pool_runner.py | 51 +++++++++++++++++++- 2 files changed, 83 insertions(+), 4 deletions(-) diff --git a/scripts/ci/run_opencode_review_model_pool.sh b/scripts/ci/run_opencode_review_model_pool.sh index ac8e3c15..21d765d5 100644 --- a/scripts/ci/run_opencode_review_model_pool.sh +++ b/scripts/ci/run_opencode_review_model_pool.sh @@ -58,12 +58,29 @@ backoff_sleep() { printf '%s\n' "$sleep_for" } +should_inline_prompt_evidence_excerpt() { + local model_candidate="$1" + + # GitHub Models OpenAI review endpoints currently reject request bodies + # above roughly 4000 tokens. Keep full evidence available as workspace + # files, but do not inline the excerpt for those candidates. + case "$model_candidate" in + github-models/openai/gpt-5 | github-models/openai/gpt-5-chat | github-models/openai/o3) + return 1 + ;; + *) + return 0 + ;; + esac +} + write_prompt() { local model_candidate="$1" local prompt_file="$2" local intro local contract_file local evidence_excerpt_file + local evidence_file_in_workdir if [ -n "${OPENCODE_REVIEW_INTRO:-}" ]; then intro="$OPENCODE_REVIEW_INTRO" @@ -72,6 +89,7 @@ write_prompt() { fi contract_file="$OPENCODE_REVIEW_WORKDIR/opencode-review-contract-${model_candidate//\//-}.md" evidence_excerpt_file="$OPENCODE_REVIEW_WORKDIR/bounded-review-evidence-excerpt.md" + evidence_file_in_workdir="$OPENCODE_REVIEW_WORKDIR/bounded-review-evidence.md" cp "$GITHUB_WORKSPACE/scripts/ci/opencode_review_prompt_template.md" "$contract_file" OPENCODE_REVIEW_INTRO="$intro" \ PROMPT_MODEL_CANDIDATE="$model_candidate" \ @@ -82,9 +100,17 @@ write_prompt() { printf 'Follow the complete review contract in `%s`; use this launcher as a packet-first entry point, not as a reduced policy.\n' "$contract_file" printf 'Read bounded review evidence from `%s` and source files from `%s` when tool access works.\n' "$OPENCODE_EVIDENCE_FILE" "$OPENCODE_SOURCE_WORKDIR" printf 'Use the trusted review workspace `%s` for scripts, prompts, policy files, CodeGraph config, and validation helpers.\n\n' "$OPENCODE_REVIEW_WORKDIR" - printf 'First review the current-head evidence excerpt in this prompt. Then inspect full evidence, changed files, focused related code, and configured structural/search tools when available.\n' + if should_inline_prompt_evidence_excerpt "$model_candidate"; then + printf 'First review the current-head evidence excerpt in this prompt. Then inspect full evidence, changed files, focused related code, and configured structural/search tools when available.\n' + else + printf 'The current-head evidence excerpt is not inlined for this GitHub Models OpenAI candidate because that provider rejects large request bodies. First read `%s`, `%s`, changed files, focused related code, and configured structural/search tools before any conclusion.\n' "$evidence_file_in_workdir" "$evidence_excerpt_file" + fi printf 'Never emit raw tool-call markup, MCP call syntax, function-call JSON, tool_call text, or a JSON array of tool calls. If tool calls or file reads are unavailable, do not emit progress notes or raw tool-call text.\n' - printf 'If full-file reads do not execute, use the inlined evidence packet and its repeated current-head sections for Changed files, Focused changed hunks, Coverage execution evidence, Failed GitHub Check evidence, and unresolved thread evidence.\n' + if should_inline_prompt_evidence_excerpt "$model_candidate"; then + printf 'If full-file reads do not execute, use the inlined evidence packet and its repeated current-head sections for Changed files, Focused changed hunks, Coverage execution evidence, Failed GitHub Check evidence, and unresolved thread evidence.\n' + else + printf 'If file reads do not execute for this non-inlined prompt, do not approve from memory or generic confidence. REQUEST_CHANGES only when the visible launcher text or executed file reads provide current-head evidence tied to a positive source/evidence line.\n' + fi printf 'Do not request changes solely because your tool call, MCP call, or full-file read was not executed. Treat that as a review source limitation unless current-head evidence explicitly reports a materialization failure; any such finding must be tied to that evidence, not a generic model-exhaustion message. REQUEST_CHANGES findings must cite a positive source/evidence line; never use line 0.\n' printf 'Always return a final control block instead of a progress summary. Return only the final review body.\n\n' printf 'Required control block shape:\n' @@ -93,7 +119,8 @@ write_prompt() { printf '```\n' if [ -s "$evidence_excerpt_file" ]; then printf '\nCurrent-head evidence packet:\n\n' - python3 - "$evidence_excerpt_file" "${OPENCODE_PROMPT_EVIDENCE_MAX_BYTES:-120000}" <<'PY' + if should_inline_prompt_evidence_excerpt "$model_candidate"; then + python3 - "$evidence_excerpt_file" "${OPENCODE_PROMPT_EVIDENCE_MAX_BYTES:-120000}" <<'PY' import pathlib import sys @@ -113,6 +140,9 @@ else: ) sys.stdout.buffer.write(tail) PY + else + printf '[Evidence excerpt omitted for `%s` to stay under the GitHub Models OpenAI request-body limit. Read `%s` and `%s` from the review workspace before returning a control block.]\n' "$model_candidate" "$evidence_file_in_workdir" "$evidence_excerpt_file" + fi printf '\n' fi } >"$prompt_file" diff --git a/tests/test_opencode_model_pool_runner.py b/tests/test_opencode_model_pool_runner.py index 91e16f8a..69b53f57 100644 --- a/tests/test_opencode_model_pool_runner.py +++ b/tests/test_opencode_model_pool_runner.py @@ -61,6 +61,9 @@ def run_failed_model( *, json_line: str = "", stderr_line: str = "", + evidence_excerpt: str = "", + model_candidates: str = "github-models/openai/gpt-5", + prompt_capture: Path | None = None, ) -> subprocess.CompletedProcess[str]: """Run one fake provider failure through the real model-pool launcher.""" command = bash_command() @@ -74,10 +77,18 @@ def run_failed_model( shutil.copy2(ROOT / "opencode.jsonc", review_dir / "opencode.jsonc") evidence_file = tmp_path / "evidence.md" evidence_file.write_text("bounded current-head evidence\n", encoding="utf-8") + if evidence_excerpt: + (review_dir / "bounded-review-evidence-excerpt.md").write_text( + evidence_excerpt, encoding="utf-8" + ) + (review_dir / "bounded-review-evidence.md").write_text( + f"full evidence\n{evidence_excerpt}", encoding="utf-8" + ) fake_opencode = fake_bin / "opencode" fake_opencode.write_text( "#!/usr/bin/env bash\n" "if [ \"${1:-}\" = run ]; then\n" + " [ -z \"${FAKE_OPENCODE_PROMPT_CAPTURE:-}\" ] || printf '%s\\n' \"$2\" > \"$FAKE_OPENCODE_PROMPT_CAPTURE\"\n" " [ -z \"${FAKE_OPENCODE_JSON:-}\" ] || printf '%s\\n' \"$FAKE_OPENCODE_JSON\"\n" " [ -z \"${FAKE_OPENCODE_STDERR:-}\" ] || printf '%s\\n' \"$FAKE_OPENCODE_STDERR\" >&2\n" " exit 1\n" @@ -92,13 +103,14 @@ def run_failed_model( env.update( { "FAKE_OPENCODE_JSON": json_line, + "FAKE_OPENCODE_PROMPT_CAPTURE": bash_path(prompt_capture) if prompt_capture else "", "FAKE_OPENCODE_STDERR": stderr_line, "GITHUB_OUTPUT": bash_path(github_output), "GITHUB_WORKSPACE": bash_path(ROOT), "HEAD_SHA": "1" * 40, "OPENCODE_EVIDENCE_FILE": bash_path(evidence_file), "OPENCODE_MODEL_ATTEMPTS": "1", - "OPENCODE_MODEL_CANDIDATES": "github-models/openai/gpt-5", + "OPENCODE_MODEL_CANDIDATES": model_candidates, "OPENCODE_OUTPUT_FILE": bash_path(tmp_path / "selected-output.md"), "OPENCODE_POOL_MAX_CYCLES": "1", "OPENCODE_REVIEW_WORKDIR": bash_path(review_dir), @@ -160,3 +172,40 @@ def test_failed_provider_without_reason_logs_explicit_absence(tmp_path: Path) -> "OpenCode provider failure supplied no structured JSON or stderr reason " "(json-bytes=0, stderr-bytes=0)." ) in result.stdout + + +def test_github_models_openai_prompt_references_evidence_without_inlining(tmp_path: Path) -> None: + """Small-request GitHub Models OpenAI candidates keep evidence as files.""" + prompt_capture = tmp_path / "captured-prompt.md" + evidence_excerpt = "UNIQUE_CURRENT_HEAD_EVIDENCE_PACKET" + + result = run_failed_model( + tmp_path, + evidence_excerpt=evidence_excerpt, + prompt_capture=prompt_capture, + ) + + assert result.returncode == 1 + prompt = prompt_capture.read_text(encoding="utf-8") + assert evidence_excerpt not in prompt + assert "Evidence excerpt omitted for `github-models/openai/gpt-5`" in prompt + assert "bounded-review-evidence.md" in prompt + assert "bounded-review-evidence-excerpt.md" in prompt + + +def test_deepseek_prompt_still_inlines_bounded_evidence_excerpt(tmp_path: Path) -> None: + """Large-context DeepSeek candidates retain the current-head prompt packet.""" + prompt_capture = tmp_path / "captured-prompt.md" + evidence_excerpt = "UNIQUE_DEEPSEEK_INLINE_EVIDENCE_PACKET" + + result = run_failed_model( + tmp_path, + evidence_excerpt=evidence_excerpt, + model_candidates="github-models/deepseek/deepseek-v3-0324", + prompt_capture=prompt_capture, + ) + + assert result.returncode == 1 + prompt = prompt_capture.read_text(encoding="utf-8") + assert evidence_excerpt in prompt + assert "Evidence excerpt omitted" not in prompt