Contributing¶
Last updated: 2026-09-16
Coast Standards is a set of rules plus the checks that enforce them. You can change either. The bar is the same for both:
- A rule is not done until a check holds it.
- A check is not done until a test proves what it refuses and what it lets through.
License¶
Coast Standards is source-available under LICENSE.md. When you submit a change, you license it to the project's owner for inclusion (section 5 of the license). You keep the copyright in what you wrote.
Before you start¶
- Read
rules/00-priority-rules.md. It is short, and it applies to this repository too. - Turn on the repository's git hooks (once per clone). The pre-commit hook runs the verifier and the tests. The pre-push hook refuses a push to
mainthat does not raise the version.
git config core.hooksPath .githooks
- Run the tests once to see the starting state. This takes about two minutes.
python3 -m unittest discover -s enforcement/checks/tests -p 'test_*.py'
Everything is standard-library Python 3. There is nothing to install.
Changing or adding a rule¶
- Every rule ends with a
[…; check: …]tag naming the check that holds it. The verifier (enforcement/checks/verify_rules.py) refuses a rule that names no check, or names a check that nothing runs. The committed baseline of gaps may only go down. - A rule a machine can check gets a scanner signature in
enforcement/checks/rules_signatures.json. Add two test files underenforcement/checks/tests/plants/<platform>/: a.failfile the check must refuse and a.passfile it must accept. - A rule only a person can judge is tagged
check: review. - Rule ids are stable (
DRY-3,L-7,SEC-12). Never renumber. To replace a rule, retire its id and add a new one. - Platform files carry a release stamp. The first line of each file under
rules/platform/names the release in which its text last changed. After editing a platform file, runpython3 tools/build_rules.py: it marks the fileunreleased, and the release step replaces that with the release number. A project only receives a new copy of its rules document when the stamp is newer than its copy's. A test refuses a stale stamp. - Shared sections are edited in one place. A section used by more than one platform lives in
rules/platform/shared/. Edit it there, then runpython3 tools/build_rules.pyto update the platform files. Never paste the same section into two platform files; a test refuses it. - Write plainly. State the rule, then the reason. No marketing, and no summary at the end of a section.
Changing a check¶
- Read the relevant section first.
enforcement/DEVELOPER-GUIDE.mddescribes every mode, flag, file and output format.enforcement/README.mdexplains the design and the reasons behind it. - Keep the output format exactly:
FAIL <check> <path>:<id>: <words>. Hooks, CI and the reference implementation parse it. - Every behaviour change ships with a test in
enforcement/checks/tests/. - Every change updates the pages that describe it, in the same commit. Check at least
README.md,docs/options.md, the other pages indocs/,enforcement/DEVELOPER-GUIDE.md,enforcement/TEMPLATE-PROJECT-CLAUDE.mdandCHANGELOG.md. A test fails when an installer flag, a setting or a layout key is missing fromdocs/options.md. - Write documentation by
skills/write-developer-documentation/SKILL.md.
Pull requests¶
- One change per pull request.
- The commit subject line is under 100 characters and says what changed.
- CI runs the verifier and the tests on Linux and macOS. Both must pass.
- Every documentation page has a
*Last updated: YYYY-MM-DD*line under its title. Update the date when you change the page. - Every merge to
mainraises the version. Runpython3 tools/version.py bump patch|minor|major "<summary>"before you merge; the pre-push hook refuses a push tomainwithout it. - Add a changelog entry under Unreleased in
CHANGELOG.md, grouped under Added, Changed, Fixed or Removed. Write each entry as one line: what changed and the problem it solves. No dates, incident stories, rule numbers or task ids. Full instructions: Every merge raises the version. - The BuilderOS skills that the rules name are not copied here. Send fixes to them to BuildGreatProducts/builder-os.
Reporting a false positive¶
- Open an issue with the "A check stopped me wrongly" template.
- Paste the refusal line and the code it refused.
A false positive is a bug in the scanner signature. The fix adds a .pass test file so the same mistake cannot come back.
The documentation site¶
The site at up-coast.github.io/coast-standards/ is built from the Markdown files in this repository. No page is copied and none has front matter, so each file reads the same on GitHub, on the site, and inside a project that adopted it. mkdocs.yml holds the navigation.
To build it locally:
pip install mkdocs==1.6.1 mkdocs-material==9.7.7
tools/build-docs.sh serve # http://localhost:8000
tools/build-docs.sh # build into site/
- The build runs with
--strict, so a broken link fails it. - The
docsworkflow runs the same build on every pull request and publishes on a push tomain. - When you add a page, add it to the nav in
mkdocs.ymland to the staging list intools/build-docs.sh.