open.csr · design report

CSR template objects — what the report framework still has to be taught

A study does not produce one document. It produces a dozen, and until this evening open.csr could build one of them. This is what the second one turned out to be, what the other ten would take, and why the R Consortium submission pilots — the obvious place to borrow from — turn out to be almost entirely off limits.

1 → 2template objects in the library, after tonight
12document types a CSR framework plausibly needs
26R Consortium submission repositories examined
0of them reusable in open.csr as it is licensed
31 + 1displays the reference report for our test study contains
6of them open.csr can produce today

The question underneath the ask

@jwildfire asked for additional template objects for the test study, referencing the consortium submission projects, before showing open.csr to colleagues. The literal ask is small. The question underneath it is not, and it is worth stating before the answer: is the template layer a framework, or is it one ICH E3 file with two names?

Until tonight there was no way to tell. A template object in open.csr is a pair of files — a document model that says what this kind of document is, and an assembly that says what this report puts in it — and the code that walks that pair is entirely generic. But the library held exactly one instance, and the assembler hard-coded its path. Generic was a property of the code, not a property anything checked.

What shipped

A second real template object: the ICH E3 Annex I study synopsis, twenty-five sections, assembled against the same test study, from the same analysis results datasets, through the same gates. It is the smallest document that exercises every part of the framework at once, and the two documents now share a value store — so where they quote the same quantity they quote the same number, and the build fails if that stops being true.

1 · What a template object actually is

Two YAML files in a directory under library/templates/. That is the whole contract, and it is worth reading once because everything below depends on the split.

The document model

sections.yaml

What this kind of document is. A flat list of sections, each with a number, a title, a stable slug, and a declaration of what content it can hold: narrative, an in-text display, a container for post-text displays, or assembler-generated provenance.

  • Reusable across every study
  • Encodes a standard, not a report

The assembly

assembly.yaml

What this report puts in it. Which text blocks fill which sections, which displays render in-text, which displays occupy which post-text slot, and the study's own identifying facts.

  • One per report
  • Names nothing it does not populate

The split is what makes the numbering claim possible. A display is identified by its slug, never by its number; the number is assigned at build time from the order it appears in the assembly. That is design decision D6, and until tonight it was a claim in a comment.

2 · The second one, and what it proves

The ICH E3 Annex I synopsis. E3 prints it as a labelled form — sponsor, title, investigators, studied period, phase, objectives, methodology, number of patients, and so on to the conclusion and the date of the report. Encoding that form as a document model gives a document that is short enough to read in two minutes and complete enough to exercise everything.

Three things it demonstrates that a second copy of the CSR model would not have:

Two documents cannot disagree about a number

The synopsis and the report both draw from one store of named values. 254 randomised, 43.3% completed, 217 patients with a treatment-emergent adverse event: the same figures appear in both because both bind the same value, not because someone checked. Every value is re-derived from the committed analysis results dataset at build time, so a value that has drifted fails both builds in the same breath.

The same display carries a different number in each

DisplayIn the clinical study reportIn the synopsis
t-dispositionTable 14.1.1Table 13.1
t-demographicsTable 14.1.2Table 13.2
t-exposureTable 14.3.1.1Table 13.3
t-ae-overviewTable 14.3.1.2Table 13.4
t-ae-commonTable 14.3.1.3Table 13.5
l-ae-seriousListing 14.3.2.1Listing 13.6

From the same display specifications and the same unchanged prose. Nothing in library/tfl/ knows which document it is in.

A gap stays visible instead of disappearing

Both documents declare their efficacy sections and leave them marked unpopulated. No efficacy analysis dataset exists for this study in pharmaverseadam, and the reference report for the same study devotes thirteen tables to efficacy. A synopsis that quietly dropped the efficacy headings would have looked more finished and told the reader less.

Not reviewed

The eighteen text blocks written for the synopsis are all marked draft, and every build prints a draft warning for each one. They are agent-drafted prose. The sentences most worth a read are the ones where the analysis datasets cannot supply an Annex I answer — planned sample size, enrolment dates, batch numbers — which say so plainly rather than inventing a number.

3 · The twelve documents a CSR framework plausibly needs

Written from what a study actually has to produce, not from what would be easy. The last column is the honest one: what stands between open.csr and building it.

