The a11y sweep has no way to tell a rendered component from an orphaned one, so it keeps finding real WCAG defects in code no user can reach — and each finding costs a filing, a triage and a review before anyone notices.
Needed: a decision on whether the a11y task should skip components nothing imports. Filing rather than patching the prompt, since this is a judgement call about what the sweep is for.
The instance
src/components/dark-mode-toggle.tsx on distriktssenteret-frontend. grep -rn "DarkModeToggle" over the repo (excluding node_modules, .next, .git) returns the component and its own test file, nothing else. No layout, page, prototype route or spec renders it. Same on merkur, verified against origin/develop there.
Every commit in that file's history is a Night Shift a11y bundle:
451c9bf chore(night-shift): bundle 2026-06-18+19+22+…
b59315a night-shift(a11y): add aria-hidden to decorative icons across 4 components
506daf8 fix(a11y): increase touch targets and fix event card image alt text
86a5ca0 night-shift/a11y: fix WCAG 2.1 AA violations across 8 components
The most recent finding — no aria-pressed on a toggle button, WCAG 4.1.2 — was filed as distriktssenteret-frontend#624 and was correct. merkur even had the fix already, so the obvious move was to port it. The component just does not ship. Resolved by deleting it instead: distriktssenteret-frontend#628, with frontkom/merkur-frontend#581 filed for the sibling.
Why this is a prompt finding, not a one-off
The diagnosis was right every time. The sweep is working as specified; the specification does not include "is this reachable". So the loop has no natural end while the file exists, and deleting one orphan does not stop it finding the next.
Per the triage rule — triaging generated output includes auditing the prompt behind it — one contradictory rule fixed upstream changes every later generation, where closing a bad PR handles one instance.
Possible shapes
- Reachability pre-filter. Before reporting on
src/components/X.tsx, check whether anything outside X.test.* imports it. Cheap, mechanical, and would have caught this exact case. Risk: dynamic imports and string-keyed registries would read as unreachable — this stack has at least one (block-renderer's switch on _type), though that dispatches on already-imported components.
- Report it as a deletion candidate instead of an a11y fix. Keeps the finding, changes the recommendation — arguably more useful output than either fixing or skipping.
- Leave it, and accept that orphan components generate recurring findings until someone deletes them. Defensible if orphans are rare; on this stack I have now found one, and have not gone looking for others.
I would take (2) over (1): the sweep noticing "this component is unreachable" is a genuinely useful signal that nothing else currently produces, and it avoids the dynamic-import false negatives of a hard filter.
Worth knowing either way
Neither axe nor any CI gate could see this. The a11y suites on both sites were green throughout, because a component that never renders never gets audited. The only thing that surfaced it was reading the grep output while about to port a fix.
The a11y sweep has no way to tell a rendered component from an orphaned one, so it keeps finding real WCAG defects in code no user can reach — and each finding costs a filing, a triage and a review before anyone notices.
Needed: a decision on whether the a11y task should skip components nothing imports. Filing rather than patching the prompt, since this is a judgement call about what the sweep is for.
The instance
src/components/dark-mode-toggle.tsxon distriktssenteret-frontend.grep -rn "DarkModeToggle"over the repo (excludingnode_modules,.next,.git) returns the component and its own test file, nothing else. No layout, page, prototype route or spec renders it. Same on merkur, verified againstorigin/developthere.Every commit in that file's history is a Night Shift a11y bundle:
The most recent finding — no
aria-pressedon a toggle button, WCAG 4.1.2 — was filed as distriktssenteret-frontend#624 and was correct. merkur even had the fix already, so the obvious move was to port it. The component just does not ship. Resolved by deleting it instead: distriktssenteret-frontend#628, with frontkom/merkur-frontend#581 filed for the sibling.Why this is a prompt finding, not a one-off
The diagnosis was right every time. The sweep is working as specified; the specification does not include "is this reachable". So the loop has no natural end while the file exists, and deleting one orphan does not stop it finding the next.
Per the triage rule — triaging generated output includes auditing the prompt behind it — one contradictory rule fixed upstream changes every later generation, where closing a bad PR handles one instance.
Possible shapes
src/components/X.tsx, check whether anything outsideX.test.*imports it. Cheap, mechanical, and would have caught this exact case. Risk: dynamic imports and string-keyed registries would read as unreachable — this stack has at least one (block-renderer'sswitchon_type), though that dispatches on already-imported components.I would take (2) over (1): the sweep noticing "this component is unreachable" is a genuinely useful signal that nothing else currently produces, and it avoids the dynamic-import false negatives of a hard filter.
Worth knowing either way
Neither
axenor any CI gate could see this. The a11y suites on both sites were green throughout, because a component that never renders never gets audited. The only thing that surfaced it was reading the grep output while about to port a fix.