|
1 | 1 | # spark-dashboard — Claude project rules |
2 | 2 |
|
3 | | -These rules are project-specific. Global coding/test/security rules in `~/.claude/rules/` still apply. |
| 3 | +Project-specific. Global rules in `~/.claude/rules/` still apply. |
4 | 4 |
|
5 | | -## Pre-commit verification (NON-NEGOTIABLE) |
| 5 | +## Branches & PRs |
6 | 6 |
|
7 | | -CI fails fast on formatting. Always run the same checks CI runs *before* committing — do not skip, do not batch for "later". |
| 7 | +- `main` is protected. No direct pushes. Every change goes through a PR. |
| 8 | +- Branch name: `<type>/<slug>` (`feat/...`, `fix/...`, `docs/...`). |
| 9 | +- Squash-merge PR title = the commit on `main` → it must be a valid Conventional Commit. |
| 10 | +- All `ci.yml` jobs (rust, frontend, installer) must pass before merge. |
8 | 11 |
|
9 | | -### Rust changes (anything under `src/`, `Cargo.toml`, `Cargo.lock`) |
| 12 | +## Commits drive releases |
10 | 13 |
|
11 | | -Run from the repo root, in this exact order (mirrors `.github/workflows/ci.yml` → job `rust`): |
| 14 | +`release-please` reads commits on `main` to bump versions and publish to crates.io. Format: `<type>(<scope>)<!>: <description>`. |
| 15 | + |
| 16 | +| Type | Bump (pre-1.0) | |
| 17 | +| ---------------------------------------------------------- | ------------------------------- | |
| 18 | +| `feat:` | minor | |
| 19 | +| `fix:` | patch | |
| 20 | +| `feat!:` / `BREAKING CHANGE:` | minor (becomes major after 1.0) | |
| 21 | +| `chore`, `docs`, `refactor`, `test`, `ci`, `perf`, `style` | none | |
| 22 | + |
| 23 | +Tags: `vX.Y.Z`. After merge, release-please opens a rolling release PR; merging it tags + triggers `publish.yml` (`cargo publish`). |
| 24 | + |
| 25 | +**Never hand-edit**: `Cargo.toml` version, `Cargo.lock`, `.release-please-manifest.json`, `frontend/package.json`, `frontend/package-lock.json`, `CHANGELOG.md`. Release-please owns them. |
| 26 | + |
| 27 | +## Pre-commit checks (run before pushing) |
| 28 | + |
| 29 | +Rust changes (`src/`, `Cargo.*`): |
12 | 30 |
|
13 | 31 | ```bash |
14 | 32 | cargo fmt --all -- --check |
15 | 33 | cargo clippy --all-targets --locked -- -D warnings |
16 | 34 | cargo test --locked |
17 | 35 | ``` |
18 | 36 |
|
19 | | -All three must exit 0. If `fmt --check` fails, run `cargo fmt --all` to fix, then re-run the check. |
20 | | - |
21 | | -Note: the CI rust job builds the frontend first because `rust-embed` needs `frontend/dist/` at compile time. If you touched embedded assets, also run `(cd frontend && npm ci && npm run build)` before `cargo clippy`/`cargo test`. |
22 | | - |
23 | | -### Frontend changes (anything under `frontend/`) |
| 37 | +Frontend changes (`frontend/`): |
24 | 38 |
|
25 | 39 | ```bash |
26 | | -cd frontend |
27 | | -npm run build |
28 | | -npm test -- --run |
| 40 | +cd frontend && npm run build && npm test -- --run |
29 | 41 | ``` |
30 | 42 |
|
31 | | -Both must pass. |
32 | | - |
33 | | -### When in doubt |
34 | | - |
35 | | -If a change touches *both* Rust and frontend (e.g. metrics shape changes), run the full Rust block AND the full frontend block. CI runs both; you should too. |
36 | | - |
37 | | -## Cross-stack contract: metrics |
38 | | - |
39 | | -The metrics payload is consumed by the frontend. When you change *any* of the following, you must update *all* of the listed touchpoints in the same commit (or the same PR at minimum): |
| 43 | +If both stacks changed, run both blocks. If embedded assets changed, build the frontend first (`rust-embed` needs `frontend/dist/`). |
40 | 44 |
|
41 | | -**Trigger** — changes to: |
42 | | -- `MemoryMetrics` / `GpuMetrics` / `CpuMetrics` struct shapes in `src/metrics/` |
43 | | -- JSON field names / `serde` rename attributes |
44 | | -- Display logic (e.g. `display_total_bytes`, formatters, marketed-capacity rounding) |
45 | | -- New metric fields (added or removed) |
| 45 | +## Metrics contract (Rust ↔ frontend) |
46 | 46 |
|
47 | | -**Required updates**: |
48 | | -1. **Rust unit tests** in `src/metrics/` — cover the new field/branch (`#[cfg(test)]` modules) |
49 | | -2. **TypeScript types** in `frontend/src/types/metrics.ts` — keep in sync with serde output |
50 | | -3. **Frontend formatters** in `frontend/src/lib/format.ts` — if the value needs human formatting |
51 | | -4. **Vitest specs** in `frontend/src/__tests__/` — cover new rendering / formatting behavior |
52 | | -5. **Affected components** in `frontend/src/components/` — wire new fields through |
| 47 | +When you change `MemoryMetrics`/`GpuMetrics`/`CpuMetrics` shape, serde names, display logic, or fields — update all of these in the same PR: |
53 | 48 |
|
54 | | -If any of (1)–(5) is genuinely not applicable, say so explicitly in the commit message. Default assumption is that all five are needed. |
| 49 | +1. Rust unit tests in `src/metrics/` |
| 50 | +2. TS types in `frontend/src/types/metrics.ts` |
| 51 | +3. Formatters in `frontend/src/lib/format.ts` |
| 52 | +4. Vitest specs in `frontend/src/__tests__/` |
| 53 | +5. Components in `frontend/src/components/` |
55 | 54 |
|
56 | | -## When adding or changing any feature |
| 55 | +If one is genuinely N/A, say so in the commit. |
57 | 56 |
|
58 | | -Add or update tests in the same commit. No behavior change ships without test coverage updates — backend OR frontend. This has been forgotten before; do not repeat. |
| 57 | +## Tests ship with the change |
59 | 58 |
|
60 | | -- New Rust function with branching logic → unit test in same file's `#[cfg(test)] mod tests` |
61 | | -- New frontend component or formatter → Vitest spec in `frontend/src/__tests__/` |
62 | | -- New API field → both the Rust serializer test AND the frontend type/test |
| 59 | +No behavior change merges without test coverage in the same PR. Rust branches → `#[cfg(test)]`. Frontend components/formatters → Vitest. New API field → both sides. |
0 commit comments