open.csr · design report
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.
@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.
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.
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.
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.
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.
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.
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:
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.
| Display | In the clinical study report | In the synopsis |
|---|---|---|
t-disposition | Table 14.1.1 | Table 13.1 |
t-demographics | Table 14.1.2 | Table 13.2 |
t-exposure | Table 14.3.1.1 | Table 13.3 |
t-ae-overview | Table 14.3.1.2 | Table 13.4 |
t-ae-common | Table 14.3.1.3 | Table 13.5 |
l-ae-serious | Listing 14.3.2.1 | Listing 13.6 |
From the same display specifications and the same unchanged prose. Nothing in library/tfl/ knows which document it is in.
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.
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.
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.
| Document | What it is | Structure comes from | Status here | What it would take |
|---|---|---|---|---|
| Clinical study report | The full report | ICH E3, public | Built | — |
| Study synopsis | The three-page summary; often circulated alone | ICH E3 Annex I, public | Built tonight | — |
| Post-text display package | The Section 14 tables, figures and listings as a standalone deliverable — what a statistician reviews before the report exists | The study's own SAP | Not built | Mechanical. A display-only model with no narrative; the framework already assembles a post-text index |
| Abbreviated / integrated report | The reduced report E3 permits for studies not intended to support a claim | ICH E3 §1, public | Not built | Mechanical. A subset model over the same text and display libraries |
| Plain-language summary | The lay summary EU CTR requires for every trial | EU CTR Annex V, public | Not built | Needs a decision. Its content rules are about reading level and non-promotional language, which no gate here can check |
| Analysis Data Reviewer's Guide | Explains the analysis datasets to a regulatory reviewer; ships in every consortium pilot | PHUSE ADRG template | Not built | Needs a decision, and a licence check on the PHUSE template. Also needs dataset-level metadata open.csr does not hold |
| Study Data Reviewer's Guide | The same for the tabulation datasets | PHUSE SDRG template | Not built | As above, plus SDTM metadata the framework never sees |
| Statistical analysis plan | The pre-specification the displays are supposed to satisfy | House template; no public standard | Not built | Needs a decision. It is upstream of everything here, and modelling it would change what a display specification is |
| Display shells | The empty table layouts the SAP defines and the report fills | The SAP | Partly present | Mechanical. display.yaml already carries the layout; a shell is that rendered without an ARD |
| Analysis results metadata | Machine-readable description of what each result is; CDISC ARS is the emerging standard | CDISC ARS | Not built | Needs a decision on whether open.csr's analysis.yaml becomes an ARS profile or stays its own thing |
| Protocol | Now machine-readable in its own right | ICH M11, Step 4, Nov 2025 | Out of scope | Different tool. Worth naming because M11 is what a CSR standard would be modelled on if one existed |
| Submission cover letter and eCTD skeleton | What actually goes to the agency | Regional guidance | Out of scope | Different tool |
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.
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.
| Pilot | What it demonstrates | Document artifacts published |
|---|---|---|
| Pilot 1 | R-based analyses in a submission package | Cover letter, a TLF report PDF, an ADRG PDF, define.xml, four TLF programs, four rendered outputs |
| Pilot 2 | A Shiny application as a submitted artifact | eCTD package, app source |
| Pilot 3 | ADaM datasets and an extended define | eCTD package, ADaM programs |
| Pilot 4 | The app again, as WebAssembly and as a container | eCTD packages, app source |
| Pilot 5 | Dataset-JSON as the transport format | eCTD package, utilities, a Quarto website |
| Pilot 6 | Expanding the ADaM and TLF programs for future submissions | Nine ADaM programs, one table program, an ARD, a define, the CDISC pilot study's own SAP and CSR PDFs |
| Pilot 7 | Synthetic data | In progress |
| ADRG pipeline | Automating the reviewer's guide | Pipeline 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.
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.
| Repository | Licence | Can open.csr incorporate it? |
|---|---|---|
submissions-pilot1, -pilot2, -pilot3-adam, -pilot3-utilities, -pilot5-datasetjson-to-fda | GPL-3.0 | No — 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-utilities | AGPL-3.0 | No — 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 packages | None | No — 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-transparency | MIT | Yes, but they are webinar and transparency materials with nothing a template object would want |
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.
Three things, none of which required copying anything.
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.
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.
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 report | Displays | open.csr today |
|---|---|---|
| Populations and disposition | 3 | 1 — t-disposition |
| Demographics and baseline characteristics | 1 | 1 — t-demographics |
| Efficacy | 13 | 0 — no efficacy analysis dataset exists (D12) |
| Exposure | 1 | 1 — t-exposure |
| Adverse events | 2 | 3 — t-ae-overview, t-ae-common, l-ae-serious |
| Laboratory | 6 | 0 |
| Vital signs, weight, concomitant medications | 4 | 0 |
| Figures | 1 | 0 |
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.
Written so someone could execute them, and split by whether they need @jwildfire.
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.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.provenance_section at it. The assembler refuses to build without one.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.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 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.
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.
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.