This document defines the process for contributing to M87, with special attention to governance-touching changes.
- Fork the repository
- Create a feature branch
- Make changes
- Run
./scripts/audit.sh - Commit with proper format
- Open a pull request
All commits must follow this format:
<type>: <short description>
<optional body>
<optional footer>
| Type | When to Use |
|---|---|
feat |
New feature |
fix |
Bug fix |
docs |
Documentation only |
test |
Adding or fixing tests |
refactor |
Code change that neither fixes nor adds |
chore |
Build, CI, tooling changes |
[GOVERNANCE] |
Any change touching governance enforcement |
Changes that touch governance enforcement MUST:
- Use
[GOVERNANCE]prefix - Explain which invariant is affected
- Reference the test that verifies the change
- Include proof that tests pass
Example:
[GOVERNANCE] Add cleanup_cost budget multiplier
Affects: Autonomy Budget enforcement (Law #6)
Test: test_runner.py::test_budget_multiplier_applied
Proof: Runner logs show adjusted budget values
This applies budget_multiplier at the enforcement point in runner,
not at mint time in API. Enforcement-time application ensures the
multiplier cannot be bypassed by job tampering.
Any change to:
apps/api/app/main.py(govern_proposal, Phase 3-6)services/runner/app/runner.py(execute_job, verification functions)apps/ui/lib/governance/*.ts(normalization, reconciliation).claude/rules/*.md(Claude Code constraints)docs/PROOF_MAP.mdordocs/ARCHITECTURE.md(governance docs)
- Ensure
./scripts/audit.shpasses - Update documentation if needed
- Request review from one maintainer
- Ensure
./scripts/audit.shpasses - Update
docs/PROOF_MAP.mdif adding new enforcement - Add
INTENT PRESERVATIONcomment if modifying rejection behavior - Request review from two maintainers
- Explicitly acknowledge which Governing Law is affected
Reviewers should verify:
- Tests pass (
./scripts/audit.sh) - Commit message follows format
- No hardcoded credentials or secrets
- No unnecessary dependencies added
- Invariant is preserved or strengthened (never weakened)
- Test covers the new enforcement path
- PROOF_MAP.md updated if needed
- INTENT PRESERVATION comment explains why rejection is correct
- No "helpful defaults" that bypass checks
- No retry-with-relaxation patterns
These patterns will be rejected in code review:
# REJECTED: Swallowing verification errors
except VerificationError:
pass
# REJECTED: Conditional security
if not settings.STRICT_MODE:
skip_verification()
# REJECTED: Trust escalation
if agent.trust_score > 0.9:
auto_approve()
# REJECTED: Retry with relaxation
for attempt in range(3):
try:
execute()
except BudgetExceeded:
budget *= 1.5 # NEVER DO THIS# Run full audit
./scripts/audit.sh
# If touching API code
cd apps/api && pytest tests/ -v
# If touching UI code
cd apps/ui && npm test
# If touching runner code
cd services/runner && pytest tests/ -vAll PRs must pass:
- Unit tests (pytest)
- Integration tests (proof-test.sh)
- Lint checks (py_compile)
When you change enforcement:
- Update
docs/ARCHITECTURE.mdif a Governing Law is affected - Update
docs/PROOF_MAP.mdwith claim → test mapping - Update
README.mdif guarantees change - Add/update INTENT PRESERVATION comments in code
- Open an issue for clarification
- Tag maintainers for governance questions
- Reference this document in PR descriptions
By contributing, you agree that your contributions will be licensed under the Business Source License 1.1 — see LICENSE for details.