Thanks for getting involved!
The below is written for people. AGENTS has guidelines for robots, which you may also find useful.
We support MacOS, Linux, and Windows Subsystem for Linux (WSL).
For many of the packages here, JavaScript development tools suffice:
But to ensure contributions are compatible with all packages, you will also need:
- Golang (version 1.17 or higher)
- a C compiler and make
- On linux,
apt install build-essentialsor the like - On MacOS,
xcode-select --installor similar - On WSL, use
nmakeinstead ofmake
- On linux,
To check that everything is working before you start, or to thoroughly check a contribution, run:
yarn # short for: yarn install
yarn build
yarn test
yarn lintA standard Visual Studio Code configuration can be initialized or updated by
running scripts/configure-vscode.sh.
See also notes on Coding style, including unit testing etc.
Repository scope boundaries:
scripts/: executable entrypoints onlysrc/: production/runtime library code and production-safe helpers that are part of the package library surfacetools/: supported cross-package support utilities (test harnesses, mocks, fixtures, typed helper interfaces)test/: local tests only; not imported by other packages
Choosing between src/ and tools/:
- Put code in
src/when it is production-safe and should be treated as part of the package runtime/library API, even if tests also use it. - Put code in
tools/when its main purpose is to help another package test, integrate with, or simulate this package, even if it is intentionally shared and supported. - Short rule: if consumers import it to exercise or simulate package behavior, prefer
tools/; if consumers import it as part of real runtime behavior, prefersrc/. - If another package imports it, it must not live in
test/. - Example:
setupOrchestrationTestbelongs intools/because it is a reusable integration harness. - Example:
makeTestAddressbelongs intools/if it is only deterministic fake-address generation for tests; if it becomes a general runtime-safe address utility, move it tosrc/.
Direction rules:
src/**must not import**/tools/**(except temporary allowlisted legacy imports during migration)tools/**may importsrc/**, but not vice versa- Non-test files must not import
**/test/**from local or other packages
Publishing rules:
tools/may be published or deep-imported as needed within the monorepo.- CI does not enforce
tools/manifest or export policy. tools/is not part of the semver contract of the package.
The agreement so far is for every change to have a conventional commit message and for every commit following the leftmost parent from main/master to pass tests in CI.
* Must pass
* Must pass
* Merge commit must pass
|\
| * Fixed the broken code
| * Adopted some broken code from somewhere
|/
* Must pass
* Must pass
We also have agreement, once code review has begun, that we should as often as practical append commits with follow-up changes so subsequent reviews can be incremental, but that these follow-up commits should not survive to land on main/master. This does not preclude rebases, which are necessary to confirm that the PR continues to pass tests as the main/master branch moves under it.
We favor "Squash and merge" (which requires the PR title to be a conventional commit) since it requires the least careful attention, especially when there are appended follow-up changes, but it's not the only tool in the toolbox.
For example, we preserved the narrative of the xsnap introduction as a
sequence of commits (1. Moddable contributions, 2. our C changes, 3. our JS
wrapper) with a merge commit for the PR ("Create a merge commit"). Step 1
wasn't buildable and step 2 had no tests, but the merge commit passes CI and
all the others non-working commits are not reachable by a left-hand-rule
traversal of the parents, so git bisect will still work if we need it.
We've also squashed follow-up commits manually (through an interactive rebase) after a PR had been approved and tests were passing, then landed the stack with "Rebase and merge" or "Create merge commit".
For details on authoring, merging, and reviewing PRs, see Pull Requests Guidelines.
Some tests take time to complete and will not run by default on every PR push.
However once a PR is ready for review and flagged for merging through one of
the automerge labels, these integrations tests will run and be required
before the PR can land.
If you believe your PR may impact the result of the integration tests, you can
force them to run unconditionally by using the label force:integration. If
you know your PR has no impact on integration tests, you can use the label
bypass:integration to prevent them from running at all.
If a commit was merged without going through the merge queue (automerge
label), or if the integration tests were bypassed in the PR, the tests will
run on the merge commit instead. While the PR has landed at that point, it is
still the responsibility of the PR author to fix any breakage.