AI Software Engineer · Statistical Programming in R — clinical trial tables · SAS → R migration · AI with independent validation
I build AI tools for statistical programming that never get the last word. In a trial analysis the risky failure is quiet: a translated SAS program that rounds a half differently, or a table whose denominator came from the wrong dataset. My work puts AI on the routine drafting (SAP → table shells and R programs, SAS → R translation, answering "where does this number come from?") and puts an independent check behind every output: rebuilt numbers compared to the published CSR, side-by-side SAS vs R diffs, and sign-off by a programmer and a statistician. The copilot drafts and routes; people approve.
🔭 Building → TrialProof Studio and Forward 2028: AI drafts R for trial tables, independent checks verify every number
🧪 Measuring → table rebuilds vs the CSR, SAS → R equivalence, AI output vs an independent reference
🌱 Learning → CDISC ADaM / SDTM depth, pharmaverse (admiral, rtables), regulatory-grade R validation
AI writes the R, an independent engine checks every number, a person signs off. An LLM agent inspects ADSL/ADAE, proposes an analysis spec for approval, then writes and runs R in a sandbox. A separate deterministic engine recomputes the TEAE table (subjects, denominators, percentages, by SOC and PT) from the approved spec and compares it cell by cell: double programming, built in. Fault-injected programs (events counted instead of subjects, wrong denominator, efficacy instead of safety population, dropped TE filter, wrong or missing percentages, invented zero-count rows) all fail; the correct program passes 417/417 and reconciles with a separately written R recomputation. Sign-off is enforced on the server: only a current, verified run can be approved, and any later change to the program, spec or data marks it stale. R runs in a bubblewrap sandbox that must pass an isolation self-test before any code executes.
R·dplyr·FastAPI·React + TypeScript·Monaco·CDISC ADaM·pytest·LLM agents·Fly.io
🔁 adae-sas2r — SAS → R, validated
The CDISC Pilot
adae.sas(with its%flagfrstmacro) translated by hand into tidyverse R and validated against the released ADaM ADAE: 1,191 / 1,191 rows, 55 / 55 columns, 0 value differences (diffdf), 8testthattests. Found along the way:lubridate::ymd("2012-02")silently returns 2020-12-02, so partial dates are parsed the way SASyymmdd10.does. Adds a TEAE incidence table and an exploratory negative binomial rate model (28-day window, overdispersion 3.26).
R·tidyverse·diffdf·testthat·MASS::glm.nb·Quarto
📏 sas2r-bench — can AI translate SAS into R that gives the same answer?
A benchmark that measures instead of impresses: CDISC Pilot SAS programs are translated by different models, the R is executed on real data, and the output is scored against published CSR cells or the released datasets, with comparators committed before any translation existed. AE tables reproduce exactly (417/417 and 354/354 CSR cells); ADAE reaches 96% of cells, which still counts as a fail. The bench also surfaced bugs on the SAS side.
R·Python·CDISC·LLM evaluation·sandboxed execution
A game-based academy that takes programmers from R basics to reproducible statistical programming: 5 worlds, 15 challenges that run real R in the browser (webR) and are validated automatically, video lessons, and knowledge checks. Built for teams moving from SAS to R.
R·webR·Next.js·TypeScript·GitHub Pages
An end-to-end R workspace for clinical trial statistical programming, built on public CDISC Pilot Study data. A request moves Requested → AI drafting → checks → programmer review → statistician review → approved, with an audit log. SAP → tables: the copilot drafts table shells and R programs from the SAP, and every printed number is checked against the CSR: 451 of 474 equal across 5 tables, with each of the 23 differences explained (22 from recoded data, 1 where the CSR didn't follow its SAP). SAS → R studio: scan for risky constructs, translate, run, diff, sign off, over a 12-program benchmark that also surfaced bugs on the SAS side. Trace a number from a table cell back to ADaM, SDTM and the CRF; amendment impact finds 18 of 19 recorded SAP changes; ten rule-based data checks on SDTM AE vs DM; a director dashboard in Shiny. Runs deterministically by default (recorded, validated runs); live AI is server-side with a spend cap.
R·tidyverse·Shiny·plumber·testthat·Quarto·CDISC SDTM / ADaM·SAS → R·React + TypeScript·GitHub Actions
The same discipline in another domain: pre-registered, paired experiments on held-out seeds, Holm-corrected tests, conformal bounds and published negative results. Example: a fixture-based drift monitor recovers pick success from 7/50 to 42/50 (p = 6e-11) with 0 false alarms in 1,000 frames; a pre-registered study of 299 paired episodes lifts success 0.488 → 0.773 (Holm p = 3e-14).
Python·experimental design·paired tests / multiplicity·conformal prediction·PyTorch
🛍️ Also — PennyPilot · cre-copilot
Also: a multi-turn RL shopping agent (SFT → RLOO with a verifiable reward and a structural safety gate, pre-registered data-recipe loop), and multi-agent incident response on Azure with a deterministic confidence + permission gate and human-in-the-loop remediation.
PyTorch·LoRA·RL (RLOO · GRPO · PPO)·Azure OpenAI·React + TypeScript
🔧 Open source — OpenSearch Dashboards · search-relevance
Contributing to a production OpenSearch plugin used by search-relevance engineers: a performance fix replacing O(n²) result matching with id lookup maps (#910) and surfacing real experiment errors instead of a generic failure message (#911).
TypeScript·React·OpenSearch·Jest
- AI that drafts, people who approve: copilots for SAPs, tables and code questions that cite their sources and hand off what they can't settle.
- SAS → R you can trust: translation plus side-by-side output diffs, so differences like rounding rules are found before sign-off.
- Validation first: every number traced to its source and checked against an independent reference or the published record.
📫 Reach me at madan.pa@northeastern.edu


