Skip to content

Commit a31f6b9

Browse files
igerberclaude
andcommitted
Address PR #415 R2 review (2 P1 sibling-surface drift)
R2 surfaced two cascading P1 findings — both sibling-surface drift from R0's mandate substitution and assessment-criteria tightening that didn't propagate to all reviewer-facing surfaces. R2 P1 #1 — adapted prompt still instructed impossible tool-using audits. The Mandate substitution removed shell-grep claims, but pr_review.md's Rules section (line 139-142) and Re-review Scope (line 207) still said the "Mandate above authorizes broader audits (sibling surfaces, pattern-wide greps, reciprocal checks, transitive deps)". Both reviewers are now single-shot with no shell access, so these references were misleading and contradicted the substituted Mandate. Rewrote both bullets to scope audits to the loaded context and explicitly call out single-shot constraints. R2 P1 #2 — P2-blocking verdict bar wasn't mirrored across siblings. The Assessment Criteria now says ✅ requires no unmitigated P0/P1/P2, but three sibling surfaces still treated P2 as compatible with ✅: - pr_review.md Re-review Scope (line 211-212): "If all previous P1+ findings are resolved, the assessment should be ✅ even if new P2/P3 items are noticed." - openai_review.py compile_prompt previous-review block (line 1166-1170): same wording, injected into every re-review prompt. - ai-review-local.md (line 400-418): "For ⛔ or ⚠️ (P0/P1 findings)" branch and "For ✅ with P2/P3 findings only" branch. Updated all three to mirror the new rule: P2 blocks ✅ even on re-review; the ⚠️ branch covers P0/P1/P2; the ✅ branch covers P3 only. Tests added: - TestAdaptReviewCriteria.test_no_tool_using_audit_claims_in_either_mode (asserts "pattern-wide greps", "Transitive workflow deps", "transitive deps", "Mandate above authorizes" are absent from adapted prompt in both ci_mode values) - TestAdaptReviewCriteria.test_re_review_scope_uses_new_p2_blocking_rule (asserts old P2-carve-out wording is gone and new "block ✅ just like P1" wording is present) - TestCompilePrompt.test_previous_review_block_uses_new_p2_blocking_rule (asserts compile_prompt's previous-review framing uses "P0/P1/P2 findings have been addressed" and "no new unmitigated P2 findings exist") - TestSkillDocAPIConsistency.test_skill_doc_uses_new_p2_blocking_verdict_bar (asserts ai-review-local.md verdict decision tree uses P0/P1/P2 ⚠️ branch and P3-only ✅ branch) 189 tests pass (was 185). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 7b0210d commit a31f6b9

4 files changed

Lines changed: 127 additions & 15 deletions

File tree

.claude/commands/ai-review-local.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -397,15 +397,15 @@ Review passed with no findings. Suggested next steps:
397397
- /submit-pr — commit and open a pull request
398398
```
399399

400-
**For ⛔ or ⚠️ (P0/P1 findings)**:
400+
**For ⛔ or ⚠️ (P0/P1/P2 findings)**:
401401
```
402402
Options:
403403
1. Enter plan mode to address findings (Recommended)
404404
2. Re-run with --full-registry for deeper methodology context
405405
3. Skip — I'll address these manually
406406
```
407407

408-
**For ✅ with P2/P3 findings only**:
408+
**For ✅ with P3 findings only**:
409409
```
410410
Options:
411411
1. Address findings before submitting
@@ -414,8 +414,8 @@ Options:
414414

415415
**If user chooses to address findings**: Parse the findings from the review output.
416416
The review context is already in the conversation. Start addressing the findings
417-
directly — for P0/P1 issues use `EnterPlanMode` for a structured approach; for P2/P3
418-
issues, fix them directly since they are minor.
417+
directly — for P0/P1/P2 issues use `EnterPlanMode` for a structured approach; for
418+
P3 issues, fix them directly since they are minor.
419419

