Skip to content

Replace the scanner's A–F grade with status counts per requirement level - #72

Merged
jbspeakr merged 4 commits into
mainfrom
claude/project-thread-vg8kgo
Oct 23, 2026
Merged

jbspeakr merged 4 commits into
mainfrom
claude/project-thread-vg8kgo

Conversation

@jbspeakr

Copy link
Copy Markdown
Collaborator

Requested by Jan · project thread

What this changes

Jan found the scanner grades too aggressive. They also broke the site's own rule, "Neutral. Nothing is ranked or scored." A letter is a score. An F in the threat colour next to a company's name reads as a verdict, whatever rule sits behind it. It also added nothing: the matrix row already shows every status the grade came from.

There is no grade anywhere now. A report counts the statuses its rows show, per requirement level, and names the checks that are not supported. Nothing is added up into one number. This is spec 017-neutral-scan-summary, which supersedes 004 FR-008 and the grade part of FR-009.

Where the grade was, and what replaces it

Place Before After
Atlas matrix, next to each name Coloured letter box (A, C, F, "–") A quiet "report" text link. The row's cells are the result.
Scan report, top Large letter and reasons ("Grade F") "What the scan found": for MUST, SHOULD and MAY, the number of checks and the count of each status (same StatusCell glyphs), with the checks that are not supported listed under their level and linked to their rows
Scan report, ladder = Grade F = 14 checks, each with its status below
Server page panel "Passive scan Grade C · date · Report" "Passive scan 14 checks · date · Report"
Scanner page and report "How the grade is derived" (A–F rule) "How the summary is counted", which says there is no grade and no score
scan.json grade: { letter, label, reasons }, version 1 summary: { state, label, tallies, open, notes }, version 2
Nightly PR table, pnpm scan Grade column Scan summary (MUST 7 supported, 1 unsupported · …)

The either-or rule for discovery is unchanged (protected resource metadata at a well-known URL or in the 401 challenge). When it makes a count differ from its row, the summary says so in one sentence. unknown is still counted as unknown and never as unsupported.

Alternatives weighed

  • Keep A–F with softer colours (SSL Labs, securityheaders.com). It is still a score and still implies a ranking.
  • Pass/fail conformance verdict (certification badges). It is binary and a judgement, and a passive scan of public metadata cannot certify anything.
  • Percentage or points (internet.nl, Mozilla Observatory). This is a score by another name, and it mixes MUST with MAY.
  • Descriptive tiers ("meets every MUST"). This is the grade's order hidden in words.
  • Status counts per level (W3C implementation reports, wpt.fyi, caniuse). Chosen. It counts what is shown, keeps the levels apart, gives no verdict, and reuses the glyphs the site already has.

Docs. docs/scanner.md ("The summary"), README (the jq '.summary' example), architecture, design (M12), development, data model, maintenance, the accessibility statement, and the 004 report contract. The constitution changes "grade" to "scan result" in principle II.

Sync Impact Report (constitution 1.0.0 → 1.0.1, PATCH): wording only. Principle II now names "scan result" where it named "grade". No principle is added or removed. Templates are unaffected.

Screenshots

From astro preview with reduced motion. Box is shown because it was graded F.

Before (main) After
Matrix
Report, light
Report, dark
Server page
Scanner page
Report, phone
Matrix, phone

The screenshots were committed once to get stable URLs and removed in the next commit, so the squashed diff has no images.

Code checklist

  • pnpm check passes (prose gate and enforced budgets included). 320 unit tests. scanner-grade.test.ts is now scanner-summary.test.ts and covers every MUST/SHOULD status pair, the either-or rule in both directions, unknown, not scanned and no OAuth.
  • Pages still read fully without JavaScript. No script or island changes.
  • Both themes checked. The scanner, matrix and server-page e2e specs pass with snapshots ignored (122 passed). One phone sticky-column test failed once under load and passed 3 of 3 on rerun. The matrix, report and server-page baselines change on purpose, so this PR needs the refresh-screenshots label (tasks T10).

I did not touch #71's files.


Generated by Claude Code

The letter grade was a score, and it contradicted the site's own "nothing is ranked or
scored". Reports now count the statuses their rows show per level (MUST, SHOULD, MAY) and
name the checks that are not supported; nothing is added up into one number. The matrix
links each server's report with a quiet text link instead of a coloured letter, and the
server page shows how many checks ran and when.

- src/scanner/summary.ts replaces grade.ts (same either-or rule for discovery)
- JSON report: `summary` replaces `grade`, version 2
- nightly PR table and `pnpm scan` print the summary
- spec 017 supersedes 004 FR-008 and the grade part of FR-009; constitution 1.0.1

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FQXFWHwoKYz8gUULuuev4N
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FQXFWHwoKYz8gUULuuev4N
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FQXFWHwoKYz8gUULuuev4N
@jbspeakr jbspeakr self-assigned this Oct 22, 2026
@jbspeakr jbspeakr added the refresh-screenshots Regenerate Playwright screenshot baselines with CI's Chromium and commit them to the PR branch label Oct 22, 2026 — with Claude
Generated by the screenshots workflow for #72.
@github-actions github-actions Bot removed the refresh-screenshots Regenerate Playwright screenshot baselines with CI's Chromium and commit them to the PR branch label Oct 22, 2026
@jbspeakr
jbspeakr merged commit a1b4815 into main Oct 23, 2026
@jbspeakr
jbspeakr deleted the claude/project-thread-vg8kgo branch October 23, 2026 04:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants