Contributing
contributing.RmdThis document is for people making changes to the SPoRC
codebase, where things live and why is covered in Architecture; this page covers the
mechanics of actually getting a change in: environment setup, branching,
testing, and what CI checks before a change lands.
Getting set up
SPoRC is a standard R package built around RTMB. There’s no compiled code
to build (RTMB traces plain R at runtime rather than compiling C++), so
getting started is just:
Branching
Work happens on dev-* branches off main
(e.g. dev-movement, dev-popn-seasons), merged
in when ready. dev-* is not just convention, the GitHub
Actions workflows (R-CMD-check, test-coverage,
pkgdown) are configured to trigger on pushes to branches
matching that pattern, so a differently-named branch won’t get CI
feedback until you open a PR against main.
Making a change
The Architecture doc’s “Extending the model: a checklist” section walks through where a new process, fleet type, or data source touches the pipeline (Setup function → objective section → sim counterpart → post-fit exposure → tests → vignette). Two conventions worth internalizing before you start:
- Naming tells you the role.
Setup_Mod_*builds data/parameters/mapping,Get_*/get_*derives a quantity from already-built state,do_*re-runs or perturbs a fitted model,do_*_mappingbuilds an RTMB parameter map. Match an existing prefix rather than inventing a new one, see the naming conventions table in Architecture. - Extract non-trivial logic out of
model_objective.Rinto a helper. The objective function is already large; sections that do complex computations (population projection, observation models, priors/penalties) call out to aget_*()helper that takes the relevant state as named arguments and returns it, rather than computing inline.
Testing
Tests live in tests/testthat/
(Config/testthat/edition: 3). Run the full suite with:
devtools::test()or a single file while iterating:
testthat::test_file("tests/testthat/test-model_selectivity.R")or a whole group, since test files hold the same prefixes as
R/:
testthat::test_dir("tests/testthat", filter = "model_")filter is a regex matched against the file path, so use
the bare prefix rather than anchoring it with ^.
Most test files are narrowly scoped
(test-model_movement.R,
test-setup_fishery_fdev.R,
test-model_selectivity.R, …), but the
test-regression_*.R files fit a full model end-to-end
against a bundled example dataset and check the resulting
obj$rep values (e.g. SSB, Rec)
against fixed reference vectors. These are the tests most likely to
catch an accidental change in model_objective.R’s numerics,
and they’re also the slowest (each one runs a real optimization) so
expect a full local run of just that subset to take several minutes to
tens of minutes depending on your machine. If you touch anything in
model_objective.R or a helper it calls, run at least one of
these before opening a PR, even if your change looks purely mechanical
(e.g. a refactor that moves code into a helper function without
intending to change any values), a subtle argument-order or indexing
mistake in that kind of change won’t show up any other way.
For a new feature, add a targeted test near it, and check whether the
reference values in the test-regression_*.R tests need
updating (they should only change if your feature is expected to change
model output for the bundled example data, if a “pure refactor” changes
them, that’s a bug in the refactor, not a test that needs updating).
Documentation
Roxygen comments (RoxygenNote: 7.3.3) generate both
man/*.Rd and the pkgdown reference site. After
adding or changing a roxygen block:
devtools::document()Internal helpers (not meant for users to call directly) should have
@keywords internal rather than @export. If you
add a new exported function, add it to the appropriate section of
reference: in _pkgdown.yml too. pkgdown won’t
list a function on the reference index just because it’s exported, it
needs to be in that config.
User-facing vignettes are the lettered .Rmd files in
vignettes/ (a_model_dimensions.Rmd,
b_model_parameters.Rmd, …), grouped under
articles: in _pkgdown.yml. This document and
Architecture are unlettered and live
under the same articles: listing, grouped separately since
they’re about the package’s internals rather than how to use it.