diff --git a/.github/workflows/claude-review.yml b/.github/workflows/claude-review.yml index ce038c7..fef4aab 100644 --- a/.github/workflows/claude-review.yml +++ b/.github/workflows/claude-review.yml @@ -6,8 +6,9 @@ name: Claude review # 1. A deterministic policy (scripts/policy.py) decides the lowest risk the # PR can have from its paths alone: the reviewer can raise it, never # lower it. The floor also picks the model and the effort: a low floor -# (docs, tests, lockfiles) goes to the light model at low effort, -# anything else to the strong one, as the policy files say; a repository +# (docs, tests, lockfiles) goes to the light model at low effort, a +# medium one to the light model at medium effort, a high one to the +# strong model, as the policy files say; a repository # overrides any level in its .github/review-policy.yml (`review:`), which # is read from the base branch so a change cannot pick its own reviewer. At a low floor the brief carries the profiles and the diff # only; AGENTS.md and docs/architecture.md are added above it. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 0d9d0a0..1c5042a 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -70,7 +70,7 @@ Pull requests from branches of the repository (not drafts, not forks) are review - The first review reads the whole change; later ones read only what you pushed since, so keep pushes meaningful. Editing the title or description does not trigger a new review; an edited description counts as unchecked (no auto-merge) until the next push or the `review:full` label. - The review decides the type of the change from the diff and sets it as a `type:*` label; it corrects the title's type to match (the version number is computed from these labels). If it is wrong, set a different `type:*` label yourself: the bot keeps a label a person set. -- Low-risk changes (docs, tests, lockfiles) get the light model; everything else the strong one. +- Low- and medium-risk changes get the light model (low effort for docs, tests and lockfiles, medium for ordinary code); high-risk ones the strong one. - After 5 automatic reviews the next push keeps the last verdict and a human merges: add the `review:full` label, then push or re-run the review, to ask for another full pass. - It merges on its own only when the change touches only low-risk paths, the review rated it low risk and low complexity without blocking, the description matches the code (nothing claimed the diff does not do, no behaviour change left unsaid), the author is a trusted maintainer (or Dependabot), every required check is green and the policy has auto-merge on. Anything else, a maintainer merges. @@ -118,7 +118,7 @@ When AI took part, say so in one sober line at the end of the pull request descr - **AI-assisted:** a person wrote or directed the change and an AI helped. - **AI-generated:** an AI wrote the change and a person reviewed it. -- Several models: `🤖 AI-generated · Claude Opus 5.5, Claude Sonnet 5 (Anthropic)`. +- Several models: `🤖 AI-generated · Claude Opus 5.5, Claude Sonnet 5.5 (Anthropic)`. - The same line closes any issue or pull request comment an agent writes for someone. - No product advertising: CI rejects a description that says "Generated with Claude Code" or similar. diff --git a/README.md b/README.md index 83505ad..22d3a13 100644 --- a/README.md +++ b/README.md @@ -86,7 +86,7 @@ is in the run alone. code: - "bin/**" review: - medium: { model: claude-sonnet-5, effort: medium } + high: { model: claude-opus-5-5, effort: high } budget-usd: 2 auto-merge: true ``` diff --git a/policy/review-policy.default.yml b/policy/review-policy.default.yml index 8de0e94..2cd9ceb 100644 --- a/policy/review-policy.default.yml +++ b/policy/review-policy.default.yml @@ -28,8 +28,8 @@ high-risk: # what it leaves out stays as here. Replies to @dilux-bot and the weekly # learnings use the `high` reviewer. review: - low: { model: claude-sonnet-5, effort: low } - medium: { model: claude-opus-5-5, effort: medium } + low: { model: claude-sonnet-5-5, effort: low } + medium: { model: claude-sonnet-5-5, effort: medium } high: { model: claude-opus-5-5, effort: medium } # The most one review run may spend, in USD. A repository can lower or raise it. diff --git a/scripts/policy.py b/scripts/policy.py index 0962ce0..0e739ca 100644 --- a/scripts/policy.py +++ b/scripts/policy.py @@ -208,15 +208,16 @@ def self_test(): here = os.path.dirname(os.path.abspath(__file__)) default = os.path.join(here, "..", "policy", "review-policy.default.yml") with tempfile.NamedTemporaryFile("w", suffix=".yml", delete=False, encoding="utf-8") as fh: - fh.write("auto-merge: false\nreview:\n low: {model: claude-sonnet-5}\n medium: {model: claude-opus-5-5}\n high: {model: claude-opus-5-5}\n") + fh.write("auto-merge: false\nreview:\n low: {model: claude-sonnet-5-5}\n medium: {model: claude-sonnet-5-5}\n high: {model: claude-opus-5-5}\n") org_off = fh.name cases = [ # (name, defaults, repo policy, files, extra env, expected outputs, expected exit) - ("docs only is low", default, "", ["docs/a.md", "README.md"], {}, {"floor": "low", "model": "claude-sonnet-5"}, 0), + ("docs only is low", default, "", ["docs/a.md", "README.md"], {}, {"floor": "low", "model": "claude-sonnet-5-5"}, 0), ("tests and translations only are low", default, "", ["tests/Unit/ATest.php", "languages/x.pot"], {}, {"floor": "low"}, 0), ("compiled translations are not low: nobody can read them", default, "", ["languages/x-es_AR.mo"], {}, {"floor": "medium"}, 0), ("their sources and template are", default, "", ["languages/x-es_AR.po", "languages/x.pot"], {}, {"floor": "low"}, 0), - ("code is medium", default, "", ["includes/a.php"], {}, {"floor": "medium"}, 0), + ("code is medium", default, "", ["includes/a.php"], {}, {"floor": "medium", "model": "claude-sonnet-5-5", "effort": "medium"}, 0), + ("a workflow gets the strong reviewer", default, "", [".github/workflows/a.yml"], {}, {"floor": "high", "model": "claude-opus-5-5"}, 0), ("docs plus code is medium", default, "", ["docs/a.md", "includes/a.php"], {}, {"floor": "medium"}, 0), ("a workflow is high", default, "", [".github/workflows/a.yml"], {}, {"floor": "high"}, 0), ("AGENTS.md is high, though it is Markdown", default, "", ["AGENTS.md"], {}, {"floor": "high"}, 0),