Skip to content

PayPal sandbox only. No real money moves.

BuildersBuilders

Contributing

Branch and pull request naming, commit rules, labels, ownership and the checks a change must pass.

Verifiedbacked by a real run or committed evidence

Page last changed 7 Nov 2026 (from the git history)

The authoritative text is CONTRIBUTING.md in the repository. This page restates the rules with the checks that enforce them.

The flow

Start from fresh main

Fetch, then branch from the current origin/main. Work in your own branch or worktree.

Name the branch and the pull request

Branch: <type>/<KEY>-<slug>, for example feat/ENG-04-ledger-model. The key is two to four upper-case letters, a dash and two to four digits. The slug is lower case letters, digits and dashes. The type is one of feat, fix, test, docs, chore, refactor, perf, ci, build.

Title: starts with the same key, then a colon: ENG-04: append-only ledger model. Extra keys may follow the first (ENG-04 ENG-05: ...). The pr-meta workflow runs scripts/check-branch-pr.mjs from the base branch and fails the check on a mismatch.

Write conventional commits

type(scope): subject. Allowed scopes: shared, engine, payments, voice, server, web, e2e, infra, docs, repo. The header is lower case, has no full stop and is at most 72 characters. commitlint.config.cjs enforces this, locally through the husky commit-msg hook and in CI.

Check what you can locally

Run prettier on the files you changed. The pre-commit hook runs Prettier and ESLint on staged files plus the ASCII and banned-word checks; it never runs tests. Heavy checks run in CI (see Run and test).

Open the pull request

Use the template: issue link (Closes #<n>), Summary, How to test, Sandbox verification, Interfaces changed, Tests added and the checklist. Add the labels below if they apply, then follow the checks until they are green.

Labels

LabelWhen
cross-areaThe change touches files owned by more than one area. A maintainer applies it. It bypasses the ownership check
interfaceThe change alters an exported symbol or wire message. The pull request updates etc/<package>.api.md and merges before the code that depends on it

File ownership

The ownership check (scripts/check-ownership.mjs) reads the area from the issue key and compares it with the changed files, using scripts/ownership.map.json.

AreaPaths
ENGpackages/engine/**, docs/specs/engine/**
PAYpackages/payments/**, docs/GATES.md, docs/specs/payments/**
RTpackages/shared/**, packages/server/**, docs/specs/realtime/**
VOI, VOXpackages/voice/**, docs/specs/voice/**
WEBpackages/web/**, docs/specs/web/**
QApackages/e2e/**, infra/**, .github/**, scripts/**, root tooling files, docs/DECISIONS.md, docs/GATES.md, CONTRIBUTING.md

Reviewers come from .github/CODEOWNERS. Exempt from the check: package-lock.json, build info files, dist, declaration files and etc/*.api.md.

Rules that are easy to trip over

  • Money is integer cents.
  • No any, no unused variables, no non-null assertions: the root lint rejects them.
  • Files are plain ASCII. The check-ascii job fails on any other character, in code and in docs.
  • The banned-word check also reads commit messages and pull request text.
  • Never commit a key, token or secret. Use sandbox values only; the secret scanners run on every pull request.
  • Do not force-push a shared branch. If main moved, merge it into your branch (chore(repo): merge main).
  • package-lock.json must stay in sync with the workspaces. After a dependency change, run npm install --package-lock-only and commit the lockfile.

Add things

Scenarios are YAML files in packages/e2e/scenarios/, named S<nn>-<slug>.yaml and validated by packages/e2e/src/dsl/schema.ts. Copy S01-happy-path.yaml, change the id, steps and expectations, keep time and randomness explicit, then run npm run test:scenarios.

Security and conduct

Do not open a public issue for a vulnerability; follow SECURITY.md. Participation is governed by CODE_OF_CONDUCT.md.

Edit on GitHub

Last updated on