420420
After fixes are committed, the user re-runs `/ai-review-local` for a follow-up review.
421421
On re-review, the script automatically activates delta-diff mode (comparing only

.claude/scripts/openai_review.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1164,10 +1164,13 @@ def compile_prompt(
11641164
if previous_review:
11651165
sections.append(
11661166
"This is a follow-up review. The previous review's findings are included "
1167-
"below. Focus on whether previous P0/P1 findings have been addressed. "
1167+
"below. Focus on whether previous P0/P1/P2 findings have been addressed. "
11681168
"New findings on unchanged code should be marked \"[Newly identified]\". "
1169-
"If all previous P1+ findings are resolved, the assessment should be "
1170-
"\u2705 even if new P2/P3 items are noticed.\n"
1169+
"If all previous P1+ findings are resolved AND no new unmitigated P2 "
1170+
"findings exist (per the Assessment Criteria above), the assessment should "
1171+
"be \u2705. New unmitigated P2 findings (claim-vs-test mismatches, "
1172+
"public-API docstring drift, missing rendering surfaces) keep the verdict "
1173+
"at \u26a0\ufe0f Needs changes \u2014 they block \u2705 just like P1.\n"
11711174
)
11721175
if structured_findings:
11731176
sections.append("### Full Previous Review\n")

.github/codex/prompts/pr_review.md

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -137,9 +137,12 @@ This project tracks deferred technical debt in `TODO.md` under "Tech Debt from C
137137
are P0/P1 and are not deferrable.
138138

139139
Rules:
140-
- Review the changes introduced by this PR (diff). The Single-Pass Completeness
141-
Mandate above authorizes broader audits (sibling surfaces, pattern-wide greps,
142-
reciprocal checks, transitive deps) — do those upfront rather than deferring.
140+
- Review the changes introduced by this PR (diff). Conduct the audits listed in
141+
the Single-Pass Completeness section above (sibling surfaces, reciprocal
142+
checks, claim-vs-shipped) on the loaded context — do those upfront rather
143+
than deferring. You are a single-shot reviewer with no shell access, so audit
144+
only what is visible in the loaded prompt; do not claim audits that require
145+
greps, file loads, or tool use beyond the provided context.
143146
- Provide a single Markdown report with:
144147
- Overall assessment (see Assessment Criteria below)
145148
- Executive summary (3–6 bullets)
@@ -204,12 +207,14 @@ When this is a re-review (the PR has prior AI review comments):
204207
to distinguish from moving goalposts. Limit these to clear, concrete issues — not
205208
speculative concerns or stylistic preferences.
206209
- New code added since the last review IS in scope for new findings — apply the
207-
Single-Pass Completeness Mandate's audits (sibling surfaces, pattern-wide greps,
208-
reciprocal checks) to that new code in this re-review pass. For UNCHANGED code,
209-
the existing [Newly identified] convention from the bullet above still applies:
210+
Single-Pass Completeness audits (sibling surfaces, reciprocal checks, claim-vs-shipped)
211+
to that new code in this re-review pass, scoped to the loaded context. For UNCHANGED
212+
code, the existing [Newly identified] convention from the bullet above still applies:
210213
new P1+ findings MAY be raised but must be marked "[Newly identified]".
211-
- If all previous P1+ findings are resolved, the assessment should be ✅ even if new
212-
P2/P3 items are noticed.
214+
- If all previous P1+ findings are resolved AND no new unmitigated P2 findings exist
215+
(per the Assessment Criteria above), the assessment should be ✅. Newly identified
216+
unmitigated P2 findings (claim-vs-test mismatches, public-API docstring drift, missing
217+
rendering surfaces) keep the verdict at ⚠️ Needs changes — they block ✅ just like P1.
213218

214219
## Known Anti-Patterns
215220

tests/test_openai_review.py

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -311,6 +311,63 @@ def test_claim_vs_shipped_audit_in_both_modes(self, review_mod):
311311
f"Surface '{surface}' missing in ci_mode={ci_mode}"
312312
)
313313

314+
def test_no_tool_using_audit_claims_in_either_mode(self, review_mod):
315+
"""The adapted prompt (post-substitution) must NOT instruct the
316+
single-shot reviewer to do tool-using audits anywhere — neither in the
317+
Mandate (substituted) nor in the Rules section nor in Re-review Scope.
318+
Both reviewers are now single-shot; references to 'pattern-wide greps'
319+
or 'transitive deps' as required audits are misleading and were the
320+
source of PR #415 R2 P1 (sibling-surface drift).
321+
"""
322+
assert _SCRIPT_PATH is not None
323+
repo_root = _SCRIPT_PATH.parent.parent.parent
324+
prompt_path = repo_root / ".github" / "codex" / "prompts" / "pr_review.md"
325+
if not prompt_path.exists():
326+
pytest.skip("pr_review.md not found")
327+
source = prompt_path.read_text()
328+
for ci_mode in (False, True):
329+
adapted = review_mod._adapt_review_criteria(source, ci_mode=ci_mode)
330+
# These tool-using-audit phrases must not appear ANYWHERE in the
331+
# adapted prompt (Mandate, Rules, or Re-review Scope sections).
332+
for phrase in (
333+
"pattern-wide greps",
334+
"Transitive workflow deps",
335+
"transitive deps",
336+
"Mandate above authorizes",
337+
):
338+
assert phrase not in adapted, (
339+
f"Tool-using-audit phrase '{phrase}' leaked into "
340+
f"adapted prompt (ci_mode={ci_mode})"
341+
)
342+
343+
def test_re_review_scope_uses_new_p2_blocking_rule(self, review_mod):
344+
"""Re-review Scope must mirror the tightened ✅ rule: P2 blocks ✅
345+
even on re-review. Sibling-surface fix from PR #415 R2 P1."""
346+
assert _SCRIPT_PATH is not None
347+
repo_root = _SCRIPT_PATH.parent.parent.parent
348+
prompt_path = repo_root / ".github" / "codex" / "prompts" / "pr_review.md"
349+
if not prompt_path.exists():
350+
pytest.skip("pr_review.md not found")
351+
source = prompt_path.read_text()
352+
# The old wording said "✅ even if new P2/P3 items are noticed".
353+
# The new wording must explicitly say P2 blocks. Check both source
354+
# and adapted (post-substitution) since this section isn't substituted.
355+
old_p2_carve_out = (
356+
"If all previous P1+ findings are resolved, the assessment should "
357+
"be ✅ even if new P2/P3 items are noticed"
358+
)
359+
assert old_p2_carve_out not in source, (
360+
"Re-review Scope still has the old P2-carve-out wording; must be "
361+
"tightened to match Assessment Criteria"
362+
)
363+
# New wording must say P2 blocks, in both source and adapted
364+
for ci_mode in (False, True):
365+
adapted = review_mod._adapt_review_criteria(source, ci_mode=ci_mode)
366+
assert "no new unmitigated P2 findings exist" in adapted, (
367+
f"P2-blocking wording missing in ci_mode={ci_mode}"
368+
)
369+
assert "block ✅ just like P1" in adapted
370+
314371