DocumentWhat it isStructure comes fromStatus hereWhat it would take
Clinical study reportThe full reportICH E3, publicBuilt
Study synopsisThe three-page summary; often circulated aloneICH E3 Annex I, publicBuilt tonight
Post-text display packageThe Section 14 tables, figures and listings as a standalone deliverable — what a statistician reviews before the report existsThe study's own SAPNot builtMechanical. A display-only model with no narrative; the framework already assembles a post-text index
Abbreviated / integrated reportThe reduced report E3 permits for studies not intended to support a claimICH E3 §1, publicNot builtMechanical. A subset model over the same text and display libraries
Plain-language summaryThe lay summary EU CTR requires for every trialEU CTR Annex V, publicNot builtNeeds a decision. Its content rules are about reading level and non-promotional language, which no gate here can check
Analysis Data Reviewer's GuideExplains the analysis datasets to a regulatory reviewer; ships in every consortium pilotPHUSE ADRG templateNot builtNeeds a decision, and a licence check on the PHUSE template. Also needs dataset-level metadata open.csr does not hold
Study Data Reviewer's GuideThe same for the tabulation datasetsPHUSE SDRG templateNot builtAs above, plus SDTM metadata the framework never sees
Statistical analysis planThe pre-specification the displays are supposed to satisfyHouse template; no public standardNot builtNeeds a decision. It is upstream of everything here, and modelling it would change what a display specification is
Display shellsThe empty table layouts the SAP defines and the report fillsThe SAPPartly presentMechanical. display.yaml already carries the layout; a shell is that rendered without an ARD
Analysis results metadataMachine-readable description of what each result is; CDISC ARS is the emerging standardCDISC ARSNot builtNeeds a decision on whether open.csr's analysis.yaml becomes an ARS profile or stays its own thing
ProtocolNow machine-readable in its own rightICH M11, Step 4, Nov 2025Out of scopeDifferent tool. Worth naming because M11 is what a CSR standard would be modelled on if one existed
Submission cover letter and eCTD skeletonWhat actually goes to the agencyRegional guidanceOut of scopeDifferent tool
The cheapest next two

The post-text display package and the abbreviated report. Both are subset models over libraries that already exist, both assemble from the six displays already built, and neither needs a decision from @jwildfire or a licence from anyone. Between them they would take the library from two template objects to four without authoring a single new sentence of prose.

4 · What the consortium actually publishes

The R Consortium Submissions Working Group runs a series of pilots that submit R-based analyses to the FDA and publish the whole package. Twenty-six repositories under the RConsortium organisation carry submission in their name. Each pilot splits in two: a development repository, and a -to-fda repository holding the eCTD package as submitted.

PilotWhat it demonstratesDocument artifacts published
Pilot 1R-based analyses in a submission packageCover letter, a TLF report PDF, an ADRG PDF, define.xml, four TLF programs, four rendered outputs
Pilot 2A Shiny application as a submitted artifacteCTD package, app source
Pilot 3ADaM datasets and an extended defineeCTD package, ADaM programs
Pilot 4The app again, as WebAssembly and as a containereCTD packages, app source
Pilot 5Dataset-JSON as the transport formateCTD package, utilities, a Quarto website
Pilot 6Expanding the ADaM and TLF programs for future submissionsNine ADaM programs, one table program, an ARD, a define, the CDISC pilot study's own SAP and CSR PDFs
Pilot 7Synthetic dataIn progress
ADRG pipelineAutomating the reviewer's guidePipeline source

The artifact closest to what open.csr does is Pilot 1's four TLF programs — tlf-demographic, tlf-primary, tlf-efficacy, tlf-kmplot — and Pilot 6's t_14_1_1.r, which builds an analysis results dataset and renders from it, the same shape open.csr uses. That is a genuine convergence and worth saying out loud: two independent efforts arrived at ARD-first rendering.

5 · The licence position, which decides most of this

open.csr is Apache-2.0, in LICENSE, in package.json and in the R package DESCRIPTION. Every consortium repository was checked against the GitHub API rather than assumed.

RepositoryLicenceCan open.csr incorporate it?
submissions-pilot1, -pilot2, -pilot3-adam, -pilot3-utilities, -pilot5-datasetjson-to-fdaGPL-3.0No — one-way incompatible. Apache-2.0 code may be taken into a GPL-3.0 project; GPL-3.0 code may not come the other way without relicensing open.csr entirely
submissions-pilot5-utilitiesAGPL-3.0No — stricter still
submissions-wg, -pilot1-to-fda, -pilot2-to-fda, -pilot4, -pilot4-webR, -pilot4-container, -pilot5-datasetjson, -pilot5-website, -pilot6-adams-tlfs, -pilot7-synthetic-data, -adrg-generation-pipeline, pilot1-to-pmda-submission, and the remaining -to-fda packagesNoneNo — a public repository with no licence file is all rights reserved under GitHub's terms. Being able to read it is not permission to reuse it
submissions-git-collab-power, submission-transparencyMITYes, but they are webinar and transparency materials with nothing a template object would want
The counter-intuitive half

