A change lands only when everything below passes. CI runs it on every pull request and every push to main (.github/workflows/ci.yml); run it locally first. README.md says which commands need more than the Rust toolchain.
Formatting and lints, both clippy configurations:
cargo fmt --all --check
cargo clippy --workspace --all-targets -- -D warnings
cargo clippy --workspace --all-targets --features basal-module/rig-kill-hook -- -D warningsTests, with and without the rig kill hook. Portable production-mode tests run on both Linux architectures; their hook-enabled pass runs on x86_64 Linux only. Worker packages run in production mode on every Linux, macOS and Windows image. The hook-enabled worker pass runs on macOS (where the rig uses the hook) and x86_64 Linux (for Linux coverage); hook-enabled clippy still runs on all three platforms in the checks job (x86_64 Linux, Linux aarch64 and macOS):
cargo test --locked -p basal-proto -p basal-core -p basal-host
cargo test --locked -p basal-proto -p basal-core -p basal-host --features basal-host/rig-kill-hook
cargo test --locked -p basal-worker -p basal-module -p basal-testkit -p basal-rig
cargo test --locked -p basal-worker -p basal-module -p basal-testkit -p basal-rig --features basal-module/rig-kill-hookCI also builds every target at the declared minimum Rust version:
cargo +1.89.0 check --workspace --all-targets --locked
cargo +1.89.0 check --workspace --all-targets --locked --features basal-module/rig-kill-hookFormatting and the script checks run once in a build-cache-free lint job:
shellcheck -x script/*.sh
/bin/sh -n script/stage.sh
python3 script/check-path-deps.py
python3 script/check-ckdev-names.py
python3 script/check-local-paths.py
python3 -m unittest script.tests
python3 -m unittest discover -s .github/workflows -p 'test_*.py'The mutation catalogue checks, with the pinned runner installed as docs/mutations.md describes:
ckdev-mutate check
python3 .github/workflows/check_mutation_coverage.pyckdev-mutate check validates every row's anchors and test names, and check_mutation_coverage.py enforces that every row declares exactly one replay platform. The latter's schema check and Python tests run in lint; native anchor/test-name checks stay with the build jobs. On a pull request CI then replays the rows the diff touches, with ckdev-mutate run --diff origin/main; Windows application/restoration witnesses (indexed source diffs and exact named-test failures captured by script/witness-mutations.py) are restricted to the selected Windows rows. On a push to main it replays the whole catalogue in shards (eight Linux, five macOS, two Windows), uploads full Windows witness evidence across both shards, and check_mutation_coverage.py --reports requires exactly one successful replay of every row across all shards. Each Windows image, windows-latest and windows-2022, runs two parallel package groups: launcher + worker + host (including the remaining workspace packages), and module + core + testkit + rig. The workspace pass includes all host tests once; launcher and worker suites retain both production and deviations modes.
- Author commits with your GitHub no-reply address (
<id>+<user>@users.noreply.github.com), not a personal or work address. - Keep local paths out of tracked files.
script/check-local-paths.pyrefuses absolute user-home paths; also leave out machine names and other paths that exist only on your machine. - Don't commit raw logs or generated machine output. Mutation reports stay under the git-ignored
target/mutations/, and CI uploads its own reports as artifacts. Measurements that back a performance claim belong inevidence/, with the command that produced them. - Commit a safety guard together with the source it guards and its catalogue row.
| Crate | Owns |
|---|---|
basal-proto |
The parent–worker IPC protocol. A change that isn't additive needs the stop-the-world update (docs/deploy.md). |
basal-worker |
ck-basal-worker: the QuickJS engine and its self-confinement on each operating system (docs/sandbox.md). |
basal-launch |
Windows process creation: the LPAC worker launch, job-owned child processes and the shared spawn lock. |
basal-core |
The SQLite store and schema, admission, the run state machine, the journal and mailbox, manifests and authorization, the scheduler and the activation driver. |
basal-host |
The Host boundary for flow calls, the built-ins, the adapters to the fleet's modules, and the deterministic mock. |
basal-module |
ck-basal: the subc manifest and serving, the codemode tool-provider role, the worker pool, the flow ops, dry runs and consent cards. |
basal-testkit |
Test parents, crash and cut harnesses, and benchmarks. |
basal-rig |
Test support for the ckdev-flows rig only; never deployed. |
Test doubles and test-only helpers stay behind cfg(test) or the owning crate's test-support feature (docs/testing.md). Scripts live in script/, with their offline tests in script/tests/. Checked-in flows live in flows/ and templates in templates/.
Every safety guard has a mutation proof: a source edit that the named test must catch. The catalogue is the mutations.d/*.toml files, one per crate or area; add a row to the file for the area of the source it edits. Every row declares exactly one platform in platforms (linux, macos or windows), the one CI host that replays it, and row ids are unique across all files. Record a row with ckdev-mutate prove, which writes it only when the mutant is caught. docs/mutations.md gives the file naming, the platform rules, anchor scopes, run sets and the prove command.