315372
# ---------------------------------------------------------------------------
316373
# compile_prompt
@@ -346,6 +403,26 @@ def test_includes_previous_review(self, review_mod):
346403
assert "Previous review findings here." in result
347404
assert "follow-up review" in result
348405

406+
def test_previous_review_block_uses_new_p2_blocking_rule(self, review_mod):
407+
"""The previous-review framing in compile_prompt must mirror the
408+
tightened ✅ rule: P2 blocks ✅ even on re-review. Sibling-surface fix
409+
from PR #415 R2 P1.
410+
"""
411+
result = review_mod.compile_prompt(
412+
criteria_text="Criteria.",
413+
registry_content="Registry.",
414+
diff_text="diff content",
415+
changed_files_text="M\tfoo.py",
416+
branch_info="main",
417+
previous_review="Previous review findings here.",
418+
)
419+
# Old (stale) wording must NOT appear
420+
assert "✅ even if new P2/P3 items are noticed" not in result
421+
# New wording must explicitly state P2 blocks
422+
assert "P0/P1/P2 findings have been addressed" in result
423+
assert "no new unmitigated P2 findings exist" in result
424+
assert "block ✅ just like P1" in result
425+
349426
def test_no_previous_review_block_when_none(self, review_mod):
350427
result = review_mod.compile_prompt(
351428
criteria_text="C.",
@@ -1996,6 +2073,33 @@ def test_skill_doc_does_not_reference_chat_completions(self):
19962073
"script uses Responses API at openai_review.py:ENDPOINT"
19972074
)
19982075

2076+
def test_skill_doc_uses_new_p2_blocking_verdict_bar(self):
2077+
"""Skill doc's verdict-handling decision tree must mirror the
2078+
tightened ✅ rule: P2 triggers ⚠️, not ✅. Sibling-surface fix from
2079+
PR #415 R2 P1.
2080+
"""
2081+
assert _SCRIPT_PATH is not None
2082+
repo_root = _SCRIPT_PATH.parent.parent.parent
2083+
doc_path = repo_root / ".claude" / "commands" / "ai-review-local.md"
2084+
if not doc_path.exists():
2085+
pytest.skip("ai-review-local.md not found")
2086+
text = doc_path.read_text()
2087+
# Old (stale) wording must NOT appear
2088+
assert "**For ⛔ or ⚠️ (P0/P1 findings)**" not in text, (
2089+
"Skill doc still uses old P0/P1-only ⚠️ branch; tighten to P0/P1/P2"
2090+
)
2091+
assert "**For ✅ with P2/P3 findings only**" not in text, (
2092+
"Skill doc still has '✅ with P2/P3 findings only' branch; under "
2093+
"the new rule, ✅ allows only P3"
2094+
)
2095+
# New wording must appear
2096+
assert "**For ⛔ or ⚠️ (P0/P1/P2 findings)**" in text
2097+
assert "**For ✅ with P3 findings only**" in text
2098+
assert (
2099+
"for P0/P1/P2 issues use `EnterPlanMode` for a structured approach"
2100+
in text
2101+
)
2102+
19992103

20002104
class TestExtractResponseText:
20012105
def test_prefers_output_text_field(self, review_mod):

0 commit comments

Comments
 (0)