30-second answer

Three things decide whether a rule gets merged, and none of them is whether we agree with it. All of it runs offline; no tenant is needed to contribute a rule.

Set up and run the gates first

Bash
python -m venv .venv && source .venv/bin/activate
pip install -e . && pip install -r requirements-dev.txt

./tools/release-check.sh     # everything CI runs, in the same order

That one script is the gate. Nine steps: dependencies, ruff check, ruff format --check, m365-governance validate, the schemas, pytest, coverage, tools/examples.py --check, and an evaluation of every fixture.

Run it before pushing. Running a subset and pushing gets a refusal for formatting, which is a refusal nobody learns anything from.

Coverage has a floor rather than a target. It moves up when something real gets covered, and never down to accommodate a change that stopped testing something.

The three things

The basis is honest. Five kinds, and the source never decides the type. An opinion that cites Microsoft documentation is still an opinion. Label a convention as a requirement and the pull request will be about that and nothing else.

passes_without_resolving is answered. Every rule states, in writing, how it can pass while the problem survives. It is a field of its own because it is the one authors skip. If you cannot answer it, the rule is not understood well enough yet, and finding that out before the review is the point.

The messages claim only what the rule established. If the fail message says "and still inherits its permissions", the rule has to have checked that. The validator catches evidence declared and never consumed, which is where this usually starts, but the sentence itself is on you.

What the build refuses

Deliberately, and by construction. The build fails when:

  • basis is missing;
  • a documented type has no source;
  • a convention has no rationale;
  • the condition reads evidence nobody declared;
  • evidence is declared and never consumed;
  • a failure message interpolates a value that is missing precisely when that message prints;
  • a YAML key is duplicated;
  • two rules share an id;
  • any unknown field appears anywhere.

That last one is additionalProperties: false everywhere. severty: high must stop the build, not disappear.

Where to start reading

rules/sharepoint/SPO-SITE-001.yaml, which is short, and docs/RULE-SCHEMA.md once. Then anatomy of a rule and the validation layers.

What will be declined

  • automatic remediation, in any form, including a flag that only suggests it;
  • a rule that executes code;
  • inferring basis from the presence of a source;
  • treating missing evidence as compliance, anywhere, for any reason.

Those four are the trust model expressed as a review policy, not preferences.