docs/agents/rust_engine_steering.md
Rust Engine Steering (WaveNav)
Purpose: project-specific Rust rules for contributors and coding agents working on the WaveNav engine (engine-wasm/engine).
This file is intentionally prescriptive. When there is a conflict between “clever” and “predictable”, choose predictable.
0. Duplication Discipline (read first)
Follow the canonical duplication policy in docs/agents/AGENT_STANDARDS.md (“Duplication
Policy”). Tier 1 (same file/module) applies to nearly everything in this crate and is always in
scope, no matter how small the requested change is.
In this crate, watch especially for: tree/node lookups repeated across near-identical accessor functions, snapshot/rollback or other paired setup-teardown logic, wire-format encode/decode helpers, and thin wrapper functions that differ only in what they delegate to.
1. Scope
Applies to:
engine-wasm/engine/**- Rust-facing parts of
engine-wasm/pkggeneration flow - Rust-related CI and quality gates
Does not apply to:
- Tauri/TypeScript host logic (except contract alignment concerns)
2. Canonical External Standards
Use these as normative references before introducing custom patterns:
- Rust Reference (
doc.rust-lang.org/reference/) - Rust API Guidelines checklist (
rust-lang.github.io/api-guidelines/checklist.html) - Rust Style Guide + style editions (
doc.rust-lang.org/style-guide/) - Clippy usage and lint groups (
doc.rust-lang.org/clippy/usage.html) - Cargo Book (commands, workspaces, resolver, profiles)
- Rustdoc Book (docs tests and lint behavior)
- Rust Book chapter on panic vs Result (
ch09-03)
Project rule: if an internal convention conflicts with these references, prefer the official Rust guidance unless it breaks explicit repository architecture constraints.
3. Language and Toolchain Policy
- Edition:
- Keep crate edition explicit in
Cargo.toml. - Do not bump edition in incidental PRs.
- Toolchain:
- CI uses stable Rust.
- Prefer
cargosubcommands over ad-hoc scripts.
- Formatting:
- Use
cargo fmt. - CI gate is
cargo fmt --check. - Avoid custom rustfmt style overrides unless there is a concrete readability or diff-stability reason.
- Linting:
- Use
cargo clippyfor advisories, but avoid enabling broad deny-all lint policies without team agreement. - If a lint is intentionally not followed, use narrow
#[allow(...)]at the smallest scope with a short rationale comment.
4. Architecture Rules for This Repo
- Rust engine owns:
- WML parse/runtime/layout/focus/navigation semantics.
- Rust engine does not own:
- Network access
- WSP/WBXML decode
- Transport retries/session protocols
- WASM boundary:
- Export only stable, host-oriented methods via
#[wasm_bindgen]. - Keep rich internal logic in non-exported helpers returning Rust-native types (
Result<T, String>or typed errors). - Convert to
JsValueat boundary edges only.
- Public contract alignment:
- Any boundary behavior change must update:
engine-wasm/contracts/wml-engine.ts- related docs under
docs/wml-engine/ - Before hand-writing a parser/encoder/decoder for a format this crate (or the Rust ecosystem)
already has a supported implementation for, use that instead of a parallel one — see
docs/agents/AGENT_STANDARDS.md(“Codegen & Supported-Tooling Policy”) andM1-18for why.
5. API Design Rules
Follow Rust API Guidelines directly for naming, traits, docs, predictability:
- Naming:
- Types/traits:
UpperCamelCase - functions/methods/modules:
snake_case - constants/statics:
SCREAMING_SNAKE_CASE
- Method naming:
- Use idiomatic names (
new,from_*,as_*,to_*,into_*) consistently. - Do not invent one-off naming patterns for conversions.
- Predictability:
- Prefer methods when there is a clear receiver.
- Keep word order consistent across related methods/types.
- Trait derivations:
- Derive common traits where semantically correct (
Debug,Clone,PartialEq,Eq, etc.). - Avoid deriving traits that can mislead semantics (example:
Copyfor large or stateful types).
- Type exposure:
- Prefer private fields + constructor/helper methods over broad public mutable structs, unless the struct is intentionally a plain data model.
6. Error Handling Policy
- Default:
- Return
Resultfor recoverable failures.
- Panic usage:
panic!is acceptable for impossible internal invariants and test scaffolding.- Avoid panic paths in normal runtime/host input flows.
- WASM edge:
- Internal functions should return Rust errors.
- Map to
JsValueonly in exported API methods.
- Error messages:
- Keep messages stable and concise for integration tests.
- Prefer deterministic text to aid snapshot/contract checks.
7. State and Mutability
-
Keep runtime state transitions explicit.
-
For nav/focus/history:
- Update one concern at a time.
- Preserve deterministic ordering.
- Write tests for state before and after each transition.
- Avoid hidden side effects:
- Do not mutate unrelated state in parse/layout functions.
8. WASM-Specific Guidance
-
Minimize
wasm_bindgensurface area. -
Keep data crossing boundary simple and serializable.
-
Avoid passing complex internal structs directly to JS when a stable view model is sufficient.
-
Keep host compatibility:
- Do not break existing exported method names/signatures in incidental refactors.
- If breaking, do it intentionally with contract and docs updates in the same change.
9. Testing and TDD Rules
- Mandatory workflow:
- Red (failing test) -> Green (minimal fix) -> Refactor.
- Minimum tests for behavior changes:
- Unit tests for parser/runtime helper logic.
- Integration-style tests for key-sequence and state transitions.
- Required validation commands for Rust-only PRs:
cargo fmt --checkcargo test
- Preferred test qualities:
- Deterministic assertions on state (
active_card_idx, focus index, nav stack behavior). - Avoid brittle assertions on incidental formatting unless snapshot intent is explicit.
- Documentation tests:
- Add doctests for public APIs where useful.
- Keep examples runnable when possible.
10. Performance and Allocation Guidance
-
Optimize for correctness first, but avoid obvious unnecessary allocations in hot paths (layout, key handling).
-
Do not introduce complex caching until there is measured need.
-
When optimizing:
- Benchmark or at least compare before/after behavior and complexity.
- Keep readability unless perf gain is meaningful.
11. Unsafe and FFI Policy
-
unsafeis disallowed by default in this crate. -
If
unsafebecomes necessary:
- Isolate to minimal module/function.
- Document invariants and why safe alternatives are insufficient.
- Add targeted tests for boundary assumptions.
- No direct FFI expansion without explicit design review.
12. CI/Quality Gates (Rust Engine)
Current required local gates:
cargo fmt --checkcargo test
CI also enforces engine coverage through cargo llvm-cov with the current thresholds:
- 90% line coverage
- 85% function coverage
Optional/disabled gate (enable intentionally later):
cargo clippy --all-targets --all-features -- -D warnings
Rustdoc lint escalation remains optional for later public-crate hardening.
13. PR Checklist (Rust Changes)
Before merge, verify:
- Behavior change is covered by tests (preferably added first).
- No wasm boundary signature drift without contract/doc updates.
cargo fmt --checkpasses.cargo testpasses.- Coverage remains above the current CI thresholds when behavior changes.
- Relevant
docs/wml-engine/*updated when semantics changed. - No generated artifacts committed unless intentionally required.
14. Common Anti-Patterns to Avoid
- Parsing shortcuts that accept invalid deck roots silently.
- Swallowing navigation errors at internal layers.
- Panicking on user-provided deck content.
- Coupling parser/runtime internals directly to JS error handling.
- Expanding scope into transport/network behavior from Rust engine code.
15. Repo-Specific Command Quick Reference
From repo root:
cd engine-wasm/engine
cargo fmt --check
cargo test
wasm-pack build --target web --out-dir ../pkg
Coverage gate (from repo root):
make coverage-rust-engine
Host sample sanity (requires built pkg):
pnpm --dir engine-wasm/host-sample run build
16. Source References
- Rust Reference: https://doc.rust-lang.org/reference/
- Rust API Guidelines: https://rust-lang.github.io/api-guidelines/
- API Checklist: https://rust-lang.github.io/api-guidelines/checklist.html
- Naming guidelines: https://rust-lang.github.io/api-guidelines/naming.html
- Rust Style Guide: https://doc.rust-lang.org/style-guide/
- Style editions: https://doc.rust-lang.org/stable/style-guide/editions.html
- Clippy usage: https://doc.rust-lang.org/stable/clippy/usage.html
- Cargo test: https://doc.rust-lang.org/cargo/commands/cargo-test.html
- Cargo resolver/workspaces: https://doc.rust-lang.org/nightly/cargo/reference/resolver.html
- Rustdoc doctests: https://doc.rust-lang.org/rustdoc/write-documentation/documentation-tests.html
- Rustdoc lints: https://doc.rust-lang.org/rustdoc/lints.html
- Panic vs Result (Rust Book): https://doc.rust-lang.org/book/ch09-03-to-panic-or-not-to-panic.html