Contributing¶
How to get involved with the Xregulator project, what to know before changing code, and what's expected of a contribution. Written for anyone who wants to report a bug, suggest a feature, or submit code.
How to engage¶
- Email — joe@xengineering.net for bug reports, feature requests, or questions.
- GitHub — issues and pull requests on the public repo, github.com/markliquid1/Regulator2026-public.
Report unclear behavior even if it may not be a bug — confusing behavior is a documentation defect at minimum.
Before you change code¶
The following disciplines exist because each one has been violated before, with real consequences.
The telemetry three-way sync¶
Live data reaches the dashboard over four server-sent-event channels (see the telemetry pipeline). Each channel's packet is a comma-separated list of numbers, matched by position to a field-name array in the browser. That means any field you add or remove must be changed in three places at once:
- the firmware field-count marker (the sentinel value at the bottom of the channel's index list, e.g.
CSV1_FIELD_COUNTin3_functions.ino), - the packet-building format string (the
snprintfcall for that channel in3_functions.ino— one conversion specifier per field), and - the matching JavaScript field array (
CSV1_FIELDS,CSV2_FIELDS,CSV3_FIELDS, orTS_FIELDSinweb_src/script.js).
If these three drift out of sync, the failure is silent: the format string drops trailing fields, the browser sees a count mismatch, and the entire channel is rejected — not just your new field. Always verify all three together before calling a telemetry change done.
Pick the right plumbing pattern¶
There are three established patterns for wiring a new variable through the system, depending on what it is:
- a fast-changing live value the dashboard should plot in real time — see adding telemetry,
- a user-configurable setting that persists across reboots and echoes back to its form field — see adding a setting,
- a button or control on the dashboard that triggers a firmware action — see adding a dashboard control.
Classify first, then follow the matching recipe. The most common mistake is plumbing a setting through a telemetry channel meant for diagnostics, which sends redundant traffic and breaks the echo-on-change behavior.
Comments move with code¶
When you edit code, edit the comments around it in the same change. A stale comment is worse than none — both humans and AI assistants take comments at face value here. Don't delete existing comments unless the code they describe is gone.
Plain English first in UI copy¶
Any text a user sees — labels, tooltips, console messages, documentation — leads with plain English and puts the technical term in parentheses after, e.g. "current-limited phase (CC phase)". Raw firmware identifiers (cv_I, VoltageKp, etc.) never appear in user-facing copy; use the dashboard label names instead. No emojis, anywhere.
Expectations for a contribution¶
- No formal test suite exists. The bar instead: your change must compile cleanly in the Arduino IDE (board: ESP32-S3 — see Building the Firmware), and you should sanity-test it on a real device or at least exercise the affected dashboard behavior in a browser. Say in the PR what you tested and how.
- Small, focused pull requests are strongly preferred. One concern per PR. A 50-line change that does one thing reviewably beats a 500-line change that does three.
- Match the house style. Flat layout, descriptive global names, minimal abstraction. Don't introduce class hierarchies, clever indirection, or new dependencies to "clean things up" — the monolithic style is a deliberate choice (see Start Here).
- Safety-relevant code gets extra scrutiny. Anything touching the field control loop, the protections, or shutdown paths (charging control, safeties and protections) will be reviewed conservatively and may need bench-test evidence. This device drives real charging hardware on real boats.
License¶
The project is licensed under the GNU General Public License v3 (GPLv3). By submitting a contribution you agree it is provided under the same license. Don't submit code you don't have the right to license this way.