1. Sign off every commit. git commit -s adds the Signed-off-by line, which certifies
the Developer Certificate of Origin: you wrote the patch,
or have the right to submit it under this project's licence. CI checks every commit in the
range and fails the whole push if one is missing. A missing sign-off cannot be waived; the
history has to be rewritten to add it, which is easier before review than after.
2. No tool-attribution trailers. No Co-Authored-By naming a tool, no session links, no
generator banners. A commit message says what changed and why it is believed correct. Use of a
tool is not a fact about the change.
3. The gate must be green. ./tools/gate.sh runs format, compile with
--warnings-as-errors, tests, credo --strict, an SPDX header check, and a licence-file
check. There is no baseline and none will be added: this tree started clean, so a non-zero
count is a failure rather than a number to hold. Run it before you push; CI runs the same
script. To have git run it for you, ./tools/install-hooks.sh once per clone points
core.hooksPath at the tracked tools/hooks/: pre-commit runs the gate, commit-msg reads
the message through tools/text_terms.sh (the terms in rule 2, and no board ids). It is
opt-in; --uninstall undoes it; git commit --no-verify is git's own bypass and CI still runs
the gate.
4. Rebase, never merge. Keep history linear. Rebase onto main and force-push your branch
rather than merging main into it.
git clone https://github.com/ScriptKittyOS/beam_mcp && cd beam_mcp
asdf install # the Erlang/OTP and Elixir versions .tool-versions pins (any manager that reads it works)
mix deps.get
mix test # the suite
./tools/gate.sh # everything CI runsErlang/OTP 27 or newer and Elixir 1.17 or newer are supported; .tool-versions names the pair
the maintainer develops on. The HTTP transport's optional dependencies are fetched by
mix deps.get in development and test.
The style guide is the Elixir community's: the output of mix format (the project's
.formatter.exs) and the checks of Credo in --strict mode,
which implement the Elixir Style Guide
and add readability, consistency, design and warning checks, including the security-relevant
warnings .credo.exs enables. Contributions are expected to comply; the gate enforces both,
so a change that does not is red. Beyond them, CONVENTIONS.md records this project's own
rules for tests, measurements and records.
Every change that adds or changes behaviour adds tests for it to the automated suite, in
the same pull request. A new function, option, protocol method or refusal is not accepted
without a test that exercises it; a bug fix carries a regression test that was seen failing
before the fix (below). A change to the wire or to the host contract is also measured by
mutation, as CONVENTIONS.md's tier rule says. A pull request without its tests is sent
back, whoever wrote it.
A test that fails only sometimes is a bug, and worth an issue. If mix test fails on a
main you have not changed, and the test passes alone, please open an issue with the test's
name and the seed: tools/flake_hunt.sh 20 runs the suite twenty times, each with a seed of
its own, and prints each red run's failed tests with the command that replays it
(ERL_FLAGS="+S 2" runs it with two schedulers, where a test that waits on time rather than
on its condition loses most often). CI runs the same hunt weekly on the gate's four pairs
(.github/workflows/flake-hunt.yml).
How it is done. Every change reaches main through a pull request, the maintainer's
included, and is merged by rebase only after CI is green on all four OTP/Elixir legs. The
reviewer reads the diff, the commit messages and the CI results, and runs the change locally
when it touches the wire or the host contract. CONVENTIONS.md's tier rule sets the depth: a
contract change (behaviour a consumer can hit) gets two independent review passes and mutation
testing against every pin it adds; a measurement change (CI, gates, pins) gets one pass; prose
gets the gate and a self-review. Automated review passes and the censuses assist; they do not
replace the reviewer's judgement.
What must be checked.
- The change does what its message says, and nothing else (one change per commit).
- New or changed behaviour has tests; a fix has a test that was seen failing first.
- Wire-facing input stays bounded and validated: a new path through
BeamMCP.JSON, the transports orBeamMCP.Serverkeeps the size, nesting, header and schema checks, and adds no atom, evaluation, file or network access driven by a client (docs/threat-model.md,docs/assurance-case.md). - Nothing crosses the boundary
docs/will-not-implement.mddraws; the censuses undertest/beam_mcp/boundary/still pass for the right reason. - The public surface: if
docs/public-api.txtmoves, the CHANGELOG names the exact entry and the break rules indocs/api-stability.mdare followed. - Pages that describe the changed behaviour (README, threat model, assurance case) change in the same pull request.
- Sign-off on every commit, no attribution trailers, no secret in the diff.
What is acceptable. All of the above hold, CI is green, and the reviewer can say why the
change is correct. Anything short of that is sent back with the reason. Who reviews: the
maintainer reviews every pull request; the continuity holders named in docs/succession.md
may review as well. A review by a person other than the author on at least half of all changes
is the project's aim; the pull requests show who reviewed each one.
- A red before a fix. Show the failure first, in the commit message, with its output. A test that has never been seen failing is not evidence that it works. Where a red is not available (the code already exists and passes), demonstrate coverage by mutation instead: break the property in a throwaway copy and show the test catches it.
- Counts quoted from command output, never typed. Test counts, exit codes, file counts.
- SPDX headers on every
.ex,.exs,.shand.yml. The gate checks it, and CI runs the REUSE Specification's own lint over the whole tree (pipx run reuse==6.2.0 lintlocally, the version CI pins). - Scope discipline. One commit does one thing and says so. If a fix uncovers a second defect, file it rather than folding it in.
CONVENTIONS.md records why these exist, with the specific failures that produced them.
Participation is under the Code of Conduct (the Contributor Covenant, version 2.1).
Not here. See SECURITY.md.