Skip to content

ADR-0004: RAG Thresholds for Score and Coverage

Status: Accepted (2026-05-19) Supersedes:Superseded by:


Context

ADR-0001 made coverage a first-class metric alongside the composite score. ADR-0002 specified that both should be displayed with equal visual weight in the institution detail page hero. The remaining decision is how to colour-code them — RAG (Red / Amber / Green) is the obvious convention for screening output and was specifically requested by the operator.

RAG thresholds need to be defensible (consistent with the methodology and with industry norms), useful (not so generous that everything is green, not so harsh that everything is red), and tunable (easy to revisit as the pilot grows).

Decision

Adopt the following RAG bands for the institution detail UI and across all derived surfaces (institution index, peer table, watchlist, Methodology coverage matrix).

Composite ESG score (and pillar scores):

Band Range Meaning
Red < 40 Negative signals dominate; institution materially flagged
Amber 40 – 69 Mixed or neutral; further investigation warranted
Green ≥ 70 Positive signals dominate

Coverage:

Band Range Meaning
Red < 25% Score is interpretable only with strong caveats
Amber 25 – 59% Score is informative but partial
Green ≥ 60% Coverage sufficient for confident interpretation

Red flags (manual-at-intake, per v0.4):

State Colour Meaning
Exposed Red Institution has exposure to the flagged area (fossil financing, weapons manufacturing)
Clear Green No direct exposure on file

No amber state for red flags — they're binary at intake. If a flag is uncertain it should not be set; the watchlist is the right surface for uncertainty.

Palette (working values, tied to overall page palette):

Token Hex Use
--rag-red #b8392c Text and accent for red state
--rag-red-bg rgba(184, 57, 44, 0.08) Background tint
--rag-amber #c47a1f Text and accent for amber state
--rag-amber-bg rgba(196, 122, 31, 0.08) Background tint
--rag-green #3a6b56 Text and accent for green state
--rag-green-bg rgba(58, 107, 86, 0.08) Background tint

Colours are dustier than pure RAG. This is deliberate: bright red/amber/green look like a dashboard alarm. The palette here reads as "considered judgement" not "system warning," which matches the screening register.

Consequences

Positive. - Headline numbers self-explain at a glance. Barclays at 66.7%/11% reads as "amber score, red coverage" — i.e. "uncertain, mostly because we don't know enough yet." - Coverage being colour-coded reinforces ADR-0001's framing that coverage is a first-class metric, not a footnote. - Red flags get the strongest possible visual signal precisely because they are the binary deal-breakers in the screening methodology.

Negative. - Thresholds are judgement calls. Defensible but not algorithmic. Anyone challenging the bands has a fair argument that 70 is arbitrary. - Tying score thresholds (40, 70) and coverage thresholds (25, 60) to fixed numbers means they need re-tuning if the methodology changes (e.g. if scoring shifts from 0–100 to 0–5).

Implementation. - Thresholds live in a single config object (src/config/rag.js) referenced wherever colour is applied. No magic numbers in templates. - CSS variables in the base stylesheet, applied via modifier classes (.rag-red, .rag-amber, .rag-green). - Accessibility: red/green pairing fails for ~8% of male users with colour-vision deficiency. Mitigated by: (a) tonal contrast — red is darker than green; (b) the numbers themselves are always visible (the score is "11%" not just a red dot); (c) for the peer table and coverage matrix, an icon or text label accompanies the colour where the colour is the only differentiator.

Convergence with coverage thresholds in ADR-0001. Note that ADR-0001 uses different coverage thresholds for "how the headline is laid out" (1–49% → equal weight, 50–79% → score primary, ≥80% → single composite) versus this ADR's colour-coding (25 / 60). This is intentional: layout shift is a UI structural change that should happen rarely and at distinct breakpoints; colour-coding can be more granular without restructuring the page. The two sets of thresholds will be revisited together when the pilot grows.

Alternatives considered

  • Standard bright RAG palette. Rejected on aesthetic grounds — looks like alarm, not screening output.
  • Score bands aligned to MSCI ESG ratings (AAA/AA/A/BBB/BB/B/CCC). Imports an external rating's terminology and risks implying parity with MSCI methodology. Rejected.
  • Five-band coverage (very low / low / moderate / good / strong). More granular but introduces yellow and orange — too many colours, harder to scan. Rejected for v1; could revisit if needed.
  • No coverage colour-coding (only score colour-coded). Treats coverage as secondary. Inconsistent with ADR-0001's "coverage is first-class" framing.

Amendment — cycle 16 (2026-05-22)

Score-band thresholds recalibrated to the run_id=29 distribution (22-institution pilot). Operator-confirmed; commit 6f8a3a7.

Band Old range New range
Red < 40 < 15
Amber 40 – 69 15 – 29
Green ≥ 70 ≥ 30

Coverage bands (COVERAGE_THRESHOLDS) unchanged.

Reporting hygiene (5th source-instrument continuity catch): canonical score for all surfaces and handoffs is score_coverage_weighted (range 0–39 under current sparsity), not score_value (raw 0–27 range). The two diverge for the 10 institutions with a null S-pillar. Do not use score_value in handoffs or surface labelling. The column-name divergence is a candidate for the parked data-model tidy (adjacent to the source-vs-signal_source rename).

Forward note: bands are fitted to the 22-institution run_id=29 universe. Cycle 15 will roughly triple the universe and shift the score distribution; bands may need re-tuning after cycle 15's scoring run. No action now.

References

  • ADR-0001 (coverage-weighted scoring) — defines what is being colour-coded
  • ADR-0002 (UI architecture) — defines where colour is applied
  • WCAG 2.1 SC 1.4.1 (Use of Color) — colour cannot be the sole means of conveying information
  • v0.4 workbook, red flag definitions