* Prototype player: no clicks reach the prototype behind the link notice
* Selection colors: scopes filter the variable menu; the command binds as variable.bind does
* Style picker: color variables scoped to every selected layer's fill or stroke
* Corner button: named Corner smoothing on polygons and stars
* docs/gaps.md: known gaps from the #1311 review
* cargo fmt
* Style picker: clippy
A Selection colors row could take a color style but not a color
variable, and a row linked to a style or variable could not be
unlinked from there.
selection.bindColorVariable binds a color variable to every solid fill
and stroke slot a row stands for. It replaces a color style on that
list and any earlier binding of the slot. A text range with fills of
its own takes the variable's value in the layer's modes. Gradients and
slots outside the variable's scopes are refused.
selection.detachColor unlinks the style or variable of a row's slots
and keeps their colors.
In the Design panel, the Styles menu of an unlinked row lists the
document's color variables after its color styles, and a linked row
shows a Detach button in the Styles button's place.
* Dev profile: line tables for workspace crates, no debug info for dependencies
* Tests: one integration-test binary per crate with several test files
* xtask ci: nextest, doctests, tests without examples, --keep-going; add xtask test
- `figcraft-cli mcp --automation-read-root DIR --automation-write-root DIR` (each repeatable, `--flag=DIR` works too). When either is given, every file an agent's tool call reads must lie inside a read root or a write root, and every file it writes inside a write root. Anything else is an ordinary tool error (`automation path rejected: … is outside the folders that may be written: …`); nothing is written and the server keeps serving. Without the flags nothing changes.
- The desktop app takes the same flags (`figcraft --control PORT --automation-read-root DIR …`) and confines every control request and every frame of every window to them, so `figcraft-cli mcp --attach` drives a confined app. `--attach` together with the flags is a usage error, because the app runs the commands and only the app can confine them.
- New engine module `crates/engine/src/file_access.rs`: `Roots` (resolution and comparison), a thread-scoped `confined(roots, f)`, and the file primitives (`read`, `read_capped`, `open`, `metadata`, `read_dir`, `write` (atomic), `create_dir_all`, `exists`, `is_dir`). Every engine file access now goes through it. `crates/engine/clippy.toml` denies `std::fs::*`, `File::open/create`, `OpenOptions::open`, `Path::exists/is_file/is_dir/metadata/read_dir/canonicalize` and `figcraft_format::{write_file_atomic, save_file, load_file}` everywhere else in the engine, so a command added later is confined without a check of its own.
- `ui.screenshot` and `ui.render` return the PNG as base64 `data` when no `path` is given (before, `ui.screenshot` wrote `figcraft-screenshot.png` in the working directory and `ui.render` required a path). The attached MCP backend uses that, so it no longer writes and deletes temporary PNGs, and a confined app needs no exemption for them.
- `initialize`'s `instructions` name the folders the agent may read and write.
- `figcraft-cli` options may be given more than once (`Args::values`); single-valued options keep the last value, as before.
- Docs: `docs/mcp.md` › Confining file access (options, semantics, coverage, resolution, limits), `docs/control-protocol.md` › Confining file access and the optional `path` of `ui.screenshot` / `ui.render`, `docs/cli.md`, `figcraft-cli --help`, and the Automation line plus a revision row in `docs/target-app-parity.md`.
Fixes#715, fixes#481.
Preserve the upstream behaviour and regression tests alongside this feature. Align the control-server connection-limit test with main closing invalid JSON connections: assert EOF instead of shutting down an already closed socket on macOS.