This file sets out what a pull request must look like, how licensing and credit work, and which design decisions are settled. Pull requests that miss the requirements under Pull requests are closed without review.
Issues track defects and features in this repository. Raise issues about a fork's own code on that fork. Search the existing issues before opening one.
A bug report needs the command or steps you ran, what you expected, what happened, and the Julia, R and browser versions involved.
To change an architectural decision, open an issue describing the change before writing any code.
Each requirement is checked before the code is read.
-
Branch from the current
main. The merge base of your branch andmainmust be the tip ofmain. Check before pushing:gh api repos/JoshuaJewell/MetaManifold-WebUI/compare/main...<head-sha> \ --jq '{behind_by, merge_base: .merge_base_commit.sha}'behind_bymust be0. Rebase when it is not. -
No merge commits from
mainand no automated conflict-resolution commits. A branch that cannot be re-applied cleanly on top ofmainis not ready. -
One logical change per PR.
-
CI must run and pass. A PR with no reported checks is not reviewed. The required SonarCloud Code Analysis check is a third-party cloud service that nothing in this repository configures, and it fails on a single bug — at any severity — in the changed lines. It has no local equivalent, so run
bash scripts/lint-sonar-reliability.shbefore pushing a frontend change and read docs/sonar-quality-gate.md. Do not silence it by swapping asort()forlocaleCompare; the guard explains why that changes behaviour. -
Write the description: what the change does, the issues it closes, how to run its tests, what it leaves out, and the Julia, R and bun versions you tested with.
-
No generated or vendored files: build output,
node_modules, downloaded tool archives, or lockfile changes the work does not need. When a lockfile change is needed, the description says why. -
Once review has started, add commits, and rebase only when asked to. Squashing happens on merge.
The two branch rules above are checked, not merely stated:
scripts/maintenance/check-pr-freshness.sh runs on every pull request through
.github/workflows/pr-freshness.yml and reports how far behind the branch is,
or which merge commit breaks rule 2. Run it yourself before pushing:
git fetch origin
bash scripts/maintenance/check-pr-freshness.sh --base origin/main --head HEAD
What happens to a branch once it is no longer needed:
- Merged into
main— delete it. The commits are inmain; a kept branch is a second answer to the same question. - Closed unmerged — the pull request keeps the head reachable, so the branch
is deleted and the content is not lost:
git fetch origin pull/<n>/head. archive/— a deliberate snapshot that is not proposed for merging. It carries no pull request; opening one asksmainto become older.upstream/*— the upstream-candidate lane declared by the repository deed (:upstream-candidates). These are proposed to the upstream remote and squash-merged there, not here; the triage script reports them but does not count them as drift.governance-badges— not a working branch. ThePublish badgesjob force-pushes shields.io endpoint JSON to it on every push tomain, andREADME.mdreads it throughimg.shields.io/endpoint. Never delete it.
Drifted and superseded branches are measured weekly by
.github/workflows/branch-hygiene.yml, which updates one rolling issue; the
classes it reports, what each one means and how to recover closed content are in
docs/maintenance/repository-hygiene.md.
Source code is licensed under the AGPL-3.0 (LICENSE). README.md is licensed
under CC BY-SA 4.0, as its Licence section states. A contribution is offered
under the same terms, with one option: code you write yourself may be licensed
under MPL-2.0. Mark each such file with an SPDX identifier and leave out the
"Incompatible With Secondary Licenses" notice, since that notice prevents
combining the file with AGPL code. Checking that your licence choice combines
correctly is your responsibility. Documentation you write is CC BY-SA 4.0.
In a contribution PR:
- leave
LICENSE,CITATION.cffand the licence and acknowledgement sections ofREADME.mdunchanged, and open an issue if one of them looks wrong; - add no
NOTICEfile and noLICENSES/directory, and do not restate this project's licensing in your own files; - keep existing file headers exactly as they are, and add your copyright line only to files you wrote;
- put third-party attributions, such as the DADA2 tutorial used under CC BY 4.0,
in the acknowledgements section of
README.md.
The maintainer keeps CITATION.cff. Being added to its authors is an
authorship decision made by the maintainer, and owning copyright in a
contributed file does not confer it. To be considered for
authorship, say so in the PR description. Your copyright in your contributions is
unaffected by whether you are listed. Credit short of authorship goes in the
acknowledgements section of README.md.
A pull request does not reopen these. An issue can discuss them.
- HTTP layer: Oxygen.jl, pinned in
Manifest.toml, with the server insrc/server/. Genie, Stipple and other Julia web frameworks are out of scope, as is any second Julia web environment. - Frontend: React 18 and TypeScript, built by Vite and managed with bun, in
frontend/. There is one UI stack. - Statistics: R through RCall. Every R package used is pinned in
renv.lock. When a method needs a package missing from the lockfile, the code raises a clear error. - Storage: DuckDB, through
src/core/duckdb_store.jl.
- Every number shown to a user is computed from their data. Placeholder and mock values have no place in an analysis path.
- When a method cannot run (a missing package, invalid input, a model that does not converge), raise an explicit error. Substituting a cheaper method, or returning an empty result that reads as a negative finding, is a defect.
- Tests compare computed values with known references.
config/defaults/tool_versions.ymlpins Julia, R, bun and the external tools, andinstall.jland CI both install from it. The Julia version is repeated in the CI workflow. Change a pin by editing that file, and expect the change to be discussed.- R packages are pinned in
renv.lock. - CI job names carry no version numbers, so that a pin change leaves required status checks intact.
Run the tests as CI does:
julia --project=. -t 2 test/runtests.jl --integration --server
cd frontend && bun run test
The same rules apply, and a named person answers for every line of the diff.
Ask in an issue, or comment on an existing one.