Contributor guide
Set up the toolchain, make a change, and run every gate
By the end you will have the hooks installed, the client toolchain ready, and
one change through the full gate. This is the front door to working on the hub:
AGENTS.md holds the contract, Testing says what each
gate proves, and Documentation is the docs
standard.
Before you start
| Thing | Why |
|---|---|
pre-commit |
make setup installs the git hooks through it |
| A Rust toolchain, 1.97 or newer | the hub compiles from source |
clang and cmake |
the pinned engine compiles C |
| Node | the client unit, stylesheet, and type targets |
| A browser | the Playwright checks drive it |
The okf validator |
make docs/check validates the docs bundle |
Install and run the hub covers the Rust and C toolchains in full, and Documentation installs the validator.
Set up
make setup
make check
make setup installs the git hooks, creates the scratch area, and writes the
local assistant shims. It is idempotent, so re-run it whenever the hooks or the
tooling change.
make check is the full gate: hooks, linter, formatting, the docs bundle, the
client checks, and the tests. Keep its output. A change is done when the gate
passes and you have the captured output to show for it.
You should now see
make setup ends by printing that the hooks are installed, the scratch area is
ready, and the shims are written. make check ends with check: ok.
Development targets
The Makefile is the single automation entrypoint; bare make lists every
target. The ones a contributor reaches for most:
Build, lint, and format:
| Target | What it does |
|---|---|
make build |
builds the debug binary |
make test |
runs the Rust suite, through cargo-nextest when it is installed |
make test/shard N=1 M=3 |
runs one slice of the Rust suite, for CI |
make clippy |
runs the Rust linter with warnings as errors |
make fmt |
applies the formatting fixes |
make fmt/check |
fails if formatting differs from rustfmt output |
make lint |
runs every declarative hook against all files |
make lint/staged |
runs the hooks on the staged files only, for the inner loop |
make lint/engine |
fails unless exactly one engine version is linked |
make docs/check |
validates the docs bundle against OKF v0.2 |
make net/check |
tests the tailnet path in a build without the feature |
make serve/check |
compiles the serve-only build the container uses |
The gates:
| Target | What it does |
|---|---|
make gate/quick |
the fast inner loop: format, lint, and client units |
make gate |
everything the gate runs but the browser checks |
make check |
the full gate, browser checks included |
Client and browser:
| Target | What it does |
|---|---|
make web/units |
Vitest over the pure client functions and the PWA static checks |
make web/styles |
the stylesheet gate, over a css-tree parse |
make web/types |
type-checks the client sources with tsc --noEmit |
make web/e2e |
the Playwright behaviour checks and the axe audit |
make web/crypto |
the artifact encryption round-trip self-test |
make e2e/shard SHARD=1/2 |
runs one shard of the browser checks |
make e2e/baselines |
rewrites the changed screenshot baselines, on the CI runner |
make web/types is not part of make check yet; Testing
says what it has to clear before it can be. make container/config validates the
compose file and make container/build builds the image, both by hand rather
than in the gate. make clean removes the build artefacts, and
make hooks/update moves the pinned hook revisions.
The client toolchain
The PWA is served as vanilla ES modules with no bundler, so there is nothing to
compile and nothing to bundle. The Node tree is development tooling only: the
dependencies are devDependencies in package.json, the lockfile is committed,
node_modules/ is ignored, and the shipped binary and container never read it.
| Concern | Tool | Target |
|---|---|---|
| Pure client logic | Vitest | make web/units |
| PWA build and assets | Vitest reading the files | make web/units |
| Stylesheet rules and tokens | a css-tree AST walk under Vitest |
make web/styles |
| Client types | tsc --noEmit over checkJs |
make web/types |
| Browser behaviour and layout | Playwright Test | make web/e2e |
| Accessibility | @axe-core/playwright under Playwright Test |
make web/e2e |
Testing has the same matrix with what each concern proves and how to write a check.
The workflow
- State the scope in one sentence: the unit of work, the target, and the outcome. Anything outside it is out of scope.
- Work in a dedicated worktree with a conventional branch name (
feat/,fix/,docs/,chore/,refactor/), rebased on the latestmain. - Keep the change small. One logical unit. Fix up or amend into the owning commit rather than stacking fix commits on an active branch.
- Write the tests and update the wiki. A behaviour change that leaves the docs stale is not finished.
- Run
make checkand keep the output. The gate passing, with the captured output to show for it, is what done means.
Conventions
- Commits follow Conventional Commits, summary first, no trailers. Stage
explicit paths, never
git add -A. The commit-message hook enforces this. - Verification is automated.
pre-commitowns file hygiene, commit-message shape, and the editorial and privacy patterns, andmake checkruns the same hooks CI runs. Do not hand-polish what a tool enforces. - Respect the invariants. One engine, wrap AgentFS rather than reimplement
it, the wrapper as the single writer per session file, no automatic expiry, no
chat, and engine-native search.
AGENTS.mdis the authoritative list. - Tests keep their files under the build tree. A throwaway directory goes
under
target/tmp, never the system temp directory, which is often memory and keeps what a killed run leaves behind. - Vendored assets are integrity-checked. Third-party scripts under
web/vendor/must be registered inweb/vendor/MANIFEST.jsonwith their upstream URL, license, banner-derived version, and SHA-256 hash. - Committed files are public-ready. Committed code, tests, documentation, and commit messages never reference internal tracking, task or ticket identifiers, wave or lane names, or scratch area paths.
- Docs are public-ready by default.
docs/is an OKF v0.2 bundle: no internal names, hostnames, absolute paths, tokens, or task identifiers, and no link outside the bundle. Documentation has the page and index rules. - The scratch area is local. Working notes, task breakdowns, and the internal progress log live in the gitignored scratch area and are never committed.
See also
- Testing - the test matrix and the gates
- Documentation - the docs standard
- Maintainer guide - the review gate
- Install and run the hub - the toolchains in full