Sapling SAP
Get started

Quick start: from a protocol PDF to a first checked part

The smallest path through the plan language, from the command line.

One page. The reference of every block is markdown.md; this page is the smallest path through it.

1. A study from the protocol#

sapling new mystudy --protocol protocol.pdf      # protocol/protocol.txt, and the skeleton sap.qmd
cd mystudy
sapling check                                    # SAPLING CHECK PASS

sapling new prints the pages of the PDF it could not read as words (pictures, letter-spaced or cipher text) and the parts of the SAP whose section it did not find. sap.qmd has one part per item of a SAP (Gamble et al. 2017), and in each part one open decision that names the section of the protocol to read:

## Analysis populations

::: {.decision}
Declare each analysis set with its definition, and say which analyses use it. The protocol speaks of it in section 4.1 (Analysis populations).
:::
[]{.cite source="protocol:4.1"}

2. Write a part#

Replace the decision of a part with its blocks. A block is a fenced div: ::: {.kind #ID key="value"}, its text, :::. The examples below cite the protocol of the CDISC pilot study (examples/cdiscpilot01); in your study, cite the sections of your protocol.

A population:

::: {.population #EFF condition="ADSL.EFFFL" definition="Patients with a baseline and at least one postrandomization measurement"}
Efficacy population
:::
[]{.cite source="protocol:4.1"}

An estimand with one intercurrent event:

::: {.estimand #EST1 level="primary" population="EFF" analysis="P_ADAS"}
**Change from baseline in the ADAS-Cog (11) total score at Week 24**

[Xanomeline TTS at 54 mg or 81 mg, or placebo, for 24 weeks]{.treatment}
[Change from baseline to Week 24 in the ADAS-Cog (11) total score]{.endpoint}
[Discontinuation of the study drug]{.intercurrent strategy="treatment policy"}
[]{.cite source="protocol:4.3.3" words="Effects in the ANCOVA model"}
:::

The primary analysis, a table with its model (the outer div has more colons):

:::: {.tlf #T_ADAS population="EFF"}
**ADAS-Cog (11): change from baseline to Week 24**

::: {.analysis #P_ADAS}
**ANCOVA of the change from baseline at Week 24**

[]{.data dataset="ADQSADAS" records='PARAMCD = "ACTOT" and AVISIT = "Week 24" and ANL01FL = "Y"'}
[]{.formula formula="CHG ~ BASE + SITEGR1 + TRTPN"}
:::
::::
[]{.cite source="protocol:4.3.3" words="Effects in the ANCOVA model"}

A decision the protocol leaves to you (when the protocol is silent, it cites nothing and says so):

::: {.decision}
The protocol's investigator effect is the pooled site SITEGR1. Confirm that its pooling is this rule.
:::
[]{.cite source="protocol:4.3.3" words="For all ANOVA and ANCOVA models"}

3. Where a citation stands#

[]{.cite source="protocol:4.3.3" words="..."} points at the sentence of the protocol that has the words. Its place says what it is the source of:

  1. on the line right after the closing ::: of a block (no empty line), or in the body of an estimand or a table: that block;
  2. at the end of a heading line (## Efficacy []{.cite ...}): every block of that section that has no citation of its own;
  3. inside a sentence of prose: that paragraph (a footnote in the PDF), and the tests the paragraph names.

4. Check, or ask#

sapling check                          # after each edit: fix the first error with its fix: line
sapling ai "state the primary estimand with its intercurrent events"   # the AI drafts; the diff; --yes to apply
sapling sap pdf                        # the SAP with each block as a box (Quarto)

sapling ai puts the block in the part of its kind, in the place of that part's open decision, and writes it only when the plan with it has no error and you say so; else it saves the draft in out/ai/ (sapling ai --apply <file>). An approval, the answer of a decision and a waiver are yours: no tool writes them.