Sapling SAP
Get started

Your first SAP in 10 minutes

A first plan from a protocol, the visual editor, a block changed with its form, what the plan needs, the PDF and the products.

This tutorial is for a statistician who has never used Sapling. You start from a protocol and finish with a draft statistical analysis plan (SAP), its PDF, and the structured SAP that the analysis chain reads. You do not need to know the Sapling syntax: the editor writes the first plan from the protocol, and you work in the visual editor, a document with forms. The compiler checks every change at once. The .qmd file under it stays the one source, and you can show it beside the document at any time.

The example is the CDISC pilot study (CDISCPILOT01, protocol H2Q-MC-LZZT). Its protocol is in examples/cdiscpilot01/protocol/ of the Sapling repository: CDISC_Pilot_Study_v4.json (the protocol as CDISC USDM) and protocol.json (its text, section by section). Its ADaM specification is in examples/cdiscpilot01/adam/.

The short way: one command line (Rails-style)#

If you like a terminal, five commands take a protocol and its SDTM data to the study dashboard (docs/omakase.md):

sapling new mystudy --protocol usdm.json --sdtm path/to/sdtm   # the study folder and a first SAP with the defaults
cd mystudy && sapling open                                     # the SAP in the visual editor: change what you like
sapling decide                                                 # the open decisions; answer each with --by "<your name>"
sapling build && sapling run                                   # the PDF, the specs, the programs, the ADaM, the TLFs
sapling dashboard                                              # the study dashboard

The status bar of the editor shows the next step ("Next: sapling build"), and the insert palette (+ or /) has the same generators under Ready-made from your protocol. The rest of this tutorial does it in the editor, step by step.

Before you start (once, 3 minutes)#

You needHow
VS Code or Positronany recent version
The Sapling extensioncd vscode && npm install && npm run package, then code --install-extension vscode/sapling-sap-0.7.0.vsix (Positron: its code command, or Extensions → … → Install from VSIX)
Your AI agent (optional)the AI command-line agent you already use, a local model, or any command: install it, log in once, and choose it in the setting sapling.ai.provider. Sapling uses your own login; it never reads or stores a key. Everything except Ask AI works without it.
Quarto (for the PDF)install it from https://quarto.org/docs/get-started/ (sapling doctor checks it)

Open the folder examples/cdiscpilot01 in the editor (File → Open Folder).

