Files
2026-10-31 04:17:32 +00:00

6.9 KiB
Raw Permalink Blame History

FilmCraft — instructions for agents

FilmCraft is a clean-room, open-source, pure-Rust non-linear video editor targeting Adobe Premiere Pro parity (and beyond). Native on macOS, Windows, Linux; web via WASM. Sibling of ../photocraft (Photoshop), ../pdfcraft (Acrobat) and ../vectorcraft (Illustrator; formerly DrawCraft), with the same conventions.

Start every session here

plan/ is maintainer-local (gitignored, not in the repo). Each step names the public equivalent to use if you don't have it.

  1. Read plan/STATUS.md (current milestone, next unchecked task, blockers). Public: ROADMAP.md, then docs/gaps.md (ranked shortfalls) and docs/roadmap.md (current focus).
  2. Read the task in plan/execution-plan.md §3, the relevant section of plan/architecture.md, and the README/docs of the crate you touch. Public: docs/architecture.md, docs/contributing.md, docs/testing.md. Visual/behaviour reference: plan/premiere/ (local only, never committed).
  3. Follow the autonomous operation protocol (plan/execution-plan.md §7; public summary: docs/agents.md §5–7). Don't stop to ask unless it lists the decision as the user's.

Non-negotiables

Read AGENTS.md first; its rules override everything here.

  • Never crash (AGENTS.md §0). People depend on FilmCraft; a crash loses their work, so this outranks feature work. No unwrap/expect/panic!/unreachable!/todo!/unimplemented! or unsafe outside tests: return Result<T, E> and propagate with ? (ok_or, let … else, if let). Treat every number from media, project files, presets or CLI/MCP/control params as hostile: get() instead of [i], checked/saturating math, no division by possibly-zero values, capped allocations, bounded recursion. lock().unwrap_or_else(PoisonError::into_inner); background jobs run under catch_unwind. The panic hook + UI catch_unwind (crates/ui-egui/src/crash.rs) are the last-resort guard, not a licence. Every crash fix gets a regression test that panicked before. In particular (§1): never use Adobe iconography, images or any other Adobe asset. Every asset must be openly licensed (OSS / public domain / Creative Commons, or original work by a contributor) and must have a <file>.attribution sidecar plus an entry in ATTRIBUTION.md. cargo xtask assets enforces this.
  • Fonts live in storytold/craft-fonts, never in this repo (no new font files here; AGENTS.md §1.9). Build with them: git clone https://github.com/storytold/craft-fonts ../craft-fonts && CRAFT_FONTS_DIR="$PWD/../craft-fonts" cargo run -p filmcraft (crates/text/build.rs embeds them as filmcraft_text::fonts::CRAFT_FONTS, used for Japanese in the UI and titles). Unset, CRAFT_FONTS is empty and everything must still build, test and run; never add craft-fonts to a Cargo.toml. Tests on its glyphs skip when it is empty, so run the gates with and without CRAFT_FONTS_DIR when you touch fonts.
  • Clean-room. Never read/disassemble anything inside Adobe app bundles (names/listings only). Never copy Adobe icons, presets, LUTs, fonts. Never copy GPL/LGPL/AGPL code (FFmpeg, x264, x265, MLT, Kdenlive, Shotcut, Olive, LAME…). ffmpeg/ffprobe run only as external test oracles / fixture generators — never linked or shipped.
  • Pure Rust in the product. OS media APIs only via Rust bindings in crates/platform (hardware decoding; the one crate allowed unsafe, see AGENTS.md §0.3 and docs/adr/0001-platform-ffi.md), optional, behind traits, with our decoders as the fallback.
  • Layering (docs/architecture.md §1, enforced by cargo xtask layers): nothing below L5 depends on egui/eframe/winit/rfd/cpal. L0 codec/container crates depend only on filmcraft-bitstream.
  • Exact time: all time is filmcraft_time::Tick (254 016 000 000/s). Never use f64 seconds for edit math.
  • Time goes through chrono (workspace dependency). Never hand-roll UTC/calendar conversion (days-to-date algorithms, leap-year math); a crate owns only its output format string. The one exception is range extension: past the years chrono can represent, shift the date by whole 400-year Gregorian cycles (146,097 days, after which the calendar repeats), let chrono compute the month and day, and add the cycles back to the year (splitting seconds into hours, minutes and seconds is plain arithmetic).
  • Everything is a command (crates/engine): id, label, menu path, shortcut, params, enabled(), run(). UI, CLI, control channel and MCP all dispatch by id.
  • Everything is agent-drivable: every interactive widget registers an automation id; UI state is serde so the control channel can read/set it.
  • Quality gates before every commit: cargo fmt --check, cargo clippy --workspace --all-targets -- -D warnings, cargo test --workspace, cargo xtask layers, cargo xtask assets, cargo xtask wasm (checks L0–L4 crates). cargo xtask ci runs them all.
  • New workspace crates must include [lints] workspace = true in Cargo.toml to inherit [workspace.lints]. Production crate roots must declare the required crate-level lint attributes before modules or other crate items; crate-level //! documentation may precede them.
  • Commits: one task id per commit (M2.4: CABAC residual decoding). Only green states. End messages with the attribution line required by the environment.

Running and looking at the app

  • cargo run -p filmcraft -- --control 9876 opens the desktop app with the JSON-lines control server (see docs/control-protocol.md).
  • For UI work, look at the result: drive via the control channel and take ui.screenshot, compare with plan/premiere/screenshots/ (maintainer-local; see docs/agents.md §3).
  • Parallel agents: separate git worktrees and CARGO_TARGET_DIR=target/agent-<name>; keep every Cargo.toml valid at all times (the crates/* glob means one broken manifest breaks everyone).
  • Test fixtures: generate with ffmpeg into target/fixtures/ (never commit media). See docs/testing.md.

CI workflows

  • Workflows in .github/workflows/ call the shared workflows in storytold/craft-common-actions at @main, with their inputs and secrets. No other jobs: if no shared workflow does what's needed, it doesn't go here.
  • Don't add or change CI in a feature or fix PR. If the existing workflows can't build or test a change, link an existing craft-common-actions issue or PR, or open a new issue, or a PR only for a small fix that is safe for every app and does not increase CI time.
  • Some workflow files here still run their own jobs. Don't add to them. Moving a job into craft-common-actions is its own task, never part of another PR, and the job stays here until a shared workflow runs it.