open.gismo · data loading · direction C · mockup

The report is the interface

This is the document og_read() would write after being pointed at a six-file CRO delivery — an HTML file in the project at intake/report.html, committed alongside the workflows. It is clickable. Answer a finding and the ledger at the top moves, and the diff at the bottom shows the YAML that answering wrote into the project.

Every number below is measured. The inventory is generated from the actual profile of the actual fixture; the display counts come from resolving demo-301’s 39 metric and module workflows back to the raw columns they consume. Nothing here is illustrative.

~/brightstar/intake/report.html
Intake report · read 2026-08-27 09:14 · og_read() v0.3.0

I read six files and understood most of them.

~/brightstar · 60,938 rows · 50 columns · 4.08 MB · nothing in this folder was modified

Four things need an answer from you. Each one is priced in the displays it costs, biggest first. Twenty displays are not available at all and there is nothing to answer about them — they are listed at the bottom so you know what they would have been.

3
✔ Will render, complete
Everything these need is present and unambiguous.
6
⚠ Will render, wrong
These will produce output that looks fine and is not. Answering findings 1 to 3 fixes them.
10
◐ Blocked, one answer away
Waiting on a column nothing carries but everything is here to build. Finding 4.
20
✖ Cannot render
Seven extracts were not supplied. No answer here can change this.

Thirty-nine displays, each counted once. The second number is the one that matters. A display that renders wrongly is more expensive than one that does not render, because nobody goes looking for it.

1 · What I found

Every file in the folder, whatever its name or format. Expand a row to see the column profile.

FileFormatRowsColsWhat I think it is

Read with haven for the transport file and utils::read.csv for the rest. open.gismo v0.2.0 reads only CSV today; haven and arrow are already installed in the stack and never called.

2 · What needs an answer

Ranked by the number of displays affected, not by how confident I am.

Your hepatic explorer will draw an empty chart, and nothing else will tell you

2 displays

The eDISH chart does not ask for a column — it asks for four literal strings inside one. Every column check on your lab files passes. I compared the values instead.

the chart names, in workflows/4_modules/hep_explorer.yaml: ALT → "Alanine Aminotransferase" TB → "Bilirubin" AST → "Aspartate Aminotransferase" ALP → "Alkaline Phosphatase" your three lab files hold 15 distinct analyte names: lab_central.csv TEST ALB ALKP ALT AST CREAT GLUC K lab_specialty.csv ANALYTE TBILI GGT lab_haem.csv LBTEST Hematocrit Hemoglobin Lymphocytes … matched: 0 of 4 — the chart renders, with no series on it units checked: TBILI is umol/L against a umol/L limit; the cut-points are multiples of the upper limit, so the mismatch is safe. Recorded.
Confirm ALT=ALT, AST=AST, TB=TBILI, ALP=ALKP? Confirmed — 4 analytes bound.Left unbound. The chart will render empty and the site will say so.

One lab file’s participant IDs do not join to anything

4 displays

The mapping joins labs to participants with an inner join. As delivered this one returns nothing. The column is present, typed, and complete — there is no check anywhere today that would catch it.

1,005 identifiers in dm.xpt USUBJID S1000 · S1001 · S1002 1,005 identifiers in lab_haem.csv SUBJID 0301-S1000 · 0301-S1001 · 0301-S1002 overlap as delivered .......... 0.00 (0 of 1,005) overlap after removing "0301-" 1.00 (1,005 of 1,005) lab_central.csv SUBJECT and lab_specialty.csv PT_ID both join cleanly at 1.00. This file is the only one with the prefix.
Strip the leading 0301- from lab_haem.csv.SUBJID? Applied — 21,450 haematology rows recovered.Left as delivered. This file will contribute nothing.

Three files look like one lab domain

all 6

They share a shape — a participant ID, an analyte name, a numeric result, a visit — and between them they cover the whole panel with no analyte appearing twice. data-config.yaml maps one domain to one file today, so this is currently inexpressible.

proposed Raw_LB = lab_central ∪ lab_haem ∪ lab_specialty = 28,600 + 21,450 + 7,150 = 57,200 rows, 16 analytes, no overlap reference range present: lab_central yes lab_specialty yes lab_haem no columns at all → six haematology analytes will carry a null normal range. Consequence: they get no CTCAE grade in finding 4, and the shift plot's reference band is blank for those measures. Saying this now rather than after the run.
Stack the three into Raw_LB? Stacked — 57,200 rows, six analytes flagged as range-less.Not stacked. Only lab_central will be read as Raw_LB.

Five columns nothing carries, that I can build from what you sent

10 displays

There is no column to point at for these, so no mapping surface can ask about them. Two of the five are assumptions rather than facts, and both are marked as such below and on every display that uses them.

Raw_AE.aest_dy AESTDTC − RFSTDTC 2,583 / 2,583 clean Raw_AE.aeen_dy AEENDTC − RFSTDTC 2,583 / 2,583 clean Raw_SUBJ.timeonstudy last dated record − RFSTDTC 765 / 765 RFENDTC is empty for all 1,005 rows — you sent no exit date. "Last dated record" stands in for it. Median 28 d, max 119 d. Raw_LB.toxgrg_nsv CTCAE v5 from result ÷ upper limit 3,575 ALT rows band as G0 2838 · G1 465 · G2 79 · G3 173 · G4 20. Haematology has no range (finding 3) so gets no grade. Raw_AE.aetoxgr substituted from AESEV 2,583 / 2,583 severity is not toxicity grade. Three levels standing in for five. Lossy. Every display built on it will carry the mark.
Derive all five, marks and all? Derived — 10 displays unlocked, two marked.Not derived. Those ten displays stay dark.

3 · What answering has written

Nothing is written until you answer. This is the whole diff, and it is yours to edit or revert.

Nothing written yet. Answer a finding above.

Column renames are one source_col: line each — an existing, exercised gsm.mapping feature. Prefix strips, analyte bindings and derivations have no declarative home in the spec today and would be written as steps: entries, which is the weakest point in this direction (see W2).

4 · What I cannot build, and why

Twenty displays. No answer available — these need an extract you did not send. Acknowledging records the decision so the next read does not raise it again, and the study site prints “not supplied” where the tile would have been.

EDC audit trail8 displays Query rate and age, data entry lag, data change rate — at site and country level.
Protocol deviations4 displays Important and total PD rates.
Disposition5 displays Study and study-drug completion, plus one quality tolerance limit.
ECG2 displays The QT explorer and the QTc metric.
Eligibility criteria1 display The eligibility-violation tolerance limit.

Live. The three counters, the finding states and the diff all move together — answering finding 4 is the only one that adds displays; the other three convert displays from “renders wrongly” to “renders correctly”, which is the distinction this direction is built around.

What the mock is claiming, and what it is not

Mockup for direction C of the open.gismo data-loading design session. The direction, the hard case and the weaknesses.


Drafted by Claude Code using Opus 5 and reviewed by @jwildfire