| editor |
|
|---|
shigella is an R package for multivariate Bayesian hierarchical
modeling of antibody response trajectories following confirmed Shigella
infection. Chapter 2 extends the univariate Chapter 1 approach (handled
upstream in the serodynamics package) to a Kronecker-structured
covariance model (
- Type: R package (statistical modeling)
- Language: R (>= 4.1.0), Stan (cmdstanr backend)
- Key Dependencies: cmdstanr (>= 0.9.0), serodynamics, posterior, cli, dplyr, MASS, tibble
- Lifecycle: Experimental — Chapter 2 simulation is the active
branch (
chapter2-stan-simulation) - Repository owner: UCD-SERG (Aiemjoy / Morrison labs)
Follow the UCD-SeRG Lab Manual for culture, reproducibility, GitHub workflows, coding practices, and AI tools usage. If the web version is inaccessible, refer to the source files on GitHub.
This package follows strict standard R package layout. Do not create
subdirectories under R/, and do not place R/, inst/, or
vignettes/ folders inside any other directory (e.g., a former
chapter2/R/ subfolder was a structural error and was removed; do not
recreate that pattern).
-
R/: All exported and internal R functions. One function per file. File name must match function name (dotted internal helpers like.helper_fn()go inR/helper_fn.R— drop the leading dot in the filename only). -
inst/extdata/: Model files (JAGS today, plus the Stan models that the chapter branches carry). -
inst/examples/: One example script per exported function, named<function_name>-examples.R. -
tests/testthat/: Unit tests, namedtest-<function_name>.R. -
vignettes/: Quarto vignettes (.qmd). Chapter 2 manuscript-style documentation goes here. -
scripts/: Shiva HPC orchestration scripts (Phase 0/1 diagnostic runs). Listed in.Rbuildignore— not part of the package build. -
slurm/: SLURM sbatch files for Shiva. Also in.Rbuildignore. -
man/: Auto-generated documentation from roxygen2 — do not edit directly.
-
DESCRIPTION: Package metadata. KeepImportsminimal (currently cli, dplyr, MASS, tibble). Optional functionality belongs inSuggests. -
NAMESPACE: Auto-generated — do not edit. -
.lintrand.lintr.R: Custom lintr configuration. -
.Rbuildignore: Must exclude^scripts$,^slurm$, and^chapter2$(last for historical safety). -
_typos.toml: Where accepted terms for crate-ci/typos go, at the repo root, created on demand. -
AGENTS.mdandCLAUDE.md: Short orientation files for AI coding agents, both deferring to this file as the source of truth. Record a repository convention here and let them point at it.
-
All R functions live directly in
R/. No subdirectories. -
Every exported function has:
@title,@description,@paramfor every argument,@return,@export, and either@examplesinline or@example inst/examples/<fn>-examples.R.
-
One function per file. File name matches function name. Internal helpers are dotted (
.helper_fn()) and live inR/helper_fn.R. -
Stan model files belong in
inst/extdata/, never in a nested folder.
- Every exported function has a matching example file in
inst/examples/<function_name>-examples.R. - Examples must NOT depend on confidential Shigella data files. Use
sim_correlated_case_data()to generate synthetic data instead. - For Stan-fitting examples, use minimal settings (n = 5 subjects, 100
warmup + 100 sampling, 1 chain) so the example completes within ~5
minutes on CI. Wrap heavy fits in
if (interactive() && requireNamespace("cmdstanr", quietly = TRUE)).
- Every function in
R/should have a test intests/testthat/test-<function_name>.R. - For Stan-fitting tests, use minimal MCMC settings and consider
testthat::skip_on_ci()if the test exceeds ~5 minutes. - Tests for
sim_correlated_case_data()must verify the generated data has the intended structure: correct dimensions, correct ground-truth correlation sign, thetruthattribute is present.
- Real Shigella data files (anything matching
dL_clean_*.rda,data/*.rdacontaining patient data, or*.xlsxwith patient records) MUST be in.gitignoreand MUST NOT be committed. - Flag any PR that adds files with
clean_,dL_, or patient-identifying content.
- Stan files (
.stan) belong ininst/extdata/. - Compiled Stan binaries (no extension, or
.exe/.hpp) belong in.gitignore. - When a Stan model file is modified, verify:
- Likelihood computed in log space (no
expfollowed bylog). - Priors are weakly informative (sigma typically ≤ 5 on log-scale parameters).
- LKJ priors use
lkj_corr_cholesky, notlkj_corrdirectly.
- Likelihood computed in log space (no
- Both the full Kronecker model (
model_2.stan) and any future block-covariance simplification (model_2_block.stan) should be preserved. The convergence proposal identifies all four cross-biomarker / cross-parameter covariance structures as scientifically relevant; block simplification is an operational trade-off, not a project-scope redefinition.
scripts/andslurm/are Shiva-only directories. They are not built into the package and not expected to run in GitHub Actions. Do NOT flag them for missing tests.- However: the R functions they call (e.g.,
run_phase0_diagnostic(),run_phase1_diagnostic()) live inR/and DO need to pass GitHub Actions tests. - Scripts must NOT contain function definitions or
source()calls. They contain onlylibrary(shigella), parameter setup, and function invocations. Flag any function definition orsource()insidescripts/. - Phase 0 scripts are designed to run under
salloc(interactive SLURM allocation), NOT on the login node directly.
- Vignettes are Quarto
.qmdfiles rendered with thequartopackage. - Chapter 2 manuscript-style documentation belongs in a single
vignettes/chapter2.qmdwith the standard 4-section structure (Introduction / Methods / Results / Discussion), all math in one file. Do not fragment into separate methods/demo files.
- Follow the tidyverse style guide: https://style.tidyverse.org
- Native pipe:
|>not%>% - Naming: snake_case for functions, arguments, and most objects.
Uppercase acronyms allowed (e.g.,
Omega_B,tau_P). Constants use UPPER_SNAKE_CASE. - Maximum line length: 120 characters (per
.lintr). - No
library()in package code: Use::or declare inDESCRIPTIONImports. source()is banned in the package. Uselibrary(shigella)for end-user contexts (vignettes, examples, scripts) ordevtools::load_all()for developer workflows.- No
<<-(global assignment). - User-facing messages use
cli::cli_inform(),cli::cli_warn(),cli::cli_abort()— notmessage(),warning(),stop(). See.lintr.Rfor the enforced list. - No developer names in user-facing messages. Strip any reference
to specific people ("Kwan Ho", "Ezra", etc.) from
cli::cli_*(),cat(),message()output. - Decompose long functions and long loops: any R function > ~40 lines or any loop body > ~5 lines should be split into named helpers (one function per file).
# Install development dependencies
install.packages(c("devtools", "remotes"))
remotes::install_github("UCD-SERG/serodynamics", upgrade = "never",
dependencies = NA)
install.packages("cmdstanr",
repos = c("https://stan-dev.r-universe.dev",
"https://cloud.r-project.org"))
cmdstanr::install_cmdstan()
# Install the package itself
devtools::install(".", upgrade = "never")For minimal install (skipping Suggests), use base R:
cd ~/shigella
R CMD INSTALL .Always regenerate documentation after modifying roxygen2 comments.
devtools::document()man/ and NAMESPACE are auto-generated. Do not edit directly.
devtools::check()Allow ~5 minutes. Acceptable post-cleanup state: 0 errors, 0 warnings,
≤1 NOTE (the serodynamics:::calc_fit_mod triple-colon use is a known
tolerated exception, marked with # nolint: namespace_linter).
devtools::test()Tests live in tests/testthat/ and use testthat 3.0+ with edition 3
config (see DESCRIPTION).
lintr::lint_package()Lint must be clean on every commit. Treat lint failures with the
same urgency as test failures. See .lintr.R for the full custom
config. Custom rules include:
cli::cli_*()enforced overmessage()/warning()/stop().- Native pipe
|>enforced over%>%. - snake_case with uppercase acronyms allowed.
source()flagged.
If a lint must be suppressed, use # nolint: <linter_name> on the
specific line with a justifying comment, and mention it in your PR
summary.
spelling::spell_check_package()Custom words live in inst/WORDLIST.
A second, separate accept-list lives in _typos.toml — see "Two Accept-Lists" below.
Most workflows under .github/workflows/ are thin callers of reusable
workflows in
Morrison-Lab/gha, pinned to @v2.
Read the callee at its pinned tag before changing a caller's with: or
secrets: block: a caller passing a secret the pinned tag does not declare is
rejected before any job starts, and that failure produces no logs, no
annotations, and no check run.
Hand-maintained here, because gha models no equivalent:
- R-CMD-check.yaml — Runs
R CMD checkon multiple platforms. - R-check-docs.yml — Verifies
roxygen2::roxygenise()output matches committedman/andNAMESPACE. - check-readme.yaml — Renders
README.Rmd. - pkgdown.yaml — Builds the pkgdown site.
- test-coverage.yaml — Coverage, uploaded to Codecov.
- pr-commands.yaml —
/documentand/stylePR commands. - copilot-setup-steps.yml, phase0-debug.yaml — Copilot agent environment setup, and a manual Phase 0 diagnostic run.
Called from gha:
- spellcheck.yml —
{spelling}over package prose, acceptinginst/WORDLIST. - check-typos.yml — crate-ci/typos over the lines a PR adds, accepting
_typos.toml. - lint-changed-lines.yml — lintr over the lines a PR adds or modifies, rather than whole changed files.
- version-check.yml and bump-dev-version.yml — the version pair described under "Versioning" below.
- news.yaml — requires a
NEWS.mdentry, bypassed with theno changeloglabel. - check-junk-files.yml, check-secrets.yml, check-phi.yml, check-links.yml, check-new-line-breaks.yml — hygiene and safety checks.
- lint-workflows.yml, lint-yaml.yml, lint-markdown.yml — currently warn-only, while a pre-existing backlog is worked down.
- claude.yml and claude-code-review.yml — the
@claudeagent and its reviewer, which are a pair.claude.ymldispatches the reviewer by filename, so keep both names and keep their pins in step.
main is a thin package skeleton: the chapter analysis code, the Stan models, and the dissertation sources live on long-running feature branches.
Check what is present with git ls-files before asserting a layout, rather than reading it from this file or from another branch's tree.
On the branches that carry inst/scripts/, lint-changed-lines reports a large pre-existing backlog.
It is not something a given PR introduced, and clearing it is not in scope for unrelated work.
Do not change DESCRIPTION's Version: in a pull request.
It must match main's exactly, and version-check fails a PR that changes it.
bump-dev-version bumps the dev counter after every merge to main, so a PR never needs to.
This inverted on 2026-08-27.
The older convention required every PR to increment the version, so older branches and older habits point the wrong way.
Apply the no version increment label when a deliberate version change is genuinely needed, such as a release.
This departs from the lab manual deliberately.
Its quality-assurance checklist still lists "Version number has been incremented" as a pre-PR step, which predates bump-dev-version.
Here the automation owns the bump, so following that item fails version-check.
The manual remains authoritative on everything else.
Adding a word to the wrong one silently fails.
-
inst/WORDLIST— read byspelling::spell_check_package(), coveringDESCRIPTION,man/*.Rd, vignette sources, and root Markdown. Sorted by codepoint, so uppercase entries precede lowercase ones. -
_typos.toml, at the repo root — read by crate-ci/typos, covering everything the R spellchecker cannot see. Put a domain abbreviation in[default.extend-words], and prefer fixing a real typo in the source over listing it here.
scripts/andslurm/directories at the repo root — intentional Shiva-only directories listed in.Rbuildignore.- The
serodynamics:::calc_fit_modtriple-colon call inR/run_mod_stan.R— known tolerated until upstream exports it. - Stan and JAGS files — not lintable as R code.
- Tests appropriately skipped on CI with explanations.
- Repository owner: UCD-SERG (Aiemjoy / Morrison labs)
- Primary maintainer (Chapter 2): Kwan Ho Lee (ksjlee@ucdavis.edu)
- Co-advisors: Kristen Aiemjoy, Douglas Ezra Morrison
When making changes:
-
ALWAYS keep all function definitions inside
R/, one per file. -
ALWAYS preserve numerical/statistical logic (priors, parameter names, simulation semantics) unless there is a clear bug.
-
ALWAYS run
lintr::lint_package()and fix every issue in the same commit. Never push a commit that introduces or leaves a lint. -
ALWAYS run
devtools::document()after modifying roxygen2. -
ALWAYS run
devtools::check()anddevtools::test()locally before requesting review. -
NEVER add a
source()call or define a function insidescripts/orvignettes/. -
NEVER commit real Shigella data or files matching
dL_clean_*.rdaor patient data spreadsheets. -
NEVER modify
inst/extdata/*.stanfiles for stylistic reasons — only for clearly documented bug fixes. -
NEVER change
DESCRIPTION'sVersion:in a pull request, becausebump-dev-versionowns it — see "Versioning" above.
Only search for additional information if these instructions are incomplete or incorrect for your specific task.