mirror of
https://github.com/storytold/effectcraft.git
synced 2026-10-13 15:09:03 +00:00
Never crash: steering rules, clippy.toml, forbid unsafe
- AGENTS.md: a "Never crash" section ahead of the asset rules (the rule, why, the bans, Result/? patterns, hostile input-derived numbers, bounded recursion, lock poisoning, the last-resort guard, a regression test per crash fix), linking craftrules standards/never-crash.md. CLAUDE.md and CONTRIBUTING.md point to it. - clippy.toml: allow unwrap/expect/panic/indexing in tests, so the restriction lints can be denied crate by crate without touching test code. - [workspace.lints.rust] unsafe_code = "forbid" (was "deny"); there is no unsafe or allow(unsafe_code) in the workspace. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
10644a83aa
commit
0da12c676f
5 files changed
+43
-1
No files matched your search
@@ -3,6 +3,39 @@
|
||||
These rules apply to every human and AI contributor. `CLAUDE.md` holds the working instructions; this
|
||||
file holds the rules that must never be broken. When the two disagree, this file wins.
|
||||
|
||||
## Never crash
|
||||
|
||||
People trust EffectCraft with hours of work. A malformed project, PSD, SVG, Lottie or media file, a bad
|
||||
expression or script, a broken plug-in, a bad control-channel or MCP argument, a corrupt preferences file
|
||||
or a full disk must produce an error the user (or agent) can act on, never a crash and never lost work.
|
||||
**This rule outranks feature work:** don't ship a feature by adding a panic path, and fix a crash before
|
||||
building on top of it. Full standard: [craftrules `standards/never-crash.md`](https://github.com/storytold/craftrules/blob/main/standards/never-crash.md).
|
||||
|
||||
- **Fail with `Result<T, E>`** through the crate's error type and propagate with `?`; add context
|
||||
(`map_err`, an error variant) rather than discarding it. Lenient readers fall back and record the repair.
|
||||
- **No panicking shortcuts in non-test code:** no `unwrap()`, `expect()`, `panic!`, `unreachable!`,
|
||||
`todo!` or `unimplemented!`. Use `?`, `ok_or(..)?`, `let … else`, `if let`, or `unwrap_or*` where a
|
||||
fallback is genuinely correct (never where it would silently corrupt a document). Unfinished features
|
||||
return an "unsupported" error. The only exception is a provably infallible literal, written as
|
||||
`#[allow(clippy::expect_used)]` + `.expect("why this cannot fail")`.
|
||||
- **No `unsafe`** (`unsafe_code = "forbid"` for the workspace).
|
||||
- **Every input-derived number is hostile.** Use `get()` instead of `[i]`/`[a..b]` when the position
|
||||
comes from a file, a user, an agent or arithmetic on those; slice strings only at char boundaries; use
|
||||
checked or saturating arithmetic for lengths, offsets and counts; guard division by zero and NaN/inf
|
||||
casts; cap allocations sized by input.
|
||||
- **Bound recursion:** projects, precomps, expressions and SVG/PSD trees can be cyclic or deeply nested;
|
||||
walk them with seen-sets or depth limits.
|
||||
- **Don't cascade:** handle lock poisoning (`lock().unwrap_or_else(PoisonError::into_inner)` or an
|
||||
error), and treat worker-thread join results as `Result`s.
|
||||
- **Last-resort guard:** the app wraps command execution and file import/export in a panic hook /
|
||||
`catch_unwind` boundary that turns an escaped panic into an error and keeps the document. It is a
|
||||
safety net, not a substitute for the rules above; keep `panic = "unwind"`.
|
||||
- **Prove it:** every crash fix comes with a small synthetic regression test that panicked before the fix.
|
||||
|
||||
Tests, benches, fuzz targets and `xtask` may `unwrap()`; `clippy.toml` allows it in tests. Crates that are
|
||||
clean carry `#![deny(clippy::unwrap_used, clippy::expect_used, clippy::panic, clippy::unimplemented,
|
||||
clippy::todo, clippy::unreachable)]`; new crates start with it.
|
||||
|
||||
## 1. Assets: no Adobe artwork, every asset licensed and attributed
|
||||
|
||||
This rule is absolute. Breaking it is the most serious mistake a contributor can make on this project.
|
||||
|
||||
@@ -10,6 +10,7 @@ EffectCraft is a clean-room, open-source, pure-Rust motion graphics and visual e
|
||||
|
||||
## Non-negotiables
|
||||
**Read [`AGENTS.md`](AGENTS.md) first; its rules override everything here.** No Adobe assets, every asset licensed + attributed (`cargo xtask assets`).
|
||||
- **Never crash** (AGENTS.md "Never crash"; outranks feature work: a crash loses people's work). Non-test code has no `unwrap()`/`expect()`/`panic!`/`unreachable!`/`todo!`/`unimplemented!` and no `unsafe`: return `Result` and use `?`, `ok_or`, `let … else`. Input-derived indices, slices and arithmetic use `get()` and checked/saturating math; recursion is depth-limited; locks handle poisoning. The app's last-resort guard turns an escaped panic into an error and keeps the document. Every crash fix gets a regression test. Standard: [craftrules `standards/never-crash.md`](https://github.com/storytold/craftrules/blob/main/standards/never-crash.md).
|
||||
- **Clean-room.** Behaviour and public docs only. No GPL/LGPL/AGPL code. ffmpeg only as an external test oracle.
|
||||
- **Pure Rust.** Media codecs come from FilmCraft crates (git deps behind `crates/media`, see `plan/adr/0001`).
|
||||
- **Layering** (`cargo xtask layers`): nothing below L5 depends on egui/eframe/winit/rfd/cpal; L0–L4 build for wasm32.
|
||||
|
||||
@@ -24,6 +24,10 @@ cargo xtask ci # what every commit must pass
|
||||
- **Everything is a command.** New features are engine commands with an id, label, menu path,
|
||||
shortcut and parameters, so the UI, the CLI and the MCP server get them at once. Interactive
|
||||
widgets register an automation id.
|
||||
- **Never crash.** Non-test code returns errors instead of panicking: no `unwrap()`, `expect()`,
|
||||
`panic!`, `unreachable!`, `todo!`, `unimplemented!` or `unsafe`, checked indexing and arithmetic on
|
||||
input-derived values, and a regression test with every crash fix. See the "Never crash" section of
|
||||
[AGENTS.md](AGENTS.md).
|
||||
- **Tests with every change**, and green `cargo xtask ci` before every commit. One task per commit.
|
||||
|
||||
## How to add…
|
||||
|
||||
+1
-1
@@ -116,7 +116,7 @@ cpal = "0.16"
|
||||
# filmcraft-isobmff = { path = "../filmcraft/crates/isobmff" }
|
||||
|
||||
[workspace.lints.rust]
|
||||
unsafe_code = "deny"
|
||||
unsafe_code = "forbid"
|
||||
|
||||
[workspace.lints.clippy]
|
||||
dbg_macro = "warn"
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
allow-unwrap-in-tests = true
|
||||
allow-expect-in-tests = true
|
||||
allow-panic-in-tests = true
|
||||
allow-indexing-slicing-in-tests = true
|
||||
Reference in new issue
Block a user