From ad272ca071f8ee2579b39c62522e0f2abfe71ded Mon Sep 17 00:00:00 2001 From: "Dylan M. Taylor" Date: Wed, 28 Oct 2026 10:52:53 +0000 Subject: [PATCH] Enforce workspace Clippy standards and document lint policy --- AGENTS.md | 2 +- CLAUDE.md | 2 +- Cargo.lock | 2 ++ Cargo.toml | 8 +++++--- clippy.toml | 1 + crates/engine/Cargo.toml | 1 + crates/pdf/Cargo.toml | 1 + crates/ui-egui/Cargo.toml | 1 + 8 files changed, 13 insertions(+), 5 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 289cb12d0..01a8da9b3 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -23,7 +23,7 @@ Standards and learnings shared across the crafting apps live in `../../craftrule People trust GridCraft with their numbers; a crash loses their work. **This outranks feature work.** Standard: [`craftrules/standards/never-crash.md`](https://github.com/storytold/craftrules/blob/main/standards/never-crash.md). - **No panics in non-test code:** no `unwrap()`, `expect()`, `panic!`, `unreachable!`, `todo!`, `unimplemented!`; no `unsafe` (`unsafe_code = "forbid"`). - **Errors are `Result`** through the crate's error type and `?`. -- **Input-derived numbers are hostile** (files, formulas, commands, MCP/control params): `get()` instead of indexing, checked/saturating arithmetic, cap input-sized allocations (huge ranges, `REPT`, `SEQUENCE`, whole-column references). +- **Input-derived numbers are hostile** (files, formulas, commands, MCP/control params): validate indexes and ranges before access, use checked access when validity is not established, use checked/saturating arithmetic, and cap input-sized allocations (huge ranges, `REPT`, `SEQUENCE`, whole-column references). - **Bound recursion** (formula nesting, dependency chains, names referring to names). - **Last-resort guard:** `Session::execute` catches escaped panics and restores the workbook. It's a safety net, not a licence. - **Prove it:** every crash fix lands with a regression test (`tests::every_command_survives_empty_params` fuzzes every command; `crates/engine/tests/it/command_sequence_fuzz.rs` fuzzes random command sequences against undo/redo, XLSX round-trip and full-recalc invariants; soak it with `GRIDCRAFT_FUZZ_SEEDS`/`GRIDCRAFT_FUZZ_STEPS`, replay with `GRIDCRAFT_FUZZ_SEED`). diff --git a/CLAUDE.md b/CLAUDE.md index 8bf527c54..266016a1a 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -27,7 +27,7 @@ People trust GridCraft with their numbers; a crash loses their work. **This outr - **Bound recursion** (formula nesting, dependency chains, names referring to names). - **Last-resort guard:** `Session::execute` catches escaped panics and restores the workbook. It's a safety net, not a licence. - **Prove it:** every crash fix lands with a regression test (`tests::every_command_survives_empty_params` fuzzes every command; `crates/engine/tests/it/command_sequence_fuzz.rs` fuzzes random command sequences against undo/redo, XLSX round-trip and full-recalc invariants; soak it with `GRIDCRAFT_FUZZ_SEEDS`/`GRIDCRAFT_FUZZ_STEPS`, replay with `GRIDCRAFT_FUZZ_SEED`). -- Crates carry `#![deny(clippy::unwrap_used, clippy::expect_used, clippy::panic, clippy::unimplemented, clippy::todo, clippy::unreachable)]`. +- Production crate roots carry `#![deny(clippy::unwrap_used, clippy::expect_used, clippy::panic, clippy::unimplemented, clippy::todo, clippy::unreachable)]`; every new workspace crate must also include `[lints] workspace = true` in `Cargo.toml` to inherit `[workspace.lints]`. ## Non-negotiables - **Clean-room.** Microsoft Excel is installed on the dev machine and may be *observed* black-box: run it, use its UI with synthetic workbooks, take screenshots (by window id) stored only under `plan/excel/screenshots/`. Never read, disassemble or copy anything inside the Office bundle, never commit files produced by Excel, never copy GPL/AGPL/LGPL code (LibreOffice, Gnumeric…). Function behaviour comes from public documentation and observation. diff --git a/Cargo.lock b/Cargo.lock index 87ff12215..f5a6a6328 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2024,6 +2024,7 @@ dependencies = [ "serde", "serde_json", "thiserror 2.0.21", + "web-time", "zip 3.0.0", ] @@ -2097,6 +2098,7 @@ dependencies = [ "sys-locale", "toml", "web-sys", + "web-time", "zbus", ] diff --git a/Cargo.toml b/Cargo.toml index 32823c84a..4bafc9b27 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -34,7 +34,8 @@ serde = { version = "1", features = ["derive", "rc"] } serde_json = { version = "1", features = ["float_roundtrip"] } log = "0.4" # All date/time conversion goes through chrono (no hand-rolled calendar code beyond the 400-year range extension; AGENTS.md). -chrono = { version = "0.4.45", default-features = false, features = ["std"] } +chrono = { version = "0.4.45", default-features = false, features = ["std", "clock"] } +web-time = "1.1.0" rayon = "1" regex = { version = "1", default-features = false, features = ["std", "unicode", "perf"] } quick-xml = "0.41" @@ -67,10 +68,11 @@ craft-window = { version = "0.1.0", git = "https://github.com/storytold/craft-li unsafe_code = "forbid" [workspace.lints.clippy] +cognitive_complexity = "deny" +too_many_arguments = "deny" +wildcard_imports = "deny" dbg_macro = "warn" todo = "warn" -too_many_arguments = "allow" -type_complexity = "allow" [profile.dev.package."*"] opt-level = 2 diff --git a/clippy.toml b/clippy.toml index de0f11db4..c6fbddafd 100644 --- a/clippy.toml +++ b/clippy.toml @@ -14,3 +14,4 @@ disallowed-methods = [ disallowed-types = [ { path = "egui::ComboBox", reason = "use craft_ui::ComboBox: egui's combo box menu can't grow back while open (egui#5225)" }, ] +cognitive-complexity-threshold = 30 diff --git a/crates/engine/Cargo.toml b/crates/engine/Cargo.toml index e8ea91c26..1de94c60c 100644 --- a/crates/engine/Cargo.toml +++ b/crates/engine/Cargo.toml @@ -17,6 +17,7 @@ gridcraft-model = { workspace = true } gridcraft-calc = { workspace = true } serde = { workspace = true } serde_json = { workspace = true } +web-time = { workspace = true } thiserror = { workspace = true } log = { workspace = true } gridcraft-xlsx = { workspace = true } diff --git a/crates/pdf/Cargo.toml b/crates/pdf/Cargo.toml index 6cb0d2e3a..cd63456c2 100644 --- a/crates/pdf/Cargo.toml +++ b/crates/pdf/Cargo.toml @@ -4,6 +4,7 @@ version.workspace = true edition.workspace = true license.workspace = true description = "GridCraft's tiny self-contained PDF 1.7 writer (standard 14 fonts, vector drawing, RGBA images)" +readme = "README.md" [lints] workspace = true diff --git a/crates/ui-egui/Cargo.toml b/crates/ui-egui/Cargo.toml index 762663c5c..b9cddcb90 100644 --- a/crates/ui-egui/Cargo.toml +++ b/crates/ui-egui/Cargo.toml @@ -23,6 +23,7 @@ serde_json = { workspace = true } log = { workspace = true } image = { workspace = true } skrifa = { workspace = true } +web-time = { workspace = true } # Linux only, where winit reports no system theme: the desktop portal's light/dark answer (see # `desktop_theme.rs`). Already in the tree, with these features, through egui's own