Stricter reviews for critical code
Some code deserves a harder look: payments and billing, login and permissions, database migrations, infrastructure. This guide sets Gryndel up to review that code more thoroughly, to block merges on more serious findings, and to make sure nobody can quietly relax those settings.
When to do this: after your pilot, once the team trusts Gryndel's findings. Strict settings on a repository where Gryndel is often wrong just block people for no reason. When not to: don't make every repository strict "to be safe". The point is to spend extra attention, and extra model cost, where a mistake is expensive.
Before you start: you need to be a workspace admin in Gryndel. Step 5 needs the Maintainer role (or higher) on the project in GitLab, or admin access to the repository on GitHub.
What you'll set up
| Layer | What it gives you | Step |
|---|---|---|
| Agents mode | Specialist reviewers (security, database and so on) look at the files they know about | 1 |
| A lower Fail commit status on | P1 findings fail the commit, not just P0 | 2 |
| Rules | Your own policies for the critical code | 3 |
| Organization locks | Repository files can't weaken the settings | 4 |
| A required status in GitLab or GitHub | A failed Gryndel status stops the merge | 5 |
You can do the steps in any order, but test each one on a merge request (GitLab) or pull request (GitHub).
1. Use Agents mode
In Agents · specialist reviewers mode, several review agents (specialist reviewers, each one model call with its own instructions) review the change. A coordinating step picks the agents that fit the files changed, and every issue they raise is verified before it's posted. See Review agents.
- Open Repositories, click Configure on the repository.
- On the Reviews tab, set Review mode to Agents · specialist reviewers.
- Under Review agents, leave all unticked to let Gryndel choose from every enabled agent, or tick the ones that matter here, for example Security, Bugs & regressions and Database & migrations.
- Click Save settings.
On the Review agents page, check that the agents you rely on have May raise blocking issues ticked. An agent without it can only post suggestions, which never fail the commit.
Add your own agent for a domain the built-in ones don't cover. For example, a Payments agent:
- File types:
payments/**, billing/** - Description: "Reviews payment and billing code: amounts, currencies, rounding, idempotency of charges and refunds."
- Prompt: what a mistake looks like in your payment code, such as "amounts must be integers in minor units", "every charge call must pass an idempotency key".
Agents mode makes more model calls than Verified mode, so it costs more and takes longer. See Control costs.
2. Fail the commit on P1 findings too
By default the commit status fails only on P0 findings (critical: security holes or data loss). For critical code, also fail on P1 (realistic incorrect behaviour).
- In Configure → Findings, set Fail commit status on to P0 or P1 findings.
- Check Min. severity to publish is P2 · all findings or P1 · high and critical. A finding that isn't published can't fail the status, so this must be at or below your fail level.
- Click Save settings.
| Fail commit status on | Use for |
|---|---|
| P0 findings (default) | Most repositories |
| P0 or P1 findings | Payments, authentication, migrations, infrastructure |
| Any published finding | Rarely. Every posted issue blocks, including minor ones. |
| Never fail | Pilots, or repositories where Gryndel is only advisory |
Only findings labelled issue can fail the status. Suggestions, nitpicks and questions never
do. A review where an agent didn't finish (a partial review) also fails the status, so a
gap in coverage never looks like a pass.
3. Write rules for the critical code
Rules add your own policies to every review. Narrow them with file patterns so they only apply to the critical folders. Good candidates:
| Rule | Files |
|---|---|
"Every database migration must implement downgrade() so a release can be rolled back. A downgrade() that only contains pass breaks this rule." | **/migrations/** |
| "Payment amounts must be integers in minor units (cents). Never use floats for money, because rounding errors change what customers pay." | payments/**, billing/** |
"Every new endpoint under api/admin/ must check the caller has the admin role before doing anything else." | api/admin/** |
Give them a Severity hint of High if a violation should block. See Write a rule that works and File patterns, then Check that a rule works.
To keep rules with the code, and reviewed like code, put them in the repository's
.gryndel.yaml instead. See Rules & learnings.
4. Lock the settings so nobody can relax them
Anyone who can merge to a repository can change its .gryndel.yaml, which overrides the
repository settings in Gryndel. A merged file with fail_on: none would stop Gryndel ever
blocking. Organization settings can lock a value so no repository setting, shared
gryndel-config repository (of a GitLab group or a GitHub account) or .gryndel.yaml
can change it.
- On Repositories, click Organization settings.
- Set the value, then tick 🔒 Lock next to it.
- Click Save settings.
Organization settings and their locks cover the whole workspace. You can't lock a value for only the critical repositories. Lock settings that should hold everywhere, such as Fail commit status on at P0 findings, and set the stricter values per repository.
A practical split:
| Setting | Organization (locked) | Critical repositories |
|---|---|---|
| Fail commit status on | P0 findings, locked, if every repository should at least block on P0 | Can't go lower than the locked value. If you need P0 or P1 findings here, leave the organization value unlocked and set it per repository. |
| Excluded paths | Generated and vendored code | Exclusions from every level add up, so a repository can add to them but never remove the organization's. |
| Review mode | Unlocked | Agents · specialist reviewers |
Check the result with Configure → Effective configuration → Preview. A 🔒 marks
locked values. The Not applied list shows any value a level tried to set but couldn't. See
How settings combine.
The preview reads .gryndel.yaml from the repository's default branch, while a review
reads it from the target branch of the merge or pull request, so check changes into other
branches with @gryndel configuration.
5. Make GitLab or GitHub require Gryndel's status
Gryndel reports its result as a commit status named gryndel/review, passed or failed.
In GitLab it shows with the merge request's pipeline; on GitHub, in the pull request's list of
checks. On its own, a failed status is only a warning. To stop the merge button, make the
code host require it:
- GitLab
- GitHub
- In GitLab, open the project, then Settings → Merge requests.
- Under Merge checks, tick Pipelines must succeed.
- Save the changes.
- Let Gryndel review at least one pull request in the repository first. GitHub offers a status as a required check only once it has seen it on the repository recently.
- On GitHub, open the repository's Settings → Branches, and add a branch protection
rule for the target branch, such as
main. (Organizations can use a ruleset under Settings → Rules instead.) - Tick Require status checks to pass before merging, search for
gryndel/review, and add it to the required checks. - Save the rule.
Then test it on a merge or pull request that should fail, before you rely on it. Labels and options vary with your GitLab or GitHub version and plan; if yours look different, check the host's documentation for requiring a commit status.
- Gryndel sets the status only when a review finishes. It doesn't mark the commit as pending while it reviews, and a skipped or failed review sets no status.
- In GitLab, check whether a merge request can merge before Gryndel has finished, for example when your own CI pipeline passes first. If it can, ask reviewers to wait for Gryndel's Gryndel finished reviewing this merge request comment. How the merge check treats commit statuses depends on your GitLab version and setup.
- On GitHub, a required check that hasn't reported yet shows as Expected, and blocks the
merge. So a pull request whose review was skipped or failed stays blocked until a review
passes: comment
@gryndel reviewafter fixing the cause. Someone allowed to bypass branch protection can still merge.
Check it all works
- Open a draft merge or pull request in the critical repository that breaks one of your rules, or contains an obvious P1 bug.
- When the review finishes, check that the finding is posted as issue (blocking).
- Check that
gryndel/reviewshows as failed in GitLab or GitHub and the merge is blocked. - Fix the problem and push. The new review passes and the merge is allowed.
If it didn't work
| Problem | Fix |
|---|---|
| The finding was posted as non-blocking | Its severity is below Fail commit status on, it isn't an issue, or the agent that found it can't raise blocking issues. |
| A P1 finding never appears | Min. severity to publish is P0 · critical only. Lower it. |
| The setting shows a different value than you saved | A .gryndel.yaml or a lock overrides it. Check Effective configuration. |
| The merge is allowed despite a failed status | Check the GitLab merge check or the GitHub branch protection rule (step 5), and that the rule covers the target branch. |
On GitHub, gryndel/review isn't offered as a required check | Gryndel hasn't reviewed a pull request in the repository recently. Let it review one, then search again. |
| A finding blocks the merge but is wrong | The developer replies @gryndel ignore this in its thread, then comments @gryndel review. The new review leaves the dismissed finding out. See Respond to Gryndel's findings. |