Safety Outlier Explorer: test evidence
Requirement-traced qualification evidence for the safety.viz outlier-explorer module.
Requirement matrix ↗ — the reviewed source specification these tests trace to.
- Scope
- 24 coverage rows62 distinct requirement IDs
- Tests executed
- 124 automated checks22 browser · 102 unit
- Result
- pass all passing5 evidence screenshots
- Generated
- 2026-07-12 05:50 UTC
- Environment
linux 6.17.0-1018-azure · node v22.23.1 · playwright 1.61.1 · chromium 149.0.7827.55- Test run
- Actions run #29181741704
Scope & approach
Traceability for the outlier-explorer module (a Chart.js reimplementation of RhoInc/safety-outlier-explorer matching its behavior, under #24), per the convention in CONTRIBUTING.md. Two requirement-ID schemes appear:
- Module IDs (
SOE-CTRL-*,SOE-SELECT-*,SOE-NORM-*,SOE-YAXIS-*,SOE-XAXIS-*,SOE-API-*) — this module's condensed scheme, keyed to the browser/unit tests below. - Source-matrix rows (
SOE-FUNC-*,SOE-REG-*,SOE-CFG-*,SOE-DATA-*,SOE-API-*) — the reviewed matrix at safety.agentdocs/requirements/safety-outlier-explorer.md, whoseEvidence Typecolumn routes rows (unit→ Vitest,browser→ Playwright).
Each table row traces one requirement to the automated test(s) that evidence it: the requirement ID and its source-matrix rows link back to the reviewed specification, the issue column links the implementing work, and the result column shows the recorded outcome of every matching test from the committed evidence.json with its captured screenshots. Browser evidence is captured at fixed conditions (1280×800, device scale 1) on the canonical Linux CI environment.
Browser evidence (Playwright — tests/e2e/outlier-explorer.spec.js)
13 requirement rows · 13 tests
| Requirement | Source matrix rows | Issue | Tests & evidence |
|---|---|---|---|
| SOE-CTRL-001 | SOE-FUNC-001, SOE-FUNC-002, SOE-FUNC-004, SOE-FUNC-005, SOE-FUNC-006, SOE-FUNC-007 | #24 |
|
| SOE-COUNT-003 | SOE-FUNC-003, SOE-REG-001, SOE-REG-002 | #24 |
|
| SOE-DATA-037 | SOE-REG-037, SOE-REG-038 | #24 |
|
| SOE-SELECT-010 | SOE-FUNC-010, SOE-FUNC-012, SOE-FUNC-013, SOE-REG-013, SOE-REG-014, SOE-REG-016, SOE-REG-022, SOE-REG-023 | #24 |
|
| SOE-SELECT-020 | SOE-FUNC-010, SOE-REG-020 | #24 |
|
| SOE-NORM-007 | SOE-FUNC-007, SOE-REG-025, SOE-REG-026, SOE-REG-027 | #24 |
|
| SOE-YAXIS-005 | SOE-FUNC-005, SOE-FUNC-006, SOE-REG-004, SOE-REG-005, SOE-REG-006 | #24 |
|
| SOE-GROUP-049 | SOE-REG-048, SOE-REG-049, SOE-REG-050 | #24 |
|
| SOE-XAXIS-004 | SOE-FUNC-004, SOE-REG-003 | #24 |
|
| SOE-TIP-011 | SOE-REG-011 | #24 |
|
| SOE-EVENT-003 | SOE-API-003 | #24 |
|
| SOE-FILT-051 | SOE-REG-051, SOE-REG-052, SOE-REG-053 | #24 |
|
| SOE-API-001 | — (see legacy-API note) | #24 |
|
Unit evidence (Vitest — tests/unit/outlier-explorer/)
11 requirement rows · 26 tests
| Requirement | Source matrix rows | Issue | Tests & evidence |
|---|---|---|---|
| SOE-CFG-004/005/006/013/014 | SOE-CFG-004, SOE-CFG-005, SOE-CFG-006, SOE-CFG-013, SOE-CFG-014 | #24 |
|
| SOE-CFG-007/008/009 (defaults) | SOE-CFG-007, SOE-CFG-008, SOE-CFG-009 | #24 |
|
| SOE-FUNC-004/SOE-REG-048 | SOE-FUNC-004, SOE-REG-048 | #24 |
|
| SOE-REG-037/038, SOE-REG-029/031 | SOE-REG-037, SOE-REG-038, SOE-REG-029, SOE-REG-031 | #24 |
|
| SOE-FUNC-004/SOE-REG-028 (axis) | SOE-FUNC-004, SOE-REG-028 | #24 |
|
| SOE-FUNC-007/SOE-CFG-007/008 (stats) | SOE-FUNC-007, SOE-CFG-007, SOE-CFG-008, SOE-REG-025 | #24 |
|
| SOE-FUNC-005/006, SOE-REG-004/033 | SOE-FUNC-005, SOE-FUNC-006, SOE-REG-004, SOE-REG-033 | #24 |
|
| SOE-REG-028 (x-scale) | SOE-REG-028 | #24 |
|
| SOE-REG-011/049, SOE-CFG-006 | SOE-REG-011, SOE-REG-049, SOE-CFG-006 | #24 |
|
| SOE-DATA-001/003 (schema) | SOE-DATA-001, SOE-DATA-003 | #24 |
|
| SOE-API-001 (module export) | — | #24 |
|
Visual evidence
Every screenshot below is a committed baseline: the same PNG is the visual-regression baseline the browser suite asserts against and the evidence artifact shown here. Click any capture for the full-resolution image.

