| 5 route-auth |
_head_block L1411 — WINDOW, not prose |
Two fixtures differing only in docblock length, both carrying a real multi-line #[AuthorizedAdminSetting(\n Application::APP_ID\n)]: 5 doc lines → PASS, 30 doc lines → FAIL. The contiguous run stops at the )] line, and past 20 doc lines the union no longer reaches the attribute. gate-5's prose axis is separately CLEAN — this is purely budget. |
| 9 semantic-auth |
head/body sliced from raw src L632–633 |
A body whose only content is // We used to $this->requireAdmin(); here. Now anyone may read. → FAIL. _strip_comments exists in this file and is used only for the credential surface at L665. |
| 15 dashboard-antipattern |
raw read_text() L196, DASHBOARD_TAG_RE.search(body) L210 |
<!-- removed 2026-08: <CnDashboardPage /> was nested here by mistake --> → FAIL. The removal note scores as the removal it documents. |
| 21 conflict-markers |
runner inline bash, no mask at all |
A fenced code block in openspec/notes.md documenting what a conflict looks like, plus a marker inside a /* */ in PHP → FAIL — 2 file(s) with unresolved conflict markers. Neither file has a conflict. The existing .md setext carve-out does not help. |
| 23 or-abstraction-anti-patterns |
lint-or-abstraction-anti-patterns.sh L418, grep -rln -e "search_path" |
A docblock reading "We deliberately do NOT set a Postgres search_path here — tenant isolation is OpenRegister's job (ADR-022)" → FAIL. The PDOK rule in the same file already routes through _code_lines(); the grep-kind rows never got it. |
| 24 integration-parity |
runner inline ~L4527, raw grep -rqE 'new\s+LeafDescriptor' |
Two comments (// TODO: one day we could do \new LeafDescriptor(...)`, // We used to call registerIntegration({...}); removed) flip NOT APPLICABLE→SKIPPED (structural). Not a red gate — but structuralcounts against coverage, and--require-full-coverage` exit went 5 → 6 on the same tree. |
| 27 no-phantom-cross-app-rpc |
check_phantom_cross_app_rpc.py L256–268, L384–389 |
Its comment test is stripped.startswith("//","*","/*","#") per LINE, so it only recognises comment-opening lines. One clean fixture → FAIL — 3: an interior /* */ line, a trailing // never do …getLeaf(…), and a string literal. No source_scope import in the file. |
| 28 license-triangle |
check_license_triangle.py DECL |
A docblock line whose SENTENCE begins with the tag reads as a second declaration: a real * @license EUPL-1.2 plus * @license MIT was never used here — see the note above. → FAIL — 2. Mid-sentence and string forms correctly PASS, so the anchor is nearly right. |
| 46 spec-anchor-existence |
check_spec_anchors.py TAG L65, unmasked and unanchored |
const spec = '@spec openspec/specs/imaginary/spec.md' → FAIL. Also a tag mid-sentence in prose (// See @spec openspec/specs/gone/spec.md#missing for why.) → FAIL. Gates 47 and 48 were given position-anchored regexes for exactly this; 46 never was. No false-negative direction exists here — the gate has no suppression path a comment can reach. |
| 47 security-change-has-tests |
check_security_cochange.py _COMMENT_LINE_RE L145 |
Matches only lines starting with *, //, /*, #. A trailing // resolved via IUserSession elsewhere and an HTML comment (<!-- is not in its vocabulary at all, yet .vue is a candidate path) → FAIL — 2. This defeats the module's own stated promise: "Prose that merely mentions IUserSession is not — it is a sentence." |
| 61 listener-work-placement |
check_listener_placement.py parse_registrations() L296 reads raw |
_strip_comments() L472 is applied at L482 and L520 but not here, so a listener existing only as two commented-out registration lines → FAIL, though it is not wired at all. The stripper is also not string-aware. |
| 62 store-plane |
check_store_and_settings_surface.py L245 raw read_text() + plain substring test |
A docblock saying "We deliberately do NOT hit /apps/openregister/api/objects/ with an IClientService here — GenericStoreService owns that (ADR-080)" → FAIL — 1, identical to the real-violation fixture. This is exactly the doriath loadApp shape gate-64 was already fixed for. |
Found by the all-65 survey of the #415/#420 comment class. Full table with per-gate fixtures and verdicts:
fleet-board/findings/gates-comment-class.md. Companion to #422 (the false-negative half).This is the false-positive half: a comment crowds a bounded window, or a note about code that was REMOVED scores as that code.
🔑 This is not the milder half, it is the corrosive half. An author whose documented fix goes red and whose undocumented fix goes green learns to delete the explanation — and the gate then loses the only thing that would have let a human check it. 8 of gate-50's 16 opencatalogi findings were this shape.
_head_blockL1411 — WINDOW, not prose#[AuthorizedAdminSetting(\n Application::APP_ID\n)]: 5 doc lines → PASS, 30 doc lines → FAIL. The contiguous run stops at the)]line, and past 20 doc lines the union no longer reaches the attribute. gate-5's prose axis is separately CLEAN — this is purely budget.head/bodysliced from rawsrcL632–633// We used to $this->requireAdmin(); here. Now anyone may read.→ FAIL._strip_commentsexists in this file and is used only for the credential surface at L665.read_text()L196,DASHBOARD_TAG_RE.search(body)L210<!-- removed 2026-08: <CnDashboardPage /> was nested here by mistake -->→ FAIL. The removal note scores as the removal it documents.openspec/notes.mddocumenting what a conflict looks like, plus a marker inside a/* */in PHP →FAIL — 2 file(s) with unresolved conflict markers. Neither file has a conflict. The existing.mdsetext carve-out does not help.lint-or-abstraction-anti-patterns.shL418,grep -rln -e "search_path"_code_lines(); thegrep-kind rows never got it.grep -rqE 'new\s+LeafDescriptor'// TODO: one day we could do \new LeafDescriptor(...)`,// We used to call registerIntegration({...}); removed) flipNOT APPLICABLE→SKIPPED (structural). Not a red gate — butstructuralcounts against coverage, and--require-full-coverage` exit went 5 → 6 on the same tree.check_phantom_cross_app_rpc.pyL256–268, L384–389stripped.startswith("//","*","/*","#")per LINE, so it only recognises comment-opening lines. One clean fixture →FAIL — 3: an interior/* */line, a trailing// never do …getLeaf(…), and a string literal. Nosource_scopeimport in the file.check_license_triangle.pyDECL* @license EUPL-1.2plus* @license MIT was never used here — see the note above.→FAIL — 2. Mid-sentence and string forms correctly PASS, so the anchor is nearly right.check_spec_anchors.pyTAGL65, unmasked and unanchoredconst spec = '@spec openspec/specs/imaginary/spec.md'→ FAIL. Also a tag mid-sentence in prose (// See @spec openspec/specs/gone/spec.md#missing for why.) → FAIL. Gates 47 and 48 were given position-anchored regexes for exactly this; 46 never was. No false-negative direction exists here — the gate has no suppression path a comment can reach.check_security_cochange.py_COMMENT_LINE_REL145*,//,/*,#. A trailing// resolved via IUserSession elsewhereand an HTML comment (<!--is not in its vocabulary at all, yet.vueis a candidate path) →FAIL — 2. This defeats the module's own stated promise: "Prose that merely mentionsIUserSessionis not — it is a sentence."check_listener_placement.pyparse_registrations()L296 reads raw_strip_comments()L472 is applied at L482 and L520 but not here, so a listener existing only as two commented-out registration lines → FAIL, though it is not wired at all. The stripper is also not string-aware.check_store_and_settings_surface.pyL245 rawread_text()+ plain substring test/apps/openregister/api/objects/with anIClientServicehere — GenericStoreService owns that (ADR-080)" →FAIL — 1, identical to the real-violation fixture. This is exactly the doriathloadAppshape gate-64 was already fixed for.Notes
lib/source_scope.py, offset-preserving so a line number computed on the mask still names the right line. Use it rather than a sixth hand-rolled stripper._head_blockneeds to find the attribute by structure (walk the contiguous annotation run to its start) rather than by distance — the same repaircheck_contract_coveragealready made and documented at its L208, "WHY THIS IS NOT A LINE WINDOW".