Decision artifact2026-08-22awaiting your answerfive questions

Where the data-coverage numbers come from

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.

Lab rows in the bundled study: 405,720 That carry a visit label after the standard mapping: 0 Coverage the approved definition produces at one visit: 1,220% Change needed in a package we do not own: none
Answering this releases two items from the ranked ten

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 SITUATION

Three sentences

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.

WHAT THE DOMAINS ACTUALLY CARRY

Measured, not read off a specification

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 mappingWhat it carriesA visit label?
Labsstudy, participant, toxicity grade, result dateNo
Visitsstudy, participant, visit date, visit name, siteYes — the visit name
Participantssite, country, time on study, time on treatment, first-dose date, age, sex, raceNot applicable
Enrolmentstudy, participant, site, country, enrolled flag, enrolment dateNot applicable
Adverse eventsseriousness, grade, relatedness, start and end datesNo
ECGThere is no standard ECG mapping at all. The domain does not exist for any study on the stock configuration.

The visit label the lab rows do carry, and where it goes

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.

The same is true of the live demo study, in the other direction

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.

Declaring the column in the metric does not get it back, and fails quietly

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:

[INFO] Checking data against spec <- passes [INFO] Workflow Step 1 of 1 [FATAL] Error executing query: Referenced column "visnam" not found [INFO] NULL of length 0 saved as `lData$Result` [INFO] Completed Workflow <- no error raised to the caller

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.

Why this is not solved by fixing the mapping

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.

THE FIRST INFERENCE, MEASURED

Attaching a lab result to a visit by its date

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 triedResult
Lab rows whose date exactly matches a visit date for the same participant0 of 405,720
Attributing each lab row to that participant’s nearest visit date instead12.5% correct
What 12.5% isone in eight, on a study with eight visits — chance
Median distance from a lab result to the nearest visit50 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.

THE DEFINITION YOU APPROVED, MEASURED

“Expected” means the participants whose time on study reaches that visit

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:

VisitInferred dayExpectedWith a lab resultCoverage
Screening175559879%
Visit 1767459889%
Visit 226421598142%
Visit 348237598252%
Visit 459152598393%
Visit 579495981,220%
End of treatment920598no denominator
Follow-up1170598no 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.

Why this matters more than a bad table

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.

The live demo study is better behaved, and still not clean

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:

VisitDayExpectedWith a lab resultCoverage
Baseline1751751100%
Week 1865164699%
Week 21556556099%
Week 32248447999%
Week 429397397100%
Week 64328726492%
Week 85728615855%
Week 12851581711%
Week 161131717100%

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.

WHAT WORKS WITH THE DOMAINS AS THEY ARRIVE

One shape that needs nothing invented and nothing from upstream

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:

VisitAttended, of the enrolledWith a lab resultCoverage
Screening76259878.5%
Visit 176259878.5%
Visit 276259878.5%
Visit 376259878.5%
Visit 476259878.5%
Visit 576259878.5%
End of treatment76259878.5%
Follow-up76259878.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.

Neither study we have supports both halves today

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.

What a study has to supply, written down rather than discovered later

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.

InputWhere it comes fromIf a study does not supply it
A visit label on each lab recordthe study’s lab mapping passes through the visit-name column its raw data already hasno coverage rows at all; the metric stops and says which column it wanted
Which participants reached which visitthe study maps its visit table, which the standard mapping already supportsfall back to the schedule form below, or publish nothing
A visit schedule — label, order, scheduled daythe study declares it; our demo study already has the days sitting in its lab data and would be writing them down, not inventing themonly needed when there is no visit table
An ECG visit labelthe study’s own ECG mapping, since no standard one existscoverage covers labs only, and says so
THE QUESTIONS

Five things this cannot settle without you

Each carries a recommendation. Answering “all as recommended” is a complete answer; so is varying any one of them.

DC1 · the visit label

Where does a visit label for a lab result come from?

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:

  • The study says so. The study’s lab mapping passes through the visit-name column its raw data already has, and the coverage metric declares it as a required column and stops if it is absent. Nothing is inferred anywhere. The cost is that a study on the stock configuration publishes no coverage until it opts in.
  • Infer it from dates. Match each lab result to the visit whose date it falls on or nearest to. Costs nothing to build and works on no study we have: zero exact matches out of 405,720 lab rows, and 12.5% correct — chance — when matched to the nearest visit.
  • Do not attribute lab results at all. Report visit attendance from the visit table and drop the idea of per-visit lab coverage. Cheap, honest, and it answers a different question than the one the census asked.
