20 checks were defaulting to PASS when no violation was found,
even if the scanner couldn't actually test them. Now:
- Phase-based checks (tracking/cookies): absence = PASS (correct)
- UI checks: only PASS if banner_checks actually ran
- If banner not detected: everything except banner_detected = FAIL
This prevents false 100% scores when violations exist but the
text→code mapping doesn't cover them.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The consent-tester produces violations without a 'code' field — only
text, severity, service. The runner now infers check_keys from the
violation text content (36 text→code mappings). This fixes the 100%
false-pass for safetykon.de which had 3 real violations (impressum,
re-access, color contrast dark pattern) that were silently ignored.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>