Skip to content

Disease outbreak alertLevel uses undocumented keyword heuristic (smaller follow-up to #3729) #3791

Description

@koala73

Summary

detectAlertLevel in scripts/_disease-outbreaks-helpers.mjs:65-70 classifies disease outbreak items into alert / warning / watch using a hand-picked keyword list with no documented source. The resulting alertLevel drives sort order and badge color in src/components/DiseaseOutbreaksPanel.ts — so a user-visible "concern" signal is being produced by a small undocumented editorial heuristic.

Origin

Filed as a follow-up after diagnosing #3729. #3729 claimed there was a weighted scoring formula (severity * 0.6 + spread * 0.25 + alertLevel * 0.15) that turned out to never have existed in the codebase (the reporter copy-pasted from a speculative TODO). The smaller, real issue is below.

Current code

// scripts/_disease-outbreaks-helpers.mjs:65-70
export function detectAlertLevel(title, desc) {
  const text = `${title} ${desc}`.toLowerCase();
  if (text.includes('outbreak') || text.includes('emergency') || text.includes('epidemic') || text.includes('pandemic')) return 'alert';
  if (text.includes('warning') || text.includes('spread') || text.includes('cases increasing')) return 'warning';
  return 'watch';
}

Three concerns:

  1. No methodology disclosure. Users see a colored "alert/warning/watch" badge with no explanation of how it was derived.
  2. Substring matching with no boundaries. 'epidemic' matches inside 'antiepidemic'; 'spread' matches inside 'widespread vaccination'. Both can over-promote items to a higher alert level. (Lower-priority than the disclosure issue, but worth fixing while in the file.)
  3. No fallback signal. Items with neither keyword set default to 'watch', which is the lowest visible level — there's no way to mark "no useful signal" distinct from "no urgent signal."

Suggested remediation

  1. Add a header comment to detectAlertLevel documenting that the keyword set is editorial (not derived from a published index) and listing the last-reviewed date.
  2. Add word-boundary checks (/\b(outbreak|emergency|epidemic|pandemic)\b/) to avoid substring false positives.
  3. Add a methodology blurb to the panel tooltip in DiseaseOutbreaksPanel.ts so users can see what alert / warning / watch actually mean.

Same disclosure pattern as #3725 (resolved by PR #3780) — extracted constants + methodology doc — applied at the smaller scale appropriate for a 6-keyword classifier.

Scope

Small. Estimated S effort: ~30 min for the comment + boundary fix + tooltip line + a unit test for detectAlertLevel covering the substring-false-positive case.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions