From 157e934355425ac3ad54cf34212ed21c2745beb8 Mon Sep 17 00:00:00 2001 From: Remigiusz Antczak Date: Fri, 23 Oct 2026 22:18:23 +0200 Subject: [PATCH] Add read/output budget to the small-diff review fast path One-line BUDGET rule in deep-code-review SKILL.md: git diff --stat -p as the one patch read, grep callers and callees then offset/limit reads, tail -n 40 on test and CI output, no narration. Security checks unchanged. Pinned by scripts/test_review_read_budget.py and a new eval case. Tests: 8/8 (test_review_read_budget 1, test_always_loaded_bytes 6, mustload gate, size-ratchet gate) Co-Authored-By: Claude Sonnet 5.5 Claude-Session: https://claude.ai/code/session_014QNFFPWVcPUbeuvwM5fk2Z --- .claude/skills/deep-code-review/SKILL.md | 2 ++ .../skills/deep-code-review/evals/evals.json | 12 ++++++++++ changelog.d/review-read-budget.md | 2 ++ scripts/test_review_read_budget.py | 23 +++++++++++++++++++ 4 files changed, 39 insertions(+) create mode 100644 changelog.d/review-read-budget.md create mode 100644 scripts/test_review_read_budget.py diff --git a/.claude/skills/deep-code-review/SKILL.md b/.claude/skills/deep-code-review/SKILL.md index 7b465dce3..a6dc871ca 100644 --- a/.claude/skills/deep-code-review/SKILL.md +++ b/.claude/skills/deep-code-review/SKILL.md @@ -21,4 +21,6 @@ You are a senior reviewer hunting defects that a change introduces. For a small 4. One finding per distinct mechanism, most severe first, at most 8. 5. Guarantees: for each guarantee-bearing comment, docstring or UI string in the diff (never, always, exactly once, consent enforced), name the test that forces the adversarial case it denies; an unpinned guarantee is a finding, High if it guards privacy, consent, money or data. +BUDGET (small DIFF): `git diff --stat -p` is the one patch read; grep the callers and callees of each changed symbol and Read those ranges, and the context around each hunk, with offset/limit; read a whole file only if under ~200 lines; pipe test and CI output through `tail -n 40`; no narration between tool calls. This never skips a security check above. + OUTPUT. Final message: the severity-ranked findings, each as `file:line`, severity, mechanism and failing input in one or two sentences. Report template: `references/full-map-report.md`. diff --git a/.claude/skills/deep-code-review/evals/evals.json b/.claude/skills/deep-code-review/evals/evals.json index 72eb0be9e..8bd90c0b4 100644 --- a/.claude/skills/deep-code-review/evals/evals.json +++ b/.claude/skills/deep-code-review/evals/evals.json @@ -8316,6 +8316,18 @@ "States that a routing match skips INDEX.md", "Does not read INDEX.md before the full-map.md routing" ] + }, + { + "id": "small-diff-read-budget", + "prompt": "Review a 120-line diff across three files. How do you read and run things?", + "expected_output": "Runs the diff stat first, locates with grep, Reads with offset/limit around each hunk (whole file only if under ~200 lines), pipes test/CI output through tail -n 40, no narration between tool calls; security checks unchanged.", + "expectations": [ + "Runs git diff --stat before reading per-file diffs", + "Uses grep then Read with offset/limit around hunks, no whole-file read of files over ~200 lines", + "Pipes test and CI output through tail -n 40", + "Emits no narration between tool calls", + "Does not skip any security check to save tokens" + ] } ] } diff --git a/changelog.d/review-read-budget.md b/changelog.d/review-read-budget.md new file mode 100644 index 000000000..ac6901ac3 --- /dev/null +++ b/changelog.d/review-read-budget.md @@ -0,0 +1,2 @@ +### Changed +- `deep-code-review` small-diff fast path gains a one-line read/output budget: `git diff --stat` first, grep to locate then Read with offset/limit around each hunk (whole file only under ~200 lines), test and CI output through `tail -n 40`, no narration between tool calls. Targets Read results and Bash output, the two largest review-cost shares; the security checks are unchanged. Pinned by `scripts/test_review_read_budget.py` and the `small-diff-read-budget` eval. diff --git a/scripts/test_review_read_budget.py b/scripts/test_review_read_budget.py new file mode 100644 index 000000000..7121d2af3 --- /dev/null +++ b/scripts/test_review_read_budget.py @@ -0,0 +1,23 @@ +"""The small-diff fast path in SKILL.md carries the read/output budget rule and keeps the security floor.""" +import re +import unittest +from pathlib import Path + +SKILL = Path(__file__).resolve().parent.parent / ".claude/skills/deep-code-review/SKILL.md" + + +class ReadBudget(unittest.TestCase): + def test_rule_in_fast_path(self): + s = SKILL.read_text() + m = re.search(r"^BUDGET \(small DIFF\):.*$", s, re.M) + self.assertTrue(m, "BUDGET line missing") + for needle in ("git diff --stat -p", "grep", "callers", "offset/limit", "~200 lines", "tail -n 40", "no narration"): + self.assertIn(needle, m.group(0)) + self.assertLess(m.start(), s.index("\nOUTPUT."), "rule must sit in the fast path") + self.assertIn("never skips a security check", m.group(0)) + self.assertRegex(s, r"(?m)^1\. Read every hunk") + self.assertRegex(s, r"(?m)^5\. Guarantees:") + + +if __name__ == "__main__": + unittest.main()