How to Contribute
This guide is the shortest path from a clean checkout to a change that satisfies the repository's quality gates. Read AGENTS.md first: it defines the language, threading, IR, diagnostic, and delivery invariants.
1. Install the toolchains
Rust 1.98.0 is selected automatically by rust-toolchain.toml. Documentation and extension work uses Node.js 24 and pnpm 10.19.0. On Debian or Ubuntu, install the native desktop dependencies:
sudo apt-get install libgtk-4-dev libadwaita-1-dev libwebkitgtk-6.0-dev \
libssl-dev libdbus-1-dev libsecret-1-devInstall the two independent Node workspaces when you touch them:
pnpm --dir manual install --frozen-lockfile
pnpm --dir tooling install --frozen-lockfile2. Orient the change
Connect Crusty
Crusty runs locally as rust-repo-intelligence. Install it from a Crusty checkout with cargo install --path . --locked, and make that executable available on the MCP client's PATH.
The repository's .mcp.json registers Crusty for clients that support this configuration file. Launch the client from the AIVI repository root: --workspace . selects this checkout. For clients with their own MCP configuration, use the same command and pass the absolute AIVI checkout path after --workspace. An existing host-level Crusty connection can be reused when it selects this repository; avoid registering it twice. Restart the connection after changing its configuration.
Verify the checked-in configuration with Node.js 24, without installing Node dependencies:
node tooling/check-crusty-mcp.mjsThe check starts the configured server, negotiates MCP, verifies the workflow tools, calls repo.consult, and checks that the returned repository is this checkout. The separate Aivi entry runs this checkout's compiler through Cargo for live application introspection. Build it with cargo build --bin aivi before connecting so the client's startup timeout does not include a first build. It requires the desktop dependencies listed above.
Crusty stores local state under .rust-repo-intelligence/, which Git ignores. Back up the whole directory with Crusty stopped: both SQLite databases contain project records as well as derived data. Keep this directory when cleaning build artifacts. A fresh clone does not include another checkout's ledger.
Prepare and validate
The specification and implementation are authoritative for language behavior. Crusty is the sole durable project ledger:
- call
repo.consultwith the full task intent and inspect the returned decisions, steering, problems, constraints, and authorized work - check
index.status; useindex.refreshand polltask.getwhen a fresh published index is needed;repo.searchwithmode: "exact"reads live source without a refresh - call
change.preparewith the intended files, polltask.get, and retain itscontext_id - identify semantic, ownership, threading, stack-safety, IR, and diagnostic invariants, then implement at the owning compiler/runtime/tooling layer
- call
change.validatewith the context ID and polltask.get; in a dirty worktree, supply the task's focusedgit_diffso unrelated edits do not become this change's evidence - inspect
validation.queue, record applicable obligation outcomes withvalidation.record, and attach actual command results to the authorized work item before completing it
Use audit.start for a persisted architecture audit and audit.get to retrieve its report. Check inferred findings against callers and tests before acting on them. Use task.list and change.get to recover interrupted preparation or validation.
Do not create a second Markdown backlog or architecture log. Put discoverable implementation facts in code, the specification, or the manual; use Crusty for durable project memory.
3. Run focused checks while iterating
cargo fmt --all -- --check
cargo check -p <affected-crate> --all-targets --all-features
cargo clippy -p <affected-crate> --all-targets --all-features --no-deps -- -D warnings
cargo test -p <affected-crate> --all-featuresUse the artifact dependency graph in AGENTS.md. A syntax change may also require grammar, semantic-token, completion, snippet, fixture, and manual updates. A runtime or GTK change requires the corresponding stress/integration coverage and may affect MCP introspection.
4. Check documentation
Every fenced aivi block is checked documentation and must parse, resolve, and type-check as written. The gate uses aivi manual-snippets --preserve-format so canonical formatting cannot replace the . and ! forms an example is teaching. This gate does not execute effects or verify claimed output:
./tooling/check-manual-aivi-snippets.shOptional canonical formatting is available separately. Review its diff carefully: the current formatter can expand unary and projected-subject shorthand into explicit parameter forms. Keep teaching examples in the form their prose describes, then rerun the gate:
./tooling/check-manual-aivi-snippets.sh --write
./tooling/check-manual-aivi-snippets.shCheck page targets, heading anchors, navigation coverage, and code-fence languages, then build the VitePress site:
pnpm --dir manual test
pnpm --dir manual check
pnpm --dir manual buildWith a built aivi binary, pnpm --dir manual test also executes focused example regressions and checks documented execution limits. Browser regressions are opt-in: start pnpm --dir manual dev, then run AIVI_MANUAL_BROWSER_MODULE=playwright node --test manual/scripts/table-layout.test.mjs using an installed Playwright module (or its absolute module path). These cover mobile and desktop tables and labels after navigation.
Use node manual/scripts/check-docs.mjs --external to check HTTP reachability of outbound links. Access errors require manual review; external heading fragments are not checked. The checker covers maintained project Markdown (manual, specifications, crate READMEs, contribution/agent instructions, and the editor README), not installed skill packages or generated dependencies. It does not prove prose claims or exercise a graphical UI.
Use text for diagrams/output and sh for shell commands. Incomplete or multi-file AIVI examples can use aivi-fragment: it shares the AIVI highlighter but is explicitly outside the standalone snippet gate. Explain the required context beside each fragment; do not relabel a failing complete example to bypass checking. Empty fences are rejected.
Keep tutorials task-led, how-to guides goal-led, reference pages exact, and explanation pages conceptual. Mark unimplemented behavior plainly; do not present roadmap ideas as shipped features.
5. Check the VS Code extension
pnpm --dir tooling -F vscode-aivi lint
pnpm --dir tooling -F vscode-aivi test
pnpm --dir tooling -F vscode-aivi build
pnpm --dir tooling -F vscode-aivi packageThe integration suite builds the real aivi binary and performs an LSP stdio handshake. The package command also inspects the VSIX allowlist.
6. Check dependency policy
cargo deny check
cargo machete
pnpm --dir manual audit --audit-level high
pnpm --dir tooling audit --audit-level highExplain every new crate in terms of invariants, runtime and compile-time cost, binary size, and maintenance risk. Keep Cranelift and GTK-family versions aligned.
7. Run the full gate before handoff
cargo check --workspace --all-targets --all-features
cargo clippy --workspace --all-targets --all-features --no-deps -- -D warnings
cargo test --workspace --all-features -- --test-threads=1
cargo build --workspace --release --all-featuresParser and decoder fuzz targets also receive bounded smoke runs in CI. For a local smoke run:
cd fuzz
cargo +nightly fuzz run parser_lossless -- -runs=512 -max_total_time=30
cargo +nightly fuzz run decoder_paths -- -runs=512 -max_total_time=30For performance changes, follow Benchmarking and retain reproducible before/after evidence.