Problem
MERGE_POLICY.md landed on main in #1408 (f93fecd). Its gate 2 lists the security check-run names the repository actually produces:
| Security | Security Scan - python, Security Scan - javascript, bandit, python-safety, npm-audit, trivy |
But the unconditional required list that follows contains none of them:
Required for every pull request: validate, guards, lint-python, lint-frontend, build, test, CodeQL, gitleaks (working tree), dependency-review, PR Governance, Canonical issue and evidence.
And the conditional list names only one:
Security Scan - javascript — only when the diff touches JS/TS.
So Security Scan - python, bandit, python-safety, npm-audit, and trivy appear in the table and then in neither list. The literal reading of v2 is that no security scan gates a merge.
Why this matters
Merge Gate v1 listed Security among its required six. The rewrite that set out to make gate 2 precise therefore dropped every security scan out of the required set — a weakening introduced by the fix rather than present before it.
This is the same defect class the policy is named for and that #1408's own second commit repaired one layer up: a list that does not say what it means. Anyone following adoption step 3 would configure branch protection from the required list and ship a policy with no security gate, while the document's own table implies there is one.
Evidence
All six were measured against the 29 check runs on #1408's documentation-only head 27b2ecf, not inferred:
| Context |
Conclusion on a docs-only PR |
Security Scan - python |
success |
Security Scan - javascript |
success |
bandit |
success |
python-safety |
success |
npm-audit |
success |
trivy |
success |
None can strand a pull request permanently pending, which is the only reason gate 2 gives for holding a check back. So all six can be required unconditionally.
Two further findings from the same measurement:
- The stated rationale for holding
Security Scan - javascript back is empirically false. It reads "only when the diff touches JS/TS", yet it ran to success on a docs-only head.
trivy and Trivy are two different check-runs on the same head — success and neutral respectively. Selecting the capitalised one in branch protection would pin a check that never passes. This is exactly the trap gate 2's own confirmation rule exists to catch, and it is currently uncaught.
The conditional entries were re-confirmed and are correct: Generate and Upload Coverage is absent from all 29 checks, and E2E Pipeline Tests is skipped. Both stay conditional.
Acceptance criteria
Scope
MERGE_POLICY.md only. Branch protection configuration remains adoption step 3 and is out of scope here.
Problem
MERGE_POLICY.mdlanded onmainin #1408 (f93fecd). Its gate 2 lists the security check-run names the repository actually produces:But the unconditional required list that follows contains none of them:
And the conditional list names only one:
So
Security Scan - python,bandit,python-safety,npm-audit, andtrivyappear in the table and then in neither list. The literal reading of v2 is that no security scan gates a merge.Why this matters
Merge Gate v1 listed
Securityamong its required six. The rewrite that set out to make gate 2 precise therefore dropped every security scan out of the required set — a weakening introduced by the fix rather than present before it.This is the same defect class the policy is named for and that #1408's own second commit repaired one layer up: a list that does not say what it means. Anyone following adoption step 3 would configure branch protection from the required list and ship a policy with no security gate, while the document's own table implies there is one.
Evidence
All six were measured against the 29 check runs on #1408's documentation-only head
27b2ecf, not inferred:Security Scan - pythonsuccessSecurity Scan - javascriptsuccessbanditsuccesspython-safetysuccessnpm-auditsuccesstrivysuccessNone can strand a pull request permanently pending, which is the only reason gate 2 gives for holding a check back. So all six can be required unconditionally.
Two further findings from the same measurement:
Security Scan - javascriptback is empirically false. It reads "only when the diff touches JS/TS", yet it ran tosuccesson a docs-only head.trivyandTrivyare two different check-runs on the same head —successandneutralrespectively. Selecting the capitalised one in branch protection would pin a check that never passes. This is exactly the trap gate 2's own confirmation rule exists to catch, and it is currently uncaught.The conditional entries were re-confirmed and are correct:
Generate and Upload Coverageis absent from all 29 checks, andE2E Pipeline Testsisskipped. Both stay conditional.Acceptance criteria
Security Scan - javascriptis removed from the conditional list, since its stated rationale does not hold.trivy/Trivycase collision is recorded where someone configuring branch protection will see it.Generate and Upload CoverageandE2E Pipeline Testsremain conditional.Scope
MERGE_POLICY.mdonly. Branch protection configuration remains adoption step 3 and is out of scope here.