# Agent Guidelines for framepace
## Rust API Guidelines
Follow the [Rust API Guidelines](https://rust-lang.github.io/api-guidelines/checklist.html).
Key rules enforced by CI:
- No trait bounds on struct definitions (`C-STRUCT-BOUNDS`): bounds belong on
`impl` blocks only. `FrameTimer<N, T>` stores `PhantomData<T>`; the `T:
TimeSource` bound appears only on impl blocks that actually call `T::now_us()`.
- `#[non_exhaustive]` on public data structs (`FrameStats`, `StdTime`) so
adding fields is non-breaking.
- `#[must_use]` on all methods returning a meaningful value. The `PhaseGuard`
struct itself is `#[must_use]` because dropping it immediately is almost
always a bug.
- Dual-licensed `MIT OR Apache-2.0`.
- Keep `CHANGELOG.md` up to date with every public API change.
## Code style
- `just check` before committing (format + clippy with all pedantic and nursery
lints as errors). Requires `just` and `cargo-nextest` installed locally.
- `just test-all` to run all tests including doctests.
- All public items must have doc comments with at least one `# Example`.
- No `eprintln!` or `println!` in library code.
- `unsafe_code` is `forbid`; no unsafe blocks anywhere.
## Design invariants
- `FrameTimer` stores `N` frame samples in a ring buffer indexed by `head`.
The invariant `head < N` is maintained by `% N` in every write path.
- Phase slots are registered by name on first use and reused thereafter.
The inline array has `MAX_PHASES = 8` slots; extra phase names beyond that
limit are silently dropped (safe, never panics).
- `FrameStats::compute` sorts a stack-allocated copy of the window to compute
percentiles. This is O(N log N) on the stack and is only called when the
caller explicitly requests statistics.
## No interactive jj/git
Never use `-i`/`--interactive` flags. Always pass `-m` to `jj describe`/`jj new`.