Add LICENSE-MIT and LICENSE-APACHE (Copyright (c) 2026 ArtCraft Team and the LightCraft contributors) and docs/brand/LICENSE-brand.txt from the Crafting Apps licensing standard. Rewrite NOTICE to the standard template and drop the stale Source Sans 3 entry (only Inter is bundled). Attribute docs/brand/ in assets/ATTRIBUTION.md so `cargo xtask assets` passes again. README gets the standard "License and credits" section; AGENTS.md/CLAUDE.md note the brand exception to the asset rule. Co-Authored-By: Claude Opus 5.5 <[email protected]>
9.1 KiB
LightCraft — instructions for agents
LightCraft is a clean-room, open-source, pure-Rust photo library + non-destructive raw developer targeting Adobe Lightroom parity (and beyond). Native on macOS, Windows, Linux; web via WASM. Sibling of ../printcraft (Acrobat), ../photocraft (Photoshop), ../drawcraft (Illustrator) and ../filmcraft (Premiere), with the same conventions.
Start every session here
- Read
plan/STATUS.md(current milestone, next unchecked task, blockers). - Read the task in
plan/execution-plan.md§3, the relevant section ofplan/architecture.md, and the README/docs of the crate you touch. Behaviour/visual reference:plan/lightroom/(incl.10-observed-ui.md+ screenshots). - Pick work from
docs/parity.md→ Top gaps (Lightroom parity tracker: one row per feature, menu item and shortcut). When you land a feature, update its row(s) and the gap list in the same commit;cargo xtask parity(part ofci) checks that everycmd:/ctl:id and path the tracker cites still exists, andcargo xtask parity --writerefreshes its summary. - Follow the autonomous operation protocol (
plan/execution-plan.md§7). Don't stop to ask unless §7 lists the decision as the user's.
plan/ is gitignored (local-only).
Merging agent branches: merge one branch, run cargo xtask ci, fix, commit — then the next. Two individually green
branches can still break each other (e.g. a new struct field vs. a new constructor).
Resuming after a crash / another session: check git status on main, git worktree list, and each worktree's
git log main..HEAD + git status for unmerged commits or uncommitted work before starting anything new. Commit small
and often so a crash loses minutes, not hours.
Non-negotiables
- Clean-room. Never read/disassemble anything inside Adobe app bundles (names/listings only). Never copy Adobe icons, presets, profiles (DCP), lens profiles (LCP), camera matrices, fonts. Observation of the installed Lightroom is read-only (it syncs the user's personal library: never import/edit/rate/delete there). Never copy GPL/LGPL/AGPL code (darktable, RawTherapee, ART, LibRaw, rawspeed, rawloader, rawler, lensfun, dcraw-derived GPL code…).
- Pure Rust in the product. No C/C++ dependencies.
- Layering (
plan/architecture.md§3, enforced bycargo xtask layers): nothing below L5 depends on egui/eframe/winit/rfd. - Everything is a command (
crates/engine): id, label, menu path, shortcut, params, enabled(), run(). UI, CLI, control channel and MCP all dispatch by id. Every slider is adevelopcontrol spec. - Resolution independence: settings use normalized image coordinates and relative radii; previews and exports must match.
- Quality gates before every commit:
cargo xtask ci(fmt, clippy -D warnings, tests, layers, assets, wasm). - Commits: one task id per commit (
M2.3: local Laplacian highlights/shadows). Only green states. End messages with the attribution line required by the environment.
Assets: icons, images, fonts (ABSOLUTE RULE — never violate)
- Never use any iconography, image, artwork, font, sound or other asset from Adobe products (no Lightroom/Creative Cloud icons, no screenshots, no presets/profiles/LUTs, no UI bitmaps — not even as a temporary placeholder or "reference copy"). Observing Adobe's UI to imitate layout and behaviour is allowed; copying or tracing its assets is not.
- This includes Adobe's open-licensed assets: no Source Sans/Serif/Code or Source Han fonts, no Adobe Fonts, no Adobe-published icon sets, sample photos, colour profiles or LUTs — even when OFL/MIT. The UI font is Inter (OFL).
- Every asset in the repository must be one of: our own original work (e.g. icons drawn in code as vectors, procedurally generated demo photos), public domain / CC0, Creative Commons (CC-BY / CC-BY-SA with attribution honoured), OFL (fonts), or permissive open-source (MIT/Apache-2.0/BSD/ISC) — or contributed by a person who created the asset and licenses it openly.
- Exception:
docs/brand/. The ArtCraft name, wordmark and logos there are ArtCraft Team trademarks, not open source and not covered by LightCraft's MIT OR Apache-2.0 licence (LICENSE-MIT,LICENSE-APACHE,NOTICE); their terms are indocs/brand/LICENSE-brand.txt. Use them only unmodified and never redraw, recolour or derive from them. - Every asset must have an entry in
assets/ATTRIBUTION.md(path, title, author/creator, source URL or "original work", licence, date added, modifications) and its licence text when required (e.g.assets/fonts/OFL-*.txt). Add the entry in the same commit as the asset. Assets without an attribution entry must not be committed. - Icons drawn in code (e.g.
crates/ui-egui/src/icons.rs) are original work and are recorded inassets/ATTRIBUTION.mdas such; do not trace them from Adobe icons. - Demo/test images: generated procedurally by
lightcraft-scenes, or CC0 downloads kept in the gitignoredcorpus/with their source recorded. Screenshots of Adobe apps live only in the gitignoredplan/and are never committed or published. - Enforced:
cargo xtask assets(inci) fails when an image/icon/font/sound/video/raw/ICC/XMP file is not matched by a path pattern in the first column ofassets/ATTRIBUTION.md, when a referenced licence file is missing, when a file name suggests Adobe material, or when an Adobe profile/template format (.dcp,.lcp,.lrtemplate, …) appears. Never weaken this check to make a commit pass — fix the attribution or remove the asset. - When in doubt about an asset's licence: don't use it.
Running and looking at the app
cargo run --release -p lightcraft -- --control 7980opens the desktop app with the JSON-lines control server (seedocs/control-protocol.md).- Never send OS-level synthetic input (osascript/System Events keystrokes or clicks,
cliclick, accessibility automation): it goes to whatever window is frontmost — the user's terminal or other apps. Drive LightCraft only through its control channel (ui.key,ui.pointer,ui.clickWidget,ui.menu.invoke) or headless snapshots. - For UI work, look at the result: drive via the control channel and take
ui.screenshot, compare withplan/lightroom/screenshots/. - Unattended (display asleep/locked, CI, nightly runs): prefer headless snapshots — no window needed:
lightcraft-cli snapshot --demo --script tour.jsonl -o out.png --size 1600x1000(control-protocol requests, one per line; seedocs/control-protocol.md→ Headless rendering). In a running app useui.screenshot {"path": …, "headless": true}; windowed screenshots fall back to headless after 2 s. - MCP:
lightcraft-cli mcp(headless,--demofor the procedural library) orlightcraft-cli mcp --connect(drives the running app). Seedocs/mcp.md. Quick non-UI checks:lightcraft-cli render in.jpg -o out.jpg --set light.exposure=1. - Export goes through
lightcraft_engine::export(one encoder for app, CLI, MCP and web); UI-only commands live incrates/ui-egui/src/menus.rs. - Shell gotcha:
mv/cpare aliased interactive here — use/bin/mv -f//bin/cp -f. - Parallel agents: separate git worktrees and
CARGO_TARGET_DIR=target/agent-<name>; each agent uses its own control port (pick one in 18000–19999, never the default 7980) and its own scratch subfolder (<scratch>/<agent-name>/) — neverrm -rfshared paths; delete your target dir when done (disk is shared); keep everyCargo.tomlvalid at all times (thecrates/*glob means one broken manifest breaks everyone). - Test corpora:
cargo xtask corpus --downloadintocorpus/(gitignored, CC0 only). Never commit media.
Testing & performance (do this often)
- Unit/property tests next to the code; end-to-end tests drive real binaries (
crates/mcp/tests/e2e.rs,apps/lightcraft-cli/tests/). New features need at least one test that would fail without them. - Run the app after every user-visible change: launch with
--control 7980, drive it with a JSON-lines script (docs/showcase/run.py file.jsonl), takeui.screenshot, and look at it. Checkui.inspect→perf. - Benchmarks:
cargo xtask bench(24 MP raw from corpus; CPU and GPU columns) appends totarget/bench/history.jsonland flags CPU-time regressions > 20 % vs the previous run (--strictto fail). Run it before and after perf work. - Measure, don't guess:
LIGHTCRAFT_PROFILE=1prints per-stage pipeline timings to stderr; time CLI renders with/usr/bin/time. Record numbers inplan/STATUS.md→ Metrics. Budgets: slider update ≤ 16 ms (draft) / loupe ≤ 60 ms on ~2.5 MP; export ≤ 1 s per 24 MP JPEG. - Never commit media: test images are procedural (
lightcraft-scenes) or CC0 downloads in the gitignoredcorpus/.
Map of the code
geom, color, raster, tiff (L0) → raw, codecs, meta, develop (L1) → pipeline → catalog → engine
→ ui-egui, mcp (L5) → apps lightcraft (desktop), lightcraft-cli (render/commands/MCP). scenes generates demo
photos. xtask = tooling (ci, layers, assets, parity, wasm, corpus, stats).