Recommendation: the study says so. It is the only one of the three that can be qualified, and the demand is not a new one — two of the package’s three existing safety metrics already require lab and ECG columns the standard mapping does not supply, and the live demo study already passes the visit label through. The opt-in cost is real and it is small: one line in a mapping file, in the study’s own configuration, for a study that wants the number.
DC2 · the denominator

What defines the day a visit is expected on, and does a study have to supply it?

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.

  • The visit table is the denominator. Expected at a visit means the study’s visit records show that visit happening for that participant. No schedule, no scheduled day, no inference. Works on the bundled study today; needs the demo study to start mapping a visit table. What it forecloses is worth stating plainly: a visit that never happened is not in the table, so a participant who stopped attending leaves the denominator rather than reading as missing data. This form measures whether the visits that occurred produced results; it cannot measure whether the visits that should have occurred did.
  • A declared visit schedule. The study supplies a small table — visit label, order, scheduled day — and expected is your definition applied against it. This is clinically the better answer, it keeps your original one intact, and it is the only one of the three that can see a visit that simply did not happen. It needs each study to write its schedule down; our demo study would be transcribing days that are already exact in its data rather than inventing them.
  • Infer the schedule from observed dates. The cheapest, and the one that produced the 1,220%. It is also the one that would look identical to the other two on the finished page.
Recommendation: support the first two as declared inputs, take the visit table when both are present, and never the third. That is a variation on what you approved, not an execution of it, which is why it is here: your definition survives as the second form and becomes the one a study opts into by declaring a schedule, while the first form gives every study that maps its visits a coverage number that can be checked. If you would rather hold to time on study as the only definition, say so and the demo study gets a declared schedule as part of this work — but the bundled study cannot qualify that number, and the metric would ship without a second route behind it.
DC3 · results outside the denominator

What does the page do with a result from someone the denominator says is not there?

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.

  • Count only participants who are in the expected set. Coverage never exceeds 100%, and on the demo study’s last visit 269 participants with a real lab result are silently not counted.
  • Count everyone with a result. Nothing is hidden and coverage reads 1,682% at that visit, which tells a reader nothing except that something is wrong.
  • Count only the expected, and publish the outsiders as their own number. Coverage stays interpretable and the discarded results become a visible data-quality figure instead of a silent subtraction.
Recommendation: the third. It is the shape you already approved once on this rebuild, when the death count published the disagreement between its two sources as a number of its own rather than resolving it quietly. The same reasoning applies here and the cost is one extra descriptive figure.
DC4 · a study that supplies neither

If a study supplies no visit label and no expected count, does coverage report nothing, or report what it can?

  • Nothing. No coverage rows, the report renders without the section — which is what it does today — and one line names the input the study did not supply.
  • The counts without a denominator. Publish how many participants have a result at each visit, labelled as a count rather than as coverage, when a visit label exists but no expected count does.
  • Fall back to total enrolment. What the function did before this rebuild, and what your earlier answer removed.
Recommendation: nothing, and say which input was missing. The census already keeps absent, empty and zero apart in all twelve of its shipped numbers, and this is the same rule: a study that has not said what a visit is has not measured coverage, and a page that shows a bare count invites the reader to supply the missing denominator from memory — which is exactly the wrong denominator this question exists to remove. The third option is out on your own earlier answer.
DC5 · ordering

What puts the visits in order?

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.

  • The study declares the order, as a visit number beside the label or as the scheduled days in a declared schedule. Our demo study already carries a visit number; the bundled study does not.
  • Order by the middle of each visit’s observed dates. Measured on the bundled study, this recovers the correct clinical order. It is still an inference, and it can inverse two visits whose dates overlap heavily — an early-termination visit against a late scheduled one, for instance.
Recommendation: the study’s declared order when there is one, the observed middle when there is not, and the day it ordered on printed on the row either way. An ordering a reader can see the basis of is not the same kind of risk as a denominator they cannot; publishing the key is what keeps it from being a hidden assumption. Alphabetical is not among the options.
WHAT UNBLOCKS

What each answer releases, and what it costs

If you answerWhat startsWhat it costs
All five as recommendedThe 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 expectedThe 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 countCoverage 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 columnNothing 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.
WHAT THE RECOMMENDATION STILL INFERS

One inference survives, and here is what the page shows when it is wrong

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.

CORRECTIONS

Four things written down before this were not right

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.

HOW EVERY FIGURE HERE WAS MEASURED

Reproducible, on stated versions

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.