The repositories holding the most useful artifacts — the ADRG, the define, the eCTD skeletons, Pilot 6's ARD-based table program — are the ones with no licence at all. The submission packages are published so people can read a real submission, and that purpose does not need a licence, so nobody added one. The result is that the most reusable-looking material is the least reusable.

Nothing in tonight's pull request derives from any of it. Both document models are encoded from ICH E3, a public guideline, on the same footing the existing model already used, and the pull request says so in the file header where a future reader will find it.

This is a question worth asking the working group rather than working around. Several of these repositories would probably carry a permissive licence if someone asked; none of them will start doing so on their own.

6 · What the consortium work does give us

Three things, none of which required copying anything.

The test-study data, under a licence that works

open.csr already builds on pharmaverseadam, which is Apache-2.0 — the same licence open.csr uses. That is the one clean lane, and it is the one already in use.

A convergent design, independently arrived at

Pilot 6 computes an analysis results dataset and renders the table from it, rather than computing inside the table program. open.csr does the same. Two efforts reaching the same architecture is worth a sentence in the README, and costs nothing.

An honest measure of how far along we are

Pilot 6 carries the CDISC pilot study's own statistical analysis plan, which lists the displays a real report for our test study contains: thirty-one tables and one figure, in seven groups. Reading that as a fact about the study — not copying it — gives a gap analysis nothing else could:

Display group in the reference reportDisplaysopen.csr today
Populations and disposition31 — t-disposition
Demographics and baseline characteristics11 — t-demographics
Efficacy130 — no efficacy analysis dataset exists (D12)
Exposure11 — t-exposure
Adverse events23 — t-ae-overview, t-ae-common, l-ae-serious
Laboratory60
Vital signs, weight, concomitant medications40
Figures10

Six of thirty-two, and the six are the safety spine. That is a fair position for a framework at this stage, and it is a far more useful sentence to put in front of a colleague than a claim that the framework is complete.

7 · Steps to the next template object

Written so someone could execute them, and split by whether they need @jwildfire.

Mechanical — no decision required

  1. Create library/templates/<id>/sections.yaml with the document's sections. Numbers must be dotted and numeric, slugs unique and permanent, and every section declares what content it accepts.
  2. Create library/templates/<id>/assembly.yaml naming only the sections this report populates. A section left unclaimed appears as a heading marked unpopulated, which is the honest default.
  3. Declare a section that accepts generated provenance, and point provenance_section at it. The assembler refuses to build without one.
  4. Run node scripts/assemble.mjs --template <id>. Every gate runs. Cross-references are the usual first failure: a text block written for another document may point at a section this model has not got.
  5. Add requirement rows and a test file carrying their IDs. The requirement checker fails on an ID no test references and on a test referencing an ID no matrix row defines.

Needs a decision

8 · What I could not establish

The PHUSE ADRG template's licence terms

Every consortium pilot ships an ADRG built from the PHUSE template. PHUSE deliverables are generally published for free use, but I did not establish the actual terms, so no ADRG template object was designed here beyond naming what it would need. Anyone picking that up should establish the terms first.

The CDISC pilot study material's terms

The statistical analysis plan and mock report for our test study are CDISC publications, redistributed inside an unlicensed consortium repository. I read them to establish what displays the study has and cited that as a fact; I copied no structure, no title list and no text into the repository. If display titles from that document were ever wanted in shipped YAML, the terms would need establishing first.

Whether the missing licences are deliberate

I did not ask, and would not have: writes outside the jwildfire organisation are out of bounds for this work, issues and comments included. The observation stands as an observation.

Where this leaves the ask

Sources: the RConsortium organisation's twenty-six submission* repositories, read through the GitHub API on 2026-08-26; pharmaverse/pharmaverseadam; ICH E3 (1995), Step 4, Section 2 and Annex I; the CDISC pilot statistical analysis plan carried in submissions-pilot6-adams-tlfs; and the open.csr repository at branch csrtemplates.

Read-only outside the jwildfire organisation. No issue, comment, pull request or fork was created in any RConsortium, CDISC, PHUSE or pharmaverse repository.


Drafted by Claude Code (Opus 5) as worker W0131.