提示词与审查反模式
单轮多文件审查以及在同一会话中自我审查。
提示词与审查反模式 是 CoddyKit 上的免费 Claude Architect 课时。 这是第 3 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Claude Architect 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Claude Architect 课程共包含 4 节课。
本课时的部分内容尚未翻译,以英文显示。
Two Anti-Patterns, One Root Cause
This lesson dissects two review anti-patterns that quietly drain quality from agentic code review: single-pass multi-file review and same-session self-review.
Both share one root cause: asking a single context to do too much at once. When you cram many files into one pass, attention gets diluted. When the same session that wrote the code also reviews it, the author keeps its own reasoning and won't challenge itself.
On the Claude Certified Architect exam (Scenario 5, CI/CD), these are classic distractors. Recognizing them — and knowing the correct structure — is worth real points.
Why Single-Pass Multi-File Review Fails
Imagine handing the model 14 changed files and saying "review this PR." The model spreads finite attention across all of them simultaneously. Subtle per-file bugs get missed, and the cross-file story — how a renamed function ripples through its callers — is never examined deliberately.
Two mechanisms compound the failure:
- Attention dilution: more files in one pass means shallower scrutiny per file.
- Lost-in-the-middle: models attend most to the start and end of context, so files in the middle of a large dump get the least scrutiny.
The fix is not a bigger context window — it is better decomposition.
The Multi-Pass Review Structure
The correct pattern is multi-pass review: a focused per-file local pass on each file, THEN a separate cross-file integration pass that examines how the pieces fit together.
The local passes catch in-file defects with full attention. The integration pass catches the bugs that only exist between files: broken contracts, mismatched signatures, stale callers, inconsistent error handling.
This mirrors a broader exam principle: use fixed pipelines / prompt chaining for known sequential steps, and reserve adaptive decomposition for open-ended investigation. Review has a known shape, so a pipeline fits.
review_files = glob("src/**/*.py", changed_only=True)
# Pass 1: per-file local review (focused attention each)
local_findings = []
for path in review_files:
local_findings += review_one_file(client, path)
# Pass 2: separate cross-file integration review
integration_findings = review_integration(client, review_files)
report = local_findings + integration_findingsWhy Same-Session Self-Review Fails
The second anti-pattern: letting the same session that generated the code also review it. The exam is blunt here — independent / fresh-instance review beats same-session self-review.
The reason is cognitive lock-in. The author retains the reasoning, assumptions, and rationalizations it used while writing. It already "decided" the code is correct, so it tends to confirm rather than challenge. A clean reviewer carries none of that baggage and sees the code as an artifact to interrogate.
Put differently: the generation context biases the review. You want the reviewer biased toward skepticism, not toward the author's earlier conclusions.
Review in an Isolated Session
The remedy is to run review in an isolated session, decoupled from the generation context. In Claude Code CI/CD this is natural: generation and review are separate non-interactive invocations.
For pipelines, always run review with -p / --print (non-interactive) and emit --output-format json so results are machine-parseable. The review job gets only the diff and the criteria — not the chat history that produced the code.
# Generation step (one invocation)
claude -p "Implement the ticket in TICKET.md" \
--output-format json > gen.json
# Review step — SEPARATE, isolated session (no generation history)
claude -p "Review the staged diff against our review criteria." \
--output-format json > review.jsonForking Shares Context — Be Careful
Session controls matter. --resume <name> continues a named session; fork_session branches from a shared point. For review, beware: forking from the generation session carries the author's reasoning forward, recreating the same-session bias you were trying to escape.
Prefer a genuinely fresh session fed a structured summary of what to review. There is also a freshness angle: resumed tool results can be stale if the codebase changed since — sometimes a fresh session with a structured summary beats resuming.
Prompt the Reviewer With Explicit Criteria
An isolated reviewer is only as good as its instructions. Vague prompts ("be more precise," "find bugs") produce noisy, inconsistent output. Explicit criteria win: "flag a comment only when it contradicts the code" beats "check the comments."
For CI specifically, the goal is to minimize false positives — a review that cries wolf gets ignored. Tight, testable criteria keep signal high.
REVIEW_CRITERIA = """You are reviewing a code diff in an isolated session.
Flag an issue ONLY when one of these is true:
- a null/None path can be reached with attacker- or user-controlled input
- a function signature changed but a caller was not updated
- a comment directly contradicts the code it documents
Do NOT flag style, naming, or speculative refactors.
Return [] if nothing meets the bar."""Few-Shot Examples Sharpen the Reviewer
Where ambiguity remains, add 2-4 targeted few-shot examples per ambiguity. The model generalizes from them — it does not merely repeat them. Few-shot is the best lever for consistency, edge cases, output format, and reducing hallucinated findings.
For a reviewer, show one example that should be flagged and one that should NOT. That calibrates the false-positive boundary far better than another paragraph of prose.
FEW_SHOT = """Example A (FLAG):
diff: `def charge(amount):` -> `def charge(amount, currency):`
caller still calls `charge(amount)` => signature/caller mismatch.
Example B (DO NOT FLAG):
rename of a local variable `tmp` -> `buffer` with all uses updated.
No behavioral change => not an issue."""Force Structured Output for Findings
To make review results reliable and parseable, force structured output with a tool plus a JSON Schema. Setting tool_choice to "any" guarantees the model calls some tool, eliminating free-text drift; a forced specific tool gives even tighter control.
Schema discipline matters: mark a field required ONLY if it is always present. Never require a possibly-absent field — the model will fabricate one to satisfy the schema. Use an enum with an "other" value plus a free-text detail field for extensibility.
tools = [{
"name": "report_findings",
"description": "Return code-review findings for the diff.",
"input_schema": {
"type": "object",
"properties": {
"findings": {"type": "array", "items": {
"type": "object",
"properties": {
"file": {"type": "string"},
"category": {"enum": ["bug", "contract", "other"]},
"detail": {"type": "string"}
},
"required": ["file", "category"]
}}
},
"required": ["findings"]
}
}]
resp = client.messages.create(
model="claude-sonnet-4-5", max_tokens=2048,
tools=tools, tool_choice={"type": "any"},
messages=[{"role": "user", "content": review_prompt}])Re-Runs: Report Only New Issues
Review runs repeatedly as a PR evolves. When you re-run, include the prior results and report only new or still-unfixed issues. Re-flagging everything from scratch buries the genuinely new problems and trains reviewers to ignore the bot.
This also keeps the integration pass honest: a fix in one file may introduce a fresh cross-file break, and that is exactly what the next run should surface — not the noise that was already resolved.
prior = json.load(open("review.prev.json"))
prompt = f"""Re-review the current diff in an isolated session.
Prior findings (already reported): {json.dumps(prior)}
Report ONLY issues that are new or remain unfixed.
Do not repeat findings the author has resolved."""Don't Reach for the Batch API Here
One last trap. Pre-merge / blocking review is time-sensitive, so it does NOT belong on the Message Batches API. Batches are 50% cheaper with up to a 24h window but carry no latency SLA and do not support multi-turn tool calling — wrong for anything blocking a merge.
Reserve the Batch API for non-blocking jobs: overnight audits, nightly full-repo sweeps, bulk report generation. Use custom_id to correlate requests and re-submit only the failures. Pre-merge gating stays on standard, low-latency calls.
Quick Check: Designing the Review Stage
A teammate's CI calls Claude Code to review pull requests. It resumes the same session that generated the code and asks it to review all 14 changed files in one prompt. False positives are high and real cross-file bugs slip through. Which redesign best fixes this?
Recap: Review Like an Architect
Key takeaways:
- Avoid single-pass multi-file review — it dilutes attention and the middle gets lost. Do per-file local passes THEN a separate cross-file integration pass.
- Avoid same-session self-review — the author retains its reasoning and won't challenge itself. Review in a fresh, isolated session; beware that forking/resuming carries bias and stale results.
- Prompt with explicit criteria + 2-4 few-shot examples to minimize false positives.
- Force structured output (tool + schema,
tool_choice:"any"); require only always-present fields. - On re-runs, report only new/unfixed issues.
- Keep blocking review off the Batch API — no latency SLA; reserve batches for overnight audits.
常见问题解答
「提示词与审查反模式」课时是免费的吗?
是的 — 「提示词与审查反模式」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Claude Architect 课程的其余内容,请升级到 CoddyKit PRO。 Claude Architect 课程共包含 4 节课。
「提示词与审查反模式」这节课中我会学到什么?
单轮多文件审查以及在同一会话中自我审查。 你通过在浏览器中直接运行的动手代码来练习 Claude Architect,全天候 AI 导师会在你学习这节课的过程中回答你的问题。
学习 Claude Architect 需要有经验吗?
无需任何先前经验。CoddyKit 上的 Claude Architect 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 3 节课,共 4 节。
「提示词与审查反模式」课时需要多长时间?
大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。
我能在这节 Claude Architect 课中编写并运行代码吗?
能。每节 Claude Architect 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。