The 2026 SOP refresh: formatters, branch-based development, and code review
Two goals drive all the code we write:
The SOP distinguishes two tiers for guidelines:
Today’s session will focus on universal requirements, particularly the new ones.
All code at emLab must:
main.A formatter handles all the spacing, indentation, and line-break decisions automatically. Set it up once and forget about it.
Important
Formatters are required for all new code development.
Can be configured to “run on save” - so there’s nothing to remember.
Air is the required R formatter (built by Posit, enforces Tidyverse style).
Cmd+Shift+X) and install “Air” (by Posit).settings.json:Ruff is the required Python formatter.
Styling is still required if you still use RStudio, where Air is less integrated. Use the styler package:
install.packages("styler"), then Addins → “Style active file” before each commit.All code development happens on a separate branch. We don’t commit directly to
main.
main — abandon the branch and move on.Git history is a sequence of snapshots:
A --- B --- C --- D (main)
A branch is a named pointer that moves forward independently:
A --- B --- C --- D (main)
\
E --- F (my-branch)
main is untouched until you explicitly merge.
When the work is ready, you merge back into main:
A --- B --- C --- D ----------- G (main)
\ /
E --- F --- (my-branch → merged)
main now includes the work; the branch can be deleted.
main?main should always run successfully. It’s the reviewed, stable version of the project.
main; if you hit that error, you need a branch.main — git switch main && git pullgit switch -c add-spatial-aggregationgit push -u origin <branch>main periodically — the longer a branch diverges, the harder it will be to review and merge.Closes #42”).A pull request is how you propose merging your branch into main — and how code review happens.
All changes to main come through a PR.
Push your branch, then open a PR. Fill out:
main.Closes #42”).Not ready for review? Open a Draft PR.
A reviewer looks at both the code and the analytical approach. GitHub gives three options for the reviewer:
In practice, we recommend using Comment + Approve on small, low-risk PRs — reserve Request changes for substantive concerns.
Pull requests
| Timing | What to check | Required? | |
|---|---|---|---|
| Self-review | Ongoing; Before every PR; revisit after receiving PR comments | Accuracy, logic, efficiency | Always |
| Team member peer review | Ongoing; for every PR | Accuracy, logic, efficiency | Whenever there’s more than one researcher on the project |
| GitHub Copilot AI “peer” review | Ongoing; for every PR | Accuracy, logic, efficiency | Optional; use with caution, your mileage may vary |
Reproducibility check
| Timing | What to check | Required? | |
|---|---|---|---|
| External peer reviewer | End of project and before submission; again before publication | A designated reviewer re-runs the full analysis independently and regenerates all outputs | Publications and external-facing deliverables |
If your code is being reviewed:
If you’re reviewing:
The fundamental shift: code review is planned for at the start of a project, not triggered reactively by a journal requirement or an error someone found.
A code review plan answers four questions:
Explicitly discuss code review plan:
map/apply over loops.renv for packages, targets for pipelines.Three new universal requirements:
main.All three exist for the same reason: accurate, reproducible science.
The full Standard Operating Procedures live at:
Collaborative coding at emLab