SOE FUNC 001 control panel 
SOE FUNC 007 normal range band 
SOE FUNC 010 participant detail 
SOE REG 037 invalid data note 
SOE REG 049 color by group
Source-matrix routing status
The matrix carries 84 rows; this module implements the core product surface — roughly 50 rows, evidenced by the tests above — and descopes the remaining exotic, legacy, or data-unsupported rows honestly.
- Implemented (
browser/unitabove): the measure/filter controls (SOE-FUNC-001/002), the participant count (SOE-FUNC-003), the x-axis toggle (SOE-FUNC-004), the y-axis limits + reset (SOE-FUNC-005/006), all four normal-range methods with their conditional inputs (SOE-FUNC-007, SOE-CFG-007/008/009, SOE-REG-025/026/027), click-to-select participant detail and de-emphasis (SOE-FUNC-010/012/013, SOE-REG-013/014/016/020/022/023), theparticipantsSelectedevent (SOE-API-003), color-by grouping with a legend (SOE-REG-048/049/050), start-valued filters (SOE-REG-051/052/053), point tooltips with configurable columns (SOE-REG-011/012, SOE-CFG-006), removed- record reporting (SOE-REG-037/038), unit-suffixed measures (SOE-REG-029/031), and axis tick rotation by variable (SOE-REG-028). Regression rows SOE-REG-001..006 are evidenced by the count/measure/axis tests above.
- Descoped — no time/visit metadata in the shared demo data (SOE-FUNC-008/009, SOE-CFG-010/011/012, SOE-DATA-005, SOE-REG-007/008/009/010): the "visits without data" and "unscheduled visits" toggles and their
unscheduled_visit_pattern/unscheduled_visits_valuesconfig depend on a visit-name/scheduling column. The reusedadbds.csvis a distribution set with no such column, and the module derives an ordinal measurement sequence for its axis; there is no honest way to demo empty or unscheduled visits, so these are out of scope for this module.
- Descoped — secondary visualization (SOE-FUNC-010/012 sparkline panel, SOE-REG-021/024): the original opens a panel of small per-measure sparkline charts plus a selected-participant dropdown. The linked tabular participant listing (demographics + records, reusing the histogram listing) covers the drill-down requirement; the sparkline panel and its dropdown are not built.
- Descoped — exotic/legacy UX (SOE-REG-015/017/018/032/034/035/036, SOE-REG-043/044/045/046/047): overlapping-point notes and hover-from-note highlighting, hover-line darkening, the overlap-count tooltip line, and
custom_marksinjection are legacy Webcharts-era interactions not carried into the Chart.js reimplementation. Basic hover tooltips and click selection are implemented instead.
- Legacy-API note (SOE-API-001 source, SOE-CFG-001/002): the source SOE-API-001 ("a factory to create a custom Webcharts chart object") and the base-Webcharts settings describe the legacy Webcharts API, which the designs intentionally do not preserve. The module ships the pilot's lifecycle API instead — SOE-API-001 in the module scheme.
- Manual / out of automated scope (SOE-CFG-001/002, SOE-DATA-004, SOE-REG-030, SOE-REG-039/040/041/042): legacy CAT/viz-library demo checks and console-warning behaviors for invalid
start_value/ missing units. The invalid-measure and missing-unit console warnings are implemented invalidateAndCleanData/measureLabelbut not asserted by an automated row here.
Reproducing this report
The evidence set is regenerated from a full test run and committed with the code it qualifies; CI fails when they drift. To verify or rebuild it:
npm ci
npm run evidence:check # compare a fresh run against the committed evidence
npm run evidence # regenerate docs/evidence/outlier-explorer/evidence.jsonScreenshot baselines are canonical to the Linux CI runner; the repository's Update evidence baselines workflow is the authoritative way to refresh them. See CONTRIBUTING.md for the traceability convention.