gsm.safety release review 2026-08-15

What v1.1.0 adds, annotated

gsm.safety could draw the eDISH chart but could not tell you how many participants were in the Hy's Law quadrant. v1.1.0 adds the metrics phase that answers that — three participant-level safety metrics, each tuned against measured counts before being treated as real — plus SafetyCensus(), the denominators a safety overview leads with. Every capture below is the release's code running live inside the DEMO-301 study site.

3 participant-level metrics — a new 2_metrics phase 1 286 tests pass · R CMD check clean runs live in DEMO-301 → Safety promotes dev → main via gs#52

gs#45 · hub#138

The metrics phase: from chart to count

Three participant-level metrics, cut down from a longer candidate list by @jwildfire: saf0001 Hy's Law candidate, saf0002 QTcF prolongation, saf0003 serious / related AE. Each scores one row per participant with an ordinal tier through the standard gsm contract — Analyze_Identity() + Flag(), following gsm.kri's pat0015 precedent — so subject rows land in Reporting_Results beside site and country rows and nothing downstream changes. The liver and QT cut-points come from the vendored data contracts of the charts they correspond to, so the metric and the chart cannot drift apart.

The Hy's Law Candidate metric page on DEMO-301: metric header (saf0001, Participant level, eDISH Quadrant Tier, 765 scored), then the flagged-participant queue — red rows with peak ALT/AST, bilirubin and ALP values, amber rows below, each with a review score. 1 2 3
  1. 1 The metric states its contract: level Participant, score "eDISH Quadrant Tier", thresholds 1,3 — 765 scored
  2. 2 100 flagged, 9 red — the Hy's Law queue, cholestatic cases excluded per the rule
  3. 3 Every finding is a sentence with the labs in it: peak ALT/AST, bilirubin, ALP in ×ULN

Why it matters

A chart shows the quadrant; a metric gives review a workable queue with a defensible tier behind every name. Because the cut-points are read from the same vendored contracts the charts use, "the chart says quadrant, the metric says tier" can never silently disagree.

Try it

Open saf0001 on DEMO-301
  1. Read the header contract, then the red rows — 9 participants, each with its labs.
  2. Switch to saf0002: QTcF, carried by the change criterion.
  3. Cross-check the 9 red against the Hepatic Safety Explorer quadrant.
hub#138 · the gate

Tuned on real counts, before being treated as real

hub#138's Data Requirement set a binding gate: actual flagged-participant counts on demo data are reported before any metric is treated as real. The counts below are the release's own evidence — and two of them changed the design.

MetricScoredGreenAmberRed
saf0001 Hy's Law candidate765665919
saf0002 QTcF prolongation4003088111
saf0003 serious / related AE76544625168

Measured on DEMO-301's mapped output, 765 enrolled participants. Three findings reading the code would not have surfaced: the QTcF metric is carried by the change criterion (exactly one participant exceeds 500 ms absolute; ten more reach red only through ≥ 60 ms change from baseline); only 400 of 765 participants have a post-baseline QTcF at all — a coverage finding, and why the overview leads with coverage; and the AE metric as first written flagged 560 of 765 participants, so its amber threshold moved up a tier — "serious or related" alone is a property of being in a trial, not a review signal.

The Serious / Related AE metric page: 319 participants flagged, 68 red, each row a sentence — counts of AEs, serious, related — with review scores.

The retuned queue. After the gate, saf0003 flags 319 of 765 — 251 amber, 68 red — a queue someone can actually work, with amber starting at a serious event and red at a serious, related event at or above the grade cut. The discontinuation leg has no source column in this demo's AE domain; Input_SafetyAE() records ActionColumnPresent = FALSE on every row rather than scoring as though nobody discontinued — the gap is stated in the output.

Why it matters

Safety metrics that ship untested against real distributions become dashboards nobody trusts. The gate is the release's discipline: every threshold in this package has a measured consequence attached, and the one figure that did not reproduce (the design artifact's 22-participant quadrant count) is corrected in the record — 31 with both axes elevated, 22 cholestatic exclusions among them, 9 surviving.

