Twelve of the thirteen census numbers are built and merged. The thirteenth — how completely the data was collected, visit by visit — could not be, because no standard domain says which visit a lab result belongs to, and the definition of “expected” you approved needs a scheduled day that no standard domain carries either. Both gaps can be closed by guessing, and a guessed coverage figure looks exactly like a measured one. So this page measures what every guess would actually produce, on both studies we have, and asks you five questions instead.
The thirteenth census metric sits under the census rebuild, which is second on the ranked list; the data-coverage chart, whose first item this is, is third. Nothing else in the census is waiting: all four steps of the rebuild are merged and only this number is outstanding.
The safety census now publishes twelve numbers as metrics the pipeline computes and can check one at a time, and the thirteenth — data coverage per visit, the number that tells a reader whether a quiet visit is reassuring or empty — is the only one that was not built. It was not built because the lab domain, as the standard mapping delivers it, carries a study identifier, a participant identifier, a toxicity grade and a date, and nothing that says which visit a result came from; and because “expected”, which you defined as the participants whose time on study reaches that visit, needs a scheduled day for each visit that no standard domain supplies. Both missing pieces can be reconstructed by inference, and this page exists because an inferred coverage figure is indistinguishable on the page from a measured one — which is the defect the whole rebuild was written against.
Everything below was produced by running the standard mapping over the ecosystem’s own bundled study and looking at what came out, on the package versions the automation installs today. The three previous sessions on this question each found a documented claim that turned out not to be true, so nothing here is relayed.
| Domain, after the standard mapping | What it carries | A visit label? |
|---|---|---|
| Labs | study, participant, toxicity grade, result date | No |
| Visits | study, participant, visit date, visit name, site | Yes — the visit name |
| Participants | site, country, time on study, time on treatment, first-dose date, age, sex, race | Not applicable |
| Enrolment | study, participant, site, country, enrolled flag, enrolment date | Not applicable |
| Adverse events | seriousness, grade, relatedness, start and end dates | No |
| ECG | There is no standard ECG mapping at all. The domain does not exist for any study on the stock configuration. | |
The raw lab table in the bundled study has a visit-name column on every one of its 405,720 rows. The standard lab mapping declares four columns — study, participant, toxicity grade, result date — and the ingest step keeps only what the mapping declares, so the visit name is dropped on the way in. The label is not missing from the study. It is discarded by a specification we do not control.
Our own demo study writes its own lab mapping rather than taking the standard one, and that mapping already declares a visit name, a visit number and a study day on every lab row. It has been carrying the exact inputs this number needs since it was built. What it does not have is a visit domain: it ships no visit table at all.
The obvious repair is for the coverage metric to declare the visit column in its own definition, the way every other census metric declares the columns it reads. That does not work, because the column was already dropped before any metric runs — and the way it does not work is the dangerous part. Running a metric that declares the visit column against the standard mapped data produces this:
The specification check passes. The step fails. The workflow returns nothing and reports success. A report built on that would render with no coverage rows and no explanation, which is the failure mode this programme keeps meeting: an operation that reports success while doing nothing.
The cleanest repair in the whole problem is four lines: add the visit name and visit number to the standard lab and ECG specifications, and every study on the stock configuration gets coverage for free. That file belongs to another organisation and this programme does not write there. If you want it, it is a request you would make to them, not work anyone here can schedule — and everything below is designed so that we never need it.
If the lab row has a date and the visit table has dates, a lab result can be attributed to the visit it falls on. That is the inference the last session left on the table, and it is the one that would be invisible on the finished page. Here is what it does on the bundled study.
| What was tried | Result |
|---|---|
| Lab rows whose date exactly matches a visit date for the same participant | 0 of 405,720 |
| Attributing each lab row to that participant’s nearest visit date instead | 12.5% correct |
| What 12.5% is | one in eight, on a study with eight visits — chance |
| Median distance from a lab result to the nearest visit | 50 days |
The reason is worth knowing, because it is not a rounding problem. The bundled study’s entire lab domain carries three distinct dates. Sixty-one per cent of lab rows are dated on the participant’s enrolment date, and the median participant has exactly one distinct lab date across all eight of their visits. The lab date in that study is not a visit date at all, and no matching rule can recover a visit from it.
The correctness figure above is measurable only because the raw lab rows carry the true visit label — so the guess can be scored against the answer. That is the whole argument against shipping the guess: on this study it is checkable and it is wrong, and on a study where it is not checkable it would publish anyway, with nothing on the page to say which kind of study a reader is looking at.
That was your answer on the census design, and it was the right instinct: a study that enrolled half its participants last month should not read as though it were missing half its data. It was also recommended to you on the grounds that it asks no study for anything new, because time on study is already on the standard participant mapping. That second half does not survive measurement, and you should see why before you decide anything else on this page.
To ask whether a participant’s time on study reaches a visit, you need to know what day that visit falls on. No standard domain carries one. The visit table gives the date each participant attended, not the day the visit was scheduled for. So the scheduled day has to come from somewhere, and the only source available without asking a study for it is the observed dates themselves — the middle of the range at which participants actually attended. Doing exactly that, on the bundled study, produces this coverage table:
| Visit | Inferred day | Expected | With a lab result | Coverage |
|---|---|---|---|---|
| Screening | 1 | 755 | 598 | 79% |
| Visit 1 | 7 | 674 | 598 | 89% |
| Visit 2 | 26 | 421 | 598 | 142% |
| Visit 3 | 48 | 237 | 598 | 252% |
| Visit 4 | 59 | 152 | 598 | 393% |
| Visit 5 | 79 | 49 | 598 | 1,220% |
| End of treatment | 92 | 0 | 598 | no denominator |
| Follow-up | 117 | 0 | 598 | no denominator |
The cause is not the inference. It is the study: every one of its 762 enrolled participants has a visit calendar spanning longer than their own recorded time on study — a median of 117 days of visits against a median of 30 days on study. The visit table and the time-on-study column describe two different studies. So on the study every census figure is qualified against, the definition cannot be checked at all, whether the scheduled day is guessed or handed to us.
Every one of the twelve census numbers that shipped was measured twice, by two routes sharing no code, and the two had to agree. That is what qualifying a number means here. This definition, on the only study available to qualify it against, produces coverage above one hundred per cent at three visits and divides by zero at two more. A number that cannot be qualified cannot be released under the rule the rest of the census was built to.
Our demo study carries an exact scheduled day on every lab row — the same day for every participant at a given visit, which is a real visit schedule sitting in the data. Applying your definition there works far better, and still breaks at the tail:
| Visit | Day | Expected | With a lab result | Coverage |
|---|---|---|---|---|
| Baseline | 1 | 751 | 751 | 100% |
| Week 1 | 8 | 651 | 646 | 99% |
| Week 2 | 15 | 565 | 560 | 99% |
| Week 3 | 22 | 484 | 479 | 99% |
| Week 4 | 29 | 397 | 397 | 100% |
| Week 6 | 43 | 287 | 264 | 92% |
| Week 8 | 57 | 286 | 158 | 55% |
| Week 12 | 85 | 158 | 17 | 11% |
| Week 16 | 113 | 17 | 17 | 100% |
Two hundred and eighty-six of that study’s 765 enrolled participants have at least one lab result dated after their recorded time on study ends, and 269 of the 286 participants with a week-16 lab are outside the expected set by that measure. Counted the naive way — everybody with a result, over everybody expected — week 16 reads 1,682%. Counted as the table above does it, by only counting participants who are in the expected set, it reads 100% and the 269 disappear silently.
That is a design decision hiding inside an arithmetic, and it is the third question below. Dirty source data is normal in trials and is not a reason to escalate anything; what it is a reason for is deciding, once and in writing, what the page does with a result that falls outside its own denominator.
There is a version of this number that infers nothing at all. It has two halves, and both of them are things a study says rather than things we work out.
This is demonstrated rather than proposed. The same one-step metric whose log appears above — the one that returns nothing at all under the standard mapping and reports success while doing it — returns the eight visits and their participant counts as soon as a study-level lab mapping passes the visit name through. Same metric, same study, same package versions; the only change is one line in the study’s own mapping file.
On the bundled study, with the visit label restored by one line in a study-level lab mapping, that produces the following — and every figure in it comes from a domain reading rather than a calculation:
| Visit | Attended, of the enrolled | With a lab result | Coverage |
|---|---|---|---|
| Screening | 762 | 598 | 78.5% |
| Visit 1 | 762 | 598 | 78.5% |
| Visit 2 | 762 | 598 | 78.5% |
| Visit 3 | 762 | 598 | 78.5% |
| Visit 4 | 762 | 598 | 78.5% |
| Visit 5 | 762 | 598 | 78.5% |
| End of treatment | 762 | 598 | 78.5% |
| Follow-up | 762 | 598 | 78.5% |
The flatness is the study, not the method: every participant in it attends all eight visits and 598 of the 762 have any lab record at all, so the same 164 participants are missing at every visit. It is a dull table and it is a true one, and it can be checked against the domains by a second route — which is the bar the other twelve numbers cleared.
The bundled study has the visit table but drops the lab visit label under the standard mapping. The demo study passes the lab visit label through but ships no visit table. Each is one small, ordinary piece of study configuration away from supporting this number, and neither piece is in a package we do not own.
This is the part your requirement asked to be explicit, so it is stated here as the contract rather than left to whoever builds it.
| Input | Where it comes from | If a study does not supply it |
|---|---|---|
| A visit label on each lab record | the study’s lab mapping passes through the visit-name column its raw data already has | no coverage rows at all; the metric stops and says which column it wanted |
| Which participants reached which visit | the study maps its visit table, which the standard mapping already supports | fall back to the schedule form below, or publish nothing |
| A visit schedule — label, order, scheduled day | the study declares it; our demo study already has the days sitting in its lab data and would be writing them down, not inventing them | only needed when there is no visit table |
| An ECG visit label | the study’s own ECG mapping, since no standard one exists | coverage covers labs only, and says so |
Each carries a recommendation. Answering “all as recommended” is a complete answer; so is varying any one of them.
A coverage table has a row per visit, so every lab result has to be attributable to one. The standard mapping does not carry that attribution and we cannot change the standard mapping. Three ways to get one:
You answered a version of this already: expected means the participants whose time on study reaches that visit. Carrying it out needs a scheduled day per visit, and the measurements above are the reason this is being put back to you rather than built — on the study every census number is qualified against, that definition produces coverage of 1,220% at one visit and no denominator at all at two more, because that study’s visit calendar and its time-on-study column disagree with each other for every participant in it.
On the live demo study, 286 of 765 enrolled participants have a lab result dated after their recorded time on study ends. Whatever defines expected, some results will fall outside it. There are three things a coverage table can do, and they produce different numbers from the same data.
A coverage table is read left to right in time, and the old function ordered visits alphabetically. On the bundled study alphabetical order puts “End of Treatment” and “Follow-up” before “Screening”. The fix is not automatic: a visit label on its own carries no order.
| If you answer | What starts | What it costs |
|---|---|---|
| All five as recommended | The thirteenth census metric can be written and qualified against the bundled study, and the coverage chart above it has a defined input. Both ranked items move. | One line in the demo study’s configuration to map its visit table, and an extra descriptive figure for the results that fall outside the denominator. |
| Time on study as the only definition of expected | The metric can still be written, and the demo study gets a declared schedule as part of the work. | The number ships without a second route behind it, because the bundled study cannot produce a coherent one. That is a departure from how the other twelve were qualified, and it should be a deliberate one. |
| Publish counts without a denominator when a study has no expected count | Coverage appears on more studies sooner, including the demo study before it maps a visit table. | The report carries a per-visit number that is not coverage, and readers supply their own denominator. |
| Nothing until the standard mapping carries a visit column | Nothing here; the question moves to another organisation’s queue. | The thirteenth number and the chart stay unbuilt for as long as that takes, and neither ranked item moves. |
The recommended design infers nothing about which visit a result belongs to and nothing about who is expected. It infers one thing: when a study declares no visit order, the visits are ordered by the middle of their observed dates.
Everything else that could have been inferred is refused rather than defaulted: the metric stops when the visit label is absent, and publishes nothing rather than a fallback denominator when no expected count exists.
None of them changes what you decided; all of them change something that was argued in front of you or written into an issue.
One claim held exactly as written: a metric that declares a column the mapping dropped does not receive it. What was not recorded is that it fails silently — the specification check passes, the step logs a fatal error, and the workflow returns nothing while reporting completion.
Requirement: where the data-coverage numbers come from, on the roadmap — #306. Blocked by it: the thirteenth census metric, gsm.safety#58, under the census rebuild #274; and the data-coverage chart, #291. Answers on: the census design, D0023, question C2.
Drafted by 👯🤖 Claude Code (Claude Opus 5, worker W0121) for 🧭🤖 obot-navigator. Not reviewed by @jwildfire before publication.