Org rules
Org rules are your team's merge rules for agent-written code, written once in a file Verity checks on every pull request. Each rule says which files it covers, what must be true about a change to them, and whether a miss fails the check or only warns.
Verity answers each rule from the diff and the agent's session. It never reads the PR description, because the agent wrote it: a "flag exemption" line or a ticked checkbox is not evidence.
The rules file
Rules live in .verity/rules.yml in the repository. verity capture init writes a starter file from your repository's files, every rule a warning. Verity reads the file at the tip of the pull request's base branch, so a pull request can't weaken the rules it is checked against, and rule changes go through normal review.
version: 1
rules:
- id: ci-config-changed # files only: a change is the finding
files: [".github/workflows/**"]
severity: warn
why: "Build and CI changes affect every PR."
- id: tests-after-edit # a built-in fact, decided by rules
files: ["src/**/*.ts"]
exclude: ["src/**/*.test.ts"]
check: tests_passed_after_last_edit
expect: yes
severity: fail
why: "Code changes need a passing test run."
- id: auth-flagged # a question, answered by a model
files: ["src/auth/**"]
ask: "Is the new or changed behaviour behind a feature flag?"
about: diff
expect: yes
severity: fail
why: "Auth changes must be switchable off in production."
Fields
| Field | Required | Meaning |
|---|---|---|
version | yes | Always 1. |
id | yes | Lowercase kebab-case, at most 64 characters, unique in the file. It names the override label. |
files | yes | Globs matched against the pull request's changed paths. A rename uses its new path. |
exclude | no | Globs to leave out. Use this instead of ! patterns. |
check | no | A built-in fact: tests_passed_after_last_edit or ran_after_last_edit. |
ask | no | A yes/no question, at most 500 characters. Not with check. |
about | with ask | What the question is answered from: diff (the default) or session. |
expect | with check or ask | The answer that passes: yes or no. |
severity | yes | fail fails the check run; warn only reports. |
no_session | no | For check and about: session rules, what happens when the pull request has no session: fire (the default) or pass. |
why | yes | At most 300 characters. Shown on the pull request. |
A file holds at most 50 rules.
How a rule is answered
A rule has one of three kinds of condition, from most to least exact:
- Files only (no
checkorask): changing a matching file is the finding. - A built-in fact (
check): decided by rules from the session.tests_passed_after_last_editholds when a test passed after the last edit to every changed part of the file.ran_after_last_editalso accepts a build, typecheck or lint. - A question (
ask): answered by a small classification model, from the file's diff or from the session. Use it only where judgement is needed.
Verity answers each matched file separately, so a finding names the file: "Views/Edit.cshtml: no page load after the last edit". At most 30 files are judged per rule; any more fire.
Rules fail closed. Any answer other than the one you expect fires the rule: "no", an unsure answer, no answer at all (the model couldn't be reached), or no session when the rule needs one.
Rules apply to every pull request in the repository, including ones written by people.
On the pull request
The comment and the check run both show:
- a tally in the heading, such as "❌ 1 failing · ⚠️ 2 warnings · ✅ 3 passed";
- each failing rule with its override label;
- a table of every rule that applied (❌ failing, ⚠️ warning, ☑️ overridden, ✅ passed), with the question and expected answer of each rule that fired, and the files it fired on;
- the rules that matched no file, folded.
The check run fails when a fail rule fires and no override covers it. Otherwise it is neutral, which GitHub treats as passing.
Overrides
When a rule fires but the change is fine, a reviewer adds the label verity-override:<rule id> to the pull request, for example verity-override:auth-flagged. The check run updates.
- The label counts only when a GitHub user who isn't the pull request's author adds it. A bot, or the author, can't override.
- A pull request approval never counts as an override.
- An agent using a person's GitHub token looks like that person.
- An override lasts until the label is removed, even across later pushes.
Make rules block merging
Mark the Verity check as required in the branch's protection rules on GitHub. A fired fail rule then blocks the merge until it is fixed or overridden. warn rules never block.
Start with every rule set to warn, watch what fires for a week or two, then switch the ones you trust to fail.
An invalid rules file
- A pull request that makes the file invalid fails the check, with the problems listed. Nothing overrides that: fix the file.
- An invalid file already on the base branch (possible only by bypassing the check): no rules are checked, the check run says so, and it stays neutral, so the pull request that fixes the file can merge.