Try it

Open saf0003 on DEMO-301
  1. Read the header: 319 flagged, 68 red, thresholds 2,3.
  2. Each row is a sentence: total AEs, serious, related.
  3. Compare with AE Explorer — same Mapped_AE rows.
gs#47

SafetyCensus: the denominators, stated first

SafetyCensus() reduces the mapped domains to what a safety overview leads with: enrollment, randomisation, exposure, person-years, deaths — and data coverage per visit, the figure that decides whether a quiet visit is reassuring or empty.

DEMO-301's Safety overview rendered from SafetyCensus output: census and exposure tiles (765 enrolled, 741 dosed, 49.8 person-years on treatment, 5 deaths), then data coverage by visit falling from 100% at baseline to 2% at week 12.

The census as DEMO-301 renders it. Week 12 labs cover 17 of 765 participants (2%) — the display says so before anyone reads "no week-12 findings" as good news. This is the same coverage fact that explains saf0002's 400-of-765 scored count above.

Why it matters

Every rate in a safety review is a numerator over one of these denominators. Computing them once, in the package, from the mapped domains — instead of ad hoc in each display — is what lets an overview lead with them consistently.

Try it

Open the Safety overview
  1. Read the tiles, then scroll to coverage by visit.
  2. Find week 12 — 2% — and week 16 back at 37%.
gs#46 · hub#136

The standard gsm phase layout

The report workflows move from inst/workflow/3_reports/ to inst/workflow/4_modules/ — the standard gsm phase directory for meta.Type: Report workflows, the one gsm.kri already uses — and the new 2_metrics/ phase slots in where the ecosystem expects metric generation. 3_reports was the one phase directory in the portfolio that deviated, and it sorted beside gsm.reporting's unrelated 3_reporting.

inst/workflow/
├── 1_mappings/          # unchanged
├── 2_metrics/           # NEW — metric generation, ahead of module assembly
│   ├── saf0001.yaml     #   Hy's Law candidate
│   ├── saf0002.yaml     #   QTcF prolongation
│   └── saf0003.yaml     #   serious / related AE
└── 4_modules/           # was 3_reports/ — the gsm standard for Report workflows
    ├── ae_explorer.yaml … safety_shift_plot.yaml   # 9 modules, unchanged content

One breaking path. Any pipeline that globbed inst/workflow/3_reports/ updates its path — demo-301's did, in the same arc. Workflow content is unchanged.

Why it matters

The gsm pipeline's phases are a contract (1_mappings → 2_metrics → 3_reporting → 4_modules), and open.gismo's runner discovers workflows by these directories. Conforming means a study can point one runner at gsm.kri and gsm.safety alike — which is exactly how the DEMO-301 site above was built.

Try it

Browse inst/workflow on dev
  1. Open 2_metrics/saf0001.yaml — the full Input → Flag chain in YAML.
  2. Note DEMO-301's RBQM header: workflows: 1_mappings, 2_metrics, 3_reporting, 4_modules.
notes

Reading this page

How the captures were made

  • Playwright drove Chromium against the live DEMO-301 deployment on 2026-08-15 — a study site whose pipeline runs the metrics and census this release ships. Nothing was staged or mocked. DEMO-301 is a synthetic study — no real participant data.
  • Stills are 2× JPEG.

Also in the release, not shown here

  • New exported functions: Input_HysLaw(), Input_QtProlongation(), Input_SafetyAE(), SafetyCensus() and metric utilities, each roxygen-documented.
  • Test coverage for every new surface — 1 286 tests pass, R CMD check clean.
  • NEWS.md becomes the running release log per the program convention.

Where this fits

This page is the review surface for RC gs#52 (dev → main). gsm.safety is a clinical repo: nothing reaches main without your review. The release notes live in the RC PR's body and in NEWS.md, and publish on the v1.1.0 tag when it merges — on your approval, via the attested lane, and not before.

The rest of the candidate

  1. DEMO-301 → Safety — the release running live
  2. gs#47 — the increment PR with the full design record (D1–D6)
  3. open.gismo v0.2 demo — the site these metrics render in