Split out of #239's secondary observation, which #249 deliberately did not address because it is a policy change rather than a false-positive fix.
The gap
gate-19 is correct that a test.fixme / test.skip('title', …) does not run, so the scenario is not proven. But the only remedy it prints is:
replace the tag with a reason-bearing @e2e exclude
and @e2e exclude means "this scenario is out of scope for e2e, forever". A scenario that should be e2e-tested and is blocked on a tracked fixture or product gap has no way to say so. The honest states are three, and the vocabulary has two.
Measured, root-commit-scoped, against .github@main (7b66766)
These are the findings that survive #249 — i.e. every one is a correct report of a test that genuinely does not run:
| repo |
findings |
what they actually are |
| openbuild |
36 |
test.skip('REQ-OBR-002 — builder route mounts a nested CnAppRoot …', …) — 8+ declarations in openbuild-runtime.spec.ts alone |
| larpingapp |
23 |
test.fixme(…), every one carrying // FIXME(detail-actions-blocker): detail Actions menu never renders — DETAIL_ACTIONS_BLOCKER. |
| procest |
26 |
test.skip(true, 'Requires a seeded case fixture in the dev container') at top of body |
| openconnector |
6 |
test.describe.skip('Catalog page — browse, filter, badges (REQ-001)', …) |
| scholiq |
2 |
|
93 findings, and the 59 in larpingapp + openbuild are the clearest case: the author already wrote down the blocker (DETAIL_ACTIONS_BLOCKER, REQ-OBR-*) in a comment the gate cannot read. Closing these honestly today means asserting something false.
What the vocabulary is missing
Three distinct facts, two words:
| fact |
today |
should be |
| not suitable for e2e (backend contract, covered by PHPUnit/Newman) |
@e2e exclude <reason> |
unchanged |
| should be e2e-tested, blocked on a tracked issue |
no representation — pressure to use @e2e exclude |
e.g. @e2e blocked <issue> <reason> |
| should be e2e-tested, nobody has written it |
missing @e2e |
unchanged |
Why it matters more than a wording nit
The remedy the gate prints is the one people follow. Every scenario pushed from blocked into @e2e exclude is permanently removed from the e2e programme's denominator — silently, and by a gate that was working correctly. That is the same shape as #239's "complying deletes a true coverage claim", but reached through an accurate finding instead of a false one, which makes it harder to notice.
Suggested shape
- accept
@e2e blocked <issue-ref> <reason> in the spec scenario block, with both parts required (a bare @e2e blocked is non-compliant, mirroring the existing bare-exclude rule);
- it does not satisfy coverage — the scenario stays in the denominator and is reported;
- but it is reported in its own category, so
FAIL — n scenario(s) separates nobody wrote this from someone wrote it and it is blocked on ;
- and consider a rot check: a
@e2e blocked whose issue is CLOSED is itself a finding, so the quarantine can only shrink — the same discipline tests/run-helper-suites.sh already applies to its own QUARANTINE list.
Related: #239 (where this was first observed), #249 (the fix that left it out on purpose).
Split out of #239's secondary observation, which #249 deliberately did not address because it is a policy change rather than a false-positive fix.
The gap
gate-19 is correct that a
test.fixme/test.skip('title', …)does not run, so the scenario is not proven. But the only remedy it prints is:and
@e2e excludemeans "this scenario is out of scope for e2e, forever". A scenario that should be e2e-tested and is blocked on a tracked fixture or product gap has no way to say so. The honest states are three, and the vocabulary has two.Measured, root-commit-scoped, against
.github@main(7b66766)These are the findings that survive #249 — i.e. every one is a correct report of a test that genuinely does not run:
test.skip('REQ-OBR-002 — builder route mounts a nested CnAppRoot …', …)— 8+ declarations inopenbuild-runtime.spec.tsalonetest.fixme(…), every one carrying// FIXME(detail-actions-blocker): detail Actions menu never renders — DETAIL_ACTIONS_BLOCKER.test.skip(true, 'Requires a seeded case fixture in the dev container')at top of bodytest.describe.skip('Catalog page — browse, filter, badges (REQ-001)', …)93 findings, and the 59 in larpingapp + openbuild are the clearest case: the author already wrote down the blocker (
DETAIL_ACTIONS_BLOCKER,REQ-OBR-*) in a comment the gate cannot read. Closing these honestly today means asserting something false.What the vocabulary is missing
Three distinct facts, two words:
@e2e exclude <reason>@e2e exclude@e2e blocked <issue> <reason>missing @e2eWhy it matters more than a wording nit
The remedy the gate prints is the one people follow. Every scenario pushed from blocked into
@e2e excludeis permanently removed from the e2e programme's denominator — silently, and by a gate that was working correctly. That is the same shape as #239's "complying deletes a true coverage claim", but reached through an accurate finding instead of a false one, which makes it harder to notice.Suggested shape
@e2e blocked <issue-ref> <reason>in the spec scenario block, with both parts required (a bare@e2e blockedis non-compliant, mirroring the existing bare-exclude rule);FAIL — n scenario(s)separates nobody wrote this from someone wrote it and it is blocked on ;@e2e blockedwhose issue is CLOSED is itself a finding, so the quarantine can only shrink — the same disciplinetests/run-helper-suites.shalready applies to its own QUARANTINE list.Related: #239 (where this was first observed), #249 (the fix that left it out on purpose).