Contributing¶
Contributions are welcome. This page collects the conventions and hard constraints that keep MaD consistent across its firmware, app, protocol, and test rig.
Before you push¶
Run the gate(s) for the area you touched (see CI/CD). At minimum:
- App:
npm run verifyinSoftware/Control. - Firmware:
pio check+pio test -e native_test, and buildMaD. The SIL's project files boot that same image off the module's flash (make flash-image), and thep2core/p2isssuites run it too (make p2image). - Protocol: regenerate all consumers and run
./examples/verify.sh. - Anything user-facing:
mkdocs build --strictif you changed docs.
Submodule changes go upstream first¶
Protocol/ProtoEmb and SIL/embsim are git submodules of standalone repos
(protoemb,
embsim). To change code inside them:
commit + push in the library repo (its own CI gates it), then bump the pinned
commit here in a MaD PR. Never open a MaD PR whose gitlink points at a commit
that isn't pushed upstream.
Pull requests¶
main is protected — you can't push to it directly; open a pull request.
CI Gatemust pass. A single required status check aggregates the build, unit, and SIL jobs (see CI/CD); it must be green before a PR can merge.- No approvals are required (0), but a PR is — so even a one-person change goes through the gate rather than a direct push.
- GitHub Copilot code review comments on every PR — covering coding-guideline
adherence, code reuse / anti-duplication, docs freshness, and
design/safety suggestions. It reads the guidelines via
.github/copilot-instructions.mdand path-scoped.github/instructions/*.instructions.md. It never blocks merge — treat it as a senior-reviewer nudge.
Key constraints¶
These are enforced by review (and often by tooling). Breaking them causes subtle, hard-to-debug failures:
- Firmware layering —
APP → DEV → IO → Library → HAL → HW, downward only. Don't call low-level MCU headers above the HAL. (pio checkruns MISRA/CERT.) - Locking discipline — HAL locks are not reentrant; never call another
module's API while holding your own lock (prevents self- and ABBA deadlocks).
Librarystructures are unsynchronised by contract. - Generated code is off-limits — never hand-edit
Generated//generated/directories; change the schema or templates and regenerate. - Keep the app pure —
Software/Control/src/uses only Web Serial + File System Access. Test-only fakes (SIL serial, OPFS) live ine2e/, never insrc/. - Native and P2 — always exercise both the host (
native_*) and the realMaDbuild; pointer sizes and timing differ. - embsim stays generic — no generic embsim crate may depend on MaD-specific
code. MaD specifics live in
models/,p2core/,p2iss/,mad-catalog/,mad-runner/, and theprotocolcrate (Protocol/rust/). - The app is not a safety device — never make the UI halt the machine on link loss or tab close; the machine is the safety authority.
Coding guidelines¶
Detailed, language-specific coding standards — grounded in how the code is actually written and gated — live in Coding guidelines: C/firmware (MISRA + CERT), Rust/SIL, Python (the generator), TypeScript, and the protocol-YAML schema. Contributors (and AI assistants) are expected to follow them.
Conventions¶
- Firmware files are prefixed by layer (
app_,dev_,IO_,lib_); usesrc/template.ch/src/template.cxas the starting layout for new files. - Match the surrounding code — comment density, naming, and idiom.
- Commits follow conventional-commit style (
feat(...),fix(...),refactor(...),test(...),docs(...)).
Documentation¶
This site lives in docs/ and is built with MkDocs Material. To work on it:
If you change the app's UI, regenerate the screenshots so the guides stay current (see Running the app).