Found while asserting the pre-tag campaign invariants for v3.2.5. Not a code defect; a release-machinery defect, and it silently weakens every claim of the form "merged green".
What's actually configured
$ gh api repos/pulseengine/scry/rules/branches/main
rule: deletion
rule: non_fast_forward
rule: required_signatures
rule: pull_request
$ gh api repos/pulseengine/scry/branches/main/protection
required_status_checks: None
So main is protected against deletion, force-push and unsigned commits, and it requires a PR — but nothing requires any status check to pass before that PR can merge. The 11 CI jobs are advisory.
Why it matters
The methodology's standing rule is never merge around a red or absent gate. That rule is currently enforced only by whoever is doing the merging remembering to look. Three PRs merged into main today (#124, #127, #129); each was 11/11 green because I checked gh pr checks and waited — not because the repo would have refused a red merge.
That is the difference between a property and a convention, and it is the same distinction this project just spent a release arguing about in DD-022 (observation mode enforced structurally, not by a comment asking people not to gate on it). The release machinery should hold itself to the standard the analyzer is held to.
It also means the invariant the release procedure asserts before tagging — "the protected branch's required_status_checks.contexts is non-empty (the gate is real)" — fails, and has presumably been failing for every release cut so far.
What to do
Add a required_status_checks rule to the main ruleset listing the 11 job contexts:
AADL model (spar parse) · Bazel build (//:scry) · Clippy · Doc claims (claim-check) ·
Format · MC/DC (witness) · Rivet artifact delta · Rivet artifact validation · Test ·
WIT round-trip (wasm-tools) · cargo-deny (licenses, advisories, bans)
This needs repo-admin rights and changes merge behaviour for everyone, so I have not done it unilaterally.
Two things worth deciding at the same time:
Rivet artifact delta may not belong in the required set — it is informational on some PRs and takes ~9 min, which would make it the critical path for every merge.
- Strict mode (require branches to be up to date before merging) is a separate toggle; it prevents the "both PRs green in isolation, broken together" case but forces rebases.
Scope note
I verified this on pulseengine/scry only. If the same ruleset template is used across the org's repos, the gap is probably not local to this one — worth a sweep.
Found while asserting the pre-tag campaign invariants for v3.2.5. Not a code defect; a release-machinery defect, and it silently weakens every claim of the form "merged green".
What's actually configured
So
mainis protected against deletion, force-push and unsigned commits, and it requires a PR — but nothing requires any status check to pass before that PR can merge. The 11 CI jobs are advisory.Why it matters
The methodology's standing rule is never merge around a red or absent gate. That rule is currently enforced only by whoever is doing the merging remembering to look. Three PRs merged into
maintoday (#124, #127, #129); each was 11/11 green because I checkedgh pr checksand waited — not because the repo would have refused a red merge.That is the difference between a property and a convention, and it is the same distinction this project just spent a release arguing about in DD-022 (observation mode enforced structurally, not by a comment asking people not to gate on it). The release machinery should hold itself to the standard the analyzer is held to.
It also means the invariant the release procedure asserts before tagging — "the protected branch's
required_status_checks.contextsis non-empty (the gate is real)" — fails, and has presumably been failing for every release cut so far.What to do
Add a
required_status_checksrule to themainruleset listing the 11 job contexts:This needs repo-admin rights and changes merge behaviour for everyone, so I have not done it unilaterally.
Two things worth deciding at the same time:
Rivet artifact deltamay not belong in the required set — it is informational on some PRs and takes ~9 min, which would make it the critical path for every merge.Scope note
I verified this on
pulseengine/scryonly. If the same ruleset template is used across the org's repos, the gap is probably not local to this one — worth a sweep.