Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,18 @@ See
- After the memory win lands, spend dedicated rounds cutting its CPU cost; reaching the 1/3
ceiling is a limit, not a target. Put the ledger table in the PR and on the parent issue.

## Design principles (fleet directives, zackees/ci.yml#163)

Agent and review guidance from zackees/ci.yml `docs/policy-rust.md` ("Design principles, narrowed"). Not enforced by ci-lint; no rule ID.

1. **Search before you add.** Before adding a resolver, detector, predicate, guard or path helper, `rg` for an existing one. Reuse it, or say in the PR why it does not fit.
2. **Conflicting implementations get a research issue, not an inline winner.** If the same concept is implemented more than once with observably different behaviour and fixing it needs a design decision, file `research: N conflicting implementations of X -- which is canonical?` listing every copy (`file:line`) and what the difference does to real input; cross-reference it and carry on with your task. Copies that behave identically are a refactor, not an issue.
3. **Keep behaviour changes and refactors apart.** Separate commits, preferably separate PRs, never one mixed diff. This sits beside hard rule 2 (never mix C-core and `rust/` paths in one commit); both apply.
4. **Refactor first only when you would grow a giant function.** If a fix would add more than 50 lines to a function already over 200 lines, extract first in a separate behaviour-preserving change with characterization tests written first (RED -> GREEN). Otherwise fix it where it belongs; no unrequested restructures. Upstream mimalloc files are never restructured at all (hard rule 6): new logic goes in new files.
5. **Function and file size follow `RUST-018`'s ceilings.** The `rust/` workspace does not run the ratchet yet (no clippy `too_many_lines`/`cognitive_complexity` lint config), so nothing mechanical holds this line. New functions still stay under clippy's `too_many_lines` (100) and `cognitive_complexity` (25), and an existing function over them must not grow. Never split a file with `include!` fragments to dodge a length ceiling. Before splitting a hot file, check `git branch -a --contains` for in-flight branches -- a split is a rename and conflicts destructively.
6. **Fail fast, and delete before you abstract.** Reject invalid input at the boundary with a typed error; never fall back silently to a degraded path. Prefer deleting code to adding a layer. No new trait until there are two real implementations (a test double does not count). When reality diverges from a sub-issue, hard rule 7 still applies: escalate on the issue, do not improvise a fallback.
7. **Existing boundaries beat generic DRY.** The upstream overlay boundary (hard rules 2 and 6: fork logic in new files, guarded one-line hooks in upstream files), the Rust/C crate split in `rust/`, and documented deliberate copies win over removing duplication. Do not copy code across a crate boundary to get around it -- say the boundary hurts. An undocumented copy is a finding under 2; a documented one is not.

## Repo facts

- Branch layout: `main` is the **v3** line (crate 1.0.x, overlay pinned to `upstream/dev3`
Expand Down
Loading