1. A first plan from the protocol (1 minute)#

  1. Open the Command Palette (⇧⌘P, or Ctrl+Shift+P) and run Sapling: New SAP from Protocol (USDM)….
  2. Choose CDISC_Pilot_Study_v4.json in the list of the protocols (CDISC USDM) of the folder (Another file… opens a file dialog). The editor finds protocol/protocol.json (the protocol's text) and the adam/ folder (the ADaM specification) by itself.
  3. Keep the study id it proposes, or type CDISCPILOT01. Save the plan as study.qmd.

The plan has the sections of a SAP in the order of the SAP guideline (Gamble et al. 2017) and already contains what the protocol says: the three arms, the visits, the significance level, the design, the planned 300 patients, the objectives and endpoints, the estimand EST1, three populations and the tests that the protocol names. Each rests on a sentence of the protocol. Everything the protocol leaves open is an open decision (about 29). The plan compiles with 0 errors.

2. The visual editor (1 minute)#

The plan opens in the visual editor, as a document that looks like its PDF: the cover with the title and the DRAFT mark, the contents and the progress on the left (the decisions made, the blocks with a source, the findings left), the sections, the text, the populations, the tables and the estimand. A strip on top of a new plan says what to do next. The bar on top shows the state: Compiles (or the number of errors), the warnings of the review, the open decisions. Click one: the navigator lists them all with their message, their source and their section; a click goes there, and the count, the arrows of the list, F8 and ⇧F8 step through them. ⇧⌘K (or the search button) finds a section or a block by its words (MMRM, SAFFL, Week 24) and inserts a block ("insert table").

Plans open in the visual editor by default; to open them as text: Sapling: Use the Visual Editor for Plans by Default (on/off).

3. Change a block with its form (2 minutes)#

Go to Analysis populations (in Statistical principles) and click the efficacy population.

The first plan has no tables yet. Open pilot.qmd (the pilot SAP, written out) in the visual editor to see them, or add one with + → Table (step 4). Go to the demographics table (4.2 of pilot.qmd). The table designer shows the population, the Total column, the p-values, one row per variable with its test, and the footnotes. Click Categorical to add a row: it takes a variable that the table does not show yet. Choose its test. The shell under the form (As typeset) changes as you type; the table button of the card shows the shell as the chain makes it.

Go to the efficacy table (4.3.3) and click Model on the row P_ADAS. The equation is in an equation editor: type in it, or open LaTeX under it (the math as text, as it is written between $$ in the plan). Each symbol is bound to an ADaM variable (The symbols). The green box shows what the compiler reads: the formula CHG ~ BASE + SITEGR1 + TRTPN, the method (ANCOVA, test for linear dose response), the dose, the covariates and the factors. Options of the model makes it an MMRM (covariance us, the fallback structures in order, Kenward-Roger). A new Model analysis row starts as an equation too; a row written as an R formula has Write it as an equation.

Under the model, the Method Lab (docs/method-lab.md) shows the analysis from four sides: Formula (the model, the estimand to the estimator, the hypotheses, the test statistic, the CI), Program (R, SAS and pseudocode for exactly this analysis, to copy or open), Assumptions (the checks on BLINDED data), Simulation (the type I error and the power of the planned test, against the sample size) and Example (the program on dummy data, its numbers labelled EXAMPLE). The R parts run when you click Run; the data mode is on every tab; unblinded data only when you ask, each time. The data folder: the setting sapling.lab.data.

4. Add what the plan needs (3 minutes)#

Move the pointer between two blocks: a + shows on the left. Click it (or type / in the text) and choose a block: a population, an estimand, a table, an open decision, multiplicity, sample size, missing data, a sensitivity analysis, ... It is inserted as a form with values from your plan: a new Population takes the ADaM population flag the plan does not use yet (the safety flag first) with its name; the Adverse events table (TEAEs by SOC and PT), Demographics table, Efficacy table with a model and Table by visit come with the population that fits. A block's Duplicate makes a copy with new ids. For example, add Multiplicity, choose the procedure graphical, two hypotheses with their weights and the transitions: the graph is drawn under the form.

Ask AI (in the palette, on the bar, or on a card) drafts a block from your words, for example: Write a table of the treatment-emergent adverse events by maximum severity for the safety population. The draft is compiled in its place before you see it; when it does not compile, the compiler's messages go back to the AI (at most twice). You see the block typeset and "Compiles in its place". Nothing is written until you click Insert. The block carries the mark drafted by the AI until you read it and remove the mark.

5. Fix what the compiler finds (1 minute)#

A card with an error has a red mark in the margin; a card with a warning of the review an amber one. Open the card: the messages are at the bottom, each with the fix, the guideline it rests on, and the quick fixes as buttons. For example, when the plan says AVISIT = "WEEK 24", the card says "WEEK 24" is not a value of ADQSADAS.AVISIT and offers Write AVISIT = "Week 24". A rule that the plan does not follow on purpose: Waive with a reason…, then write the reason; the PDF shows it. A fix the visual editor cannot make as a button shows the text to write under Fix:. For example the safety tables without a safety population have Add the safety population SAF and use it on ….

6. The PDF and the products (2 minutes)#

WhereWhat you get
PDF (the bar of the visual editor)out/study.pdf: title page with the approval table, the sections, the estimand boxes, the protocol's words under each block, the table shells in the appendix
Previewthe plan typeset beside the editor
Sapling: Build the Structured SAPout/sap.md (the structured SAP the chain reads), out/sap.json, out/sap.html
Sapling: Run the Chain's Checkerthe chain's own checker sap_build.py on the plan: SAP BUILD PASS (it needs the scratch chain: zsh tools/chain_proof.sh once)

From a terminal: node src/cli.ts pdf study.qmd and node src/cli.ts build study.qmd.

What you did not do#

You did not approve the plan, and you did not decide the open decisions in the AI's place. Only a person approves: when the decisions are made and the review is clean, the statistician writes approved: {by: Name, on: Date, role: statistician} under sapling: and status: APPROVED under sapling: in the plan. The compiler, the AI and the MCP server refuse to write them.

Next#