M8: comments and version history behaviour suite and fixes

A behaviour suite for comments and version history written from the public documentation
(`crates/engine/src/history_behaviour_tests.rs`, 15 tests, about 80 table rows plus stepwise checks),
each row with a one-line derivation; where the documentation is silent the row says so and pins
today's behaviour. 4 of the 15 tests failed on the old code. Fixes, all in shared engine code:

- **Live sessions: comment threads made in the session couldn't be used.** Their ids come from the
  creator's id space (e.g. 4294967297) and every thread command (`comment.reply`, `edit`, `react`,
  `resolve`, `move`, `delete`, `markRead`, `open`, `link`) refused them as "out of range".
  Comment ids are now parsed as ids, not small indexes.
- **Restoring a version lost newer comments.** Comments are a conversation about the file, kept
  apart from its design history: restoring now keeps the current comments; a comment on a layer
  the version doesn't have stays where it was (on the nearest surviving parent, or the canvas).
- **Restoring now keeps the replaced design in the history** as an autosave first, unless a
  version of it was just saved or restored (so work isn't only in the session's undo history).
  The checkpoint marker is now "none yet" for a freshly opened file and compares contents when
  normalising copied the document.
- **A titled autosave becomes a named version** (`version.rename` clears `auto`), so it is no longer
  dropped when autosaves make room.
- **Merging a branch adds to the main file's history:** the main file as it was (an autosave,
  when it changed since its last version), then `Merged “<branch>”`.
- `version.restore` refuses up front for a view-only live session (nothing goes into the history).

Pinned where the documentation is silent: pins go to the innermost frame under them (not to a
leaf layer); copies, duplicates and duplicated pages come without comments; replying reopens a
resolved thread; only authors delete their messages (no accounts); stepping past the last thread
stays on it; comments show on the canvas by default; versions stay with whoever saved them in a
live session.

`crates/engine/src/collab_live_tests.rs`: the test `Room` is `pub(crate)` so the suite can run a
live session. `crates/engine/src/cmd/props.rs`: one line reformatted by `cargo fmt` (it was
unformatted on the base, which failed the fmt check). `crates/render/src/effects_behaviour_tests.rs`:
the paint suite expected an offset drop shadow to grow the export on every side, but the later export
suite made exports grow only where the shadow falls (40 x 50 for a shadow 10 down); the base failed
the gate on it, so the expectation now says "grows" (wider or taller). No new commands.

Docs: collaboration-parity, target-app-parity (area 16 85%/60% -> 85%/62%, 2-5 h -> 2-4 h; full
parity ~306-595 h -> ~306-594 h; percentages unchanged at this rounding), ROADMAP (also corrects the
stale area 16 row, 80%/58%/4-8 h), gaps (gap 4's landed list), mcp.md.
This commit is contained in:
bflatastic
2026-10-12 02:09:10 +07:00
committed by BFlat
parent f2c22213d6
commit 1caf771e82
12 changed files with 734 additions and 66 deletions
+15 -11
View File
@@ -1,6 +1,6 @@
# FigCraft parity with Figma
> **Last reviewed:** 2026-10-10 · **Last updated:** 2026-10-11 · **Change:** minor (canvas navigation, guides and grids behaviour suite and fixes; export and inspect behaviour suite and fixes; .fig import: editable vector networks and more layer kinds; shapes and vector behaviour suite and fixes; paint and effects behaviour suite and fixes; frames, groups, sections and masks behaviour suite and fixes; styles and variables behaviour suite and fixes; prototyping behaviour suite and fixes; components behaviour suite and fixes; embedded image colour profiles; layers panel keyboard: F2 rename, Shift+F10 context menu, keyboard box selection, 10k-layer QA; per-side stroke weight variables; text behaviour suite: CJK line breaking, metrics, vertical trim; selection and transform behaviour suite and fixes; `.fig` import, best effort; auto layout behaviour suite and fixes; Display P3: gamut warning and soft-proof (true P3 blocked upstream); several windows; localization layer with a draft Spanish catalog; hosting figcraft-server: wss in the desktop app, server releases, deployment guide; plugin panels and settings; canvas fixes: boolean hit testing on the result, group drags, frame outlines and slices; code connect; stretch and scatter brushes, pen pressure; text on a path and pattern fills; team libraries on the server and swap library; branches: create, update from main, review and merge; animated GIF fills and TIFF images; Open recent, outlines for the selection and mask outlines: menu breadth 100%; extended collections, variables import/export, gradient stop and variant bindings; feature breadth ~80%; ready ~49%; last major: full re-measure against Figma desktop 126.10.7) · **Target:** Figma Design (desktop app 126.10.7, macOS)
> **Last reviewed:** 2026-10-10 · **Last updated:** 2026-10-12 · **Change:** minor (comments and version history behaviour suite and fixes; canvas navigation, guides and grids behaviour suite and fixes; export and inspect behaviour suite and fixes; .fig import: editable vector networks and more layer kinds; shapes and vector behaviour suite and fixes; paint and effects behaviour suite and fixes; frames, groups, sections and masks behaviour suite and fixes; styles and variables behaviour suite and fixes; prototyping behaviour suite and fixes; components behaviour suite and fixes; embedded image colour profiles; layers panel keyboard: F2 rename, Shift+F10 context menu, keyboard box selection, 10k-layer QA; per-side stroke weight variables; text behaviour suite: CJK line breaking, metrics, vertical trim; selection and transform behaviour suite and fixes; `.fig` import, best effort; auto layout behaviour suite and fixes; Display P3: gamut warning and soft-proof (true P3 blocked upstream); several windows; localization layer with a draft Spanish catalog; hosting figcraft-server: wss in the desktop app, server releases, deployment guide; plugin panels and settings; canvas fixes: boolean hit testing on the result, group drags, frame outlines and slices; code connect; stretch and scatter brushes, pen pressure; text on a path and pattern fills; team libraries on the server and swap library; branches: create, update from main, review and merge; animated GIF fills and TIFF images; Open recent, outlines for the selection and mask outlines: menu breadth 100%; extended collections, variables import/export, gradient stop and variant bindings; feature breadth ~80%; ready ~49%; last major: full re-measure against Figma desktop 126.10.7) · **Target:** Figma Design (desktop app 126.10.7, macOS)
The authoritative assessment of how close FigCraft is to Figma Design. [`ROADMAP.md`](../ROADMAP.md)
summarizes it; [`gaps.md`](gaps.md) is the ranked work list; the measured menu checklist is
@@ -21,7 +21,7 @@ summarizes it; [`gaps.md`](gaps.md) is the ranked work list; the measured menu c
| Essentials user | **~57%** | estimated ([below](#essentials-user): core features 77.8% × discounts 0.92 × 0.92 × 0.88) |
| Mainstream practitioner | **~49%** | estimated ([below](#mainstream-practitioner): weekly areas 71.0% × discounts 0.9 × 0.9 × 0.85) |
| Remaining to beta | **~170–305 h** one Opus 5.5 agent (~35–70 h wall-clock with 5 parallel agents) | estimated |
| Remaining to full parity | **~306–595 h** one agent (~86–150 h wall-clock with 5 parallel agents) | estimated |
| Remaining to full parity | **~306–594 h** one agent (~86–150 h wall-clock with 5 parallel agents) | estimated |
| Stage | **alpha**: the alpha gate passes ([roadmap](roadmap.md#alpha-gate)); multiplayer and checking the best-effort `.fig` import on real files are beta gaps (see [ROADMAP](../ROADMAP.md#stage)) | |
The previous figures (ROADMAP of 2026-10-10, "feature depth ~79%", "full parity 115–195 h") were
@@ -35,7 +35,7 @@ tool; presence was being graded as behaviour in places.
| Audience | Ready % | Opus 5.5 agent wall-clock hours to ~95% | Work that dominates |
|---|---|---|---|
| Full target (ready for real work) | ~51% | ~296–570 h | multiplayer (45–90), localization (45–75), plugins (15–40), the interaction pass (40–60), GPU canvas (30–60), AI (30–60), the `.fig` import's tail (5–10) |
| Full target (ready for real work) | ~51% | ~296–569 h | multiplayer (45–90), localization (45–75), plugins (15–40), the interaction pass (40–60), GPU canvas (30–60), AI (30–60), the `.fig` import's tail (5–10) |
| Mainstream practitioner | ~49% | ~131–245 h | core editor depth incl. the `.fig` import's tail (49–98), the interaction pass (40–60), real-file corpus and platform QA (25–50), `.fig` export for handing work back (15–30) |
| Essentials user | ~57% | ~60–110 h | the `.fig` import's tail so the files people send open well (5–10), core tool polish (25–45), interaction pass on the core tools (15–25), stability QA (10–20), onboarding and starter templates (5–10) |
@@ -109,20 +109,20 @@ Breadth: does it exist. Ready: depth, correctness and fidelity for real projects
| 13 | Prototyping | 6 | 90% | 74% | Video triggers and media actions, gamepad triggers, delays on mouse triggers, manual overlay offsets, real prototype QA (behaviour suite from the documentation, key combinations, interactive components playing their variants, drag-driven animations, physical springs landed) ([prototyping-parity](prototyping-parity.md)) | 3–6 |
| 14 | Import/export | 6 | 84% | 57% | `.fig` import's tail (best-effort import, editable vector networks, stand-ins for non-design layers and variable prototype actions landed; no real-file checks yet), `.fig` export, HEIC/video import, CMYK output intent ([file-format-parity](file-format-parity.md)) | 5–10 |
| 15 | Dev Mode / inspect | 2 | 93% | 70% | Dev resources links, import lines for connected instances inside generated layer trees; an editor extension is left to the MCP server (inspect behaviour suite with colour formats, rem and icon and image assets, code connect and plugins in Dev Mode landed) ([dev-mode-parity](dev-mode-parity.md)) | 1–3 |
| 16 | Comments, versions, find, misc | 3 | 85% | 60% | Comments are local only; a branch's own version history (branches with review and merge landed) | 2–5 |
| 16 | Comments, versions, find, misc | 3 | 85% | 62% | Comments are local only; a branch's own version history; comparing two versions (branches with review and merge, and a comments and version history behaviour suite from the documentation landed) | 2–4 |
| 17 | Multiplayer & sharing | 8 | 15% | 5% | Core landed (`crates/collab`: ids, change sets, server ordering, convergence tested); live sessions (preview): WebSocket transport, hosting from the desktop app, joining from the app or the browser, invite links that open the app, cursors, selections and follow, per-person undo, offline resume; a self-hosted `figcraft-server` with persistence and share links to edit or view. Left: accounts and teams, cursor chat ([collaboration-parity](collaboration-parity.md)) | 45–90 |
| 18 | Plugins & widgets | 4 | 45% | 28% | Own sandboxed WASM plugins landed (#101: manifest, permissions, menu, Run last, Manage, SDK, 2 examples), then plugin panels called back per button or changed value and per-plugin settings (ABI v2). Left: distribution, widgets; panels one at a time without a colour picker; Figma's plugins are JavaScript and don't run (a JS engine would be an owner decision) ([plugins.md](plugins.md)) | 15–40 |
| 19 | Team libraries & organization | 2 | 70% | 40% | Libraries kept on `figcraft-server` under their file and enabled by a share link (per-asset versions, background update checks, overrides kept), usage counts per component and file, swapping a library by names. Left: team-wide library lists, accounts and permissions, analytics over time, pushed update notices | 4–8 |
| 20 | Figma Draw extras | 2 | 80% | 55% | Have: variable width, lasso, shape builder, noise/texture, text on a path, pattern fills, stretch and scatter brushes, pen pressure (Windows pens, browser styluses). Missing: multi-edit, pressure from macOS/Linux tablets | 2–5 |
| 21 | AI features | 3 | 0% | 0% | First draft, rename layers, image edit/remove background, visual search, Make: needs local models (owner decision) | 30–60 |
| | **Weighted (÷113)** | 113 | **~82%** | **~61%** | | **148–309** |
| | Core editor only (1–16, ÷94) | 94 | ~93% | ~70% | | 46–95 |
| | **Weighted (÷113)** | 113 | **~82%** | **~61%** | | **148–308** |
| | Core editor only (1–16, ÷94) | 94 | ~93% | ~70% | | 46–94 |
## By dimension (ready for real work)
| Dimension | Weight | Ready | Hours | Evidence | Doc |
|---|---|---|---|---|---|
| Features (depth) | 35 | 61% | 46–94 (areas 1–13, 15, 16, 20) | The table above; core editor ~70% | this file |
| Features (depth) | 35 | 61% | 46–93 (areas 1–13, 15, 16, 20) | The table above; core editor ~70% | this file |
| UI/UX fidelity | 15 | 58% | 40–60 | Look & feel compared side by side with UI3 (~65% by the builders); tool-by-tool interaction (cursors, modifiers while dragging, hover states, popovers) not yet compared; accessibility names and keyboard navigation landed | [ui-parity](ui-parity.md) |
| File formats | 12 | 59% | 5–10 | `.fig` read, best effort, with editable vector networks (tested on generated fixtures, not real files), no `.fig` write; REST JSON import, SVG in/out, PNG/JPG/WebP/PDF export solid, with a behaviour suite from the documentation | [file-format-parity](file-format-parity.md) |
| Collaboration | 10 | 13% | 55–110 | Local comments, version history and branches with review and merge; the multiplayer core (sync model, server ordering, client reconciliation, convergence tests) landed in #103, and live sessions (preview) co-edit a file hosted by a desktop app or kept on a self-hosted `figcraft-server` with edit and view links, joined from the app or the browser (`docs/collab-protocol.md`) | [collaboration-parity](collaboration-parity.md) |
@@ -133,7 +133,7 @@ Breadth: does it exist. Ready: depth, correctness and fidelity for real projects
| Platforms | 3 | 75% | 10–20 | macOS, Windows (x64/x86/arm64), Linux, FreeBSD, web all packaged (v0.2.0); Figma also has iOS/Android apps; non-macOS QA thin | [hardware-parity](hardware-parity.md) |
| Ecosystem/plugins | 3 | 28% | 15–40 | Own WASM plugins with a Rust SDK and two examples (#101), plugin panels and settings (ABI v2); no Figma plugin compatibility, no widgets, no distribution or community files; the CLI, control channel and MCP server are ahead of Figma for agents | [gaps](gaps.md) |
| AI features | 2 | 0% | 30–60 | None | [gaps](gaps.md) |
| **Ready for real work** | 100 | **~51%** | **~306–595** | | |
| **Ready for real work** | 100 | **~51%** | **~306–594** | | |
Dimension hours add up to the full-parity total without double counting: the feature-area rows
for import/export (14), multiplayer and team libraries (17, 19), plugins (18) and AI (21) are
@@ -187,7 +187,7 @@ libraries (19, cloud/team admin), Figma Draw extras (20, not weekly for a produc
localization beyond English, specialist hardware. Real-time multiplayer (17) is cloud collaboration
and is left out as an area, but its effect on working with Figma users is counted in discount 3.
**2. Average depth** ("Ready" column, weighted): **71.0%**.
**2. Average depth** ("Ready" column, weighted): **71.1%**.
**3. Discounts for what still stops real work:**
@@ -197,7 +197,7 @@ and is left out as an area, but its effect on working with Figma users is counte
| Stability on real machines | ×0.90 | Never-crash lints, command guard with rollback, recovery copies and 963 tests, but no field record at all: the repository is private, v0.2.0 has had no outside users or issue reports, CI tests run on Linux only and hands-on QA is on macOS. Harsher than VectorCraft's ×0.92 because there is no outside evidence either way |
| File exchange with Figma users | ×0.85 | A Figma designer's work lives in shared Figma files. FigCraft opens a `.fig` (best effort, not yet checked on real files) but writes nothing Figma opens as a document; incoming work can come through the REST API JSON (one way, needs an access token), outgoing only as SVG, PDF, PNG or code. Teammates, reviewers and developers would all need FigCraft ([file-format-parity](file-format-parity.md), [collaboration-parity](collaboration-parity.md)) |
71.0% × 0.90 × 0.90 × 0.85 = **~49%** (estimated).
71.1% × 0.90 × 0.90 × 0.85 = **~49%** (estimated).
**4. User evidence (2026-10-10):** 0 issues, 0 praise or "switched from Figma" reports, 0 comments
from anyone but the maintainers (`gh issue list`, `gh api .../issues/comments`; the repository is
@@ -457,7 +457,10 @@ Hours in this narrative are the builders' estimates; the tables above supersede
Shift+C: read and reply). All of it through `comment.*` commands. Version history
landed (named versions saved in the `.figcraft` file; restore, rename, duplicate, delete; panel;
view a version on the canvas read-only before restoring it; autosave checkpoints every 30
minutes, folded in the panel). Real-time collaboration is designed (`docs/collab-protocol.md`:
minutes, folded in the panel). A behaviour suite written from the public documentation covers
both: restoring keeps the comments and first keeps the replaced design as an autosave, a titled
autosave becomes a named version, merging a branch records the main file before and after, and
threads made in a live session can be replied to and resolved. Real-time collaboration is designed (`docs/collab-protocol.md`:
WebSocket sessions the app can host itself, server-ordered per-property changes, live cursors)
and its core landed (`crates/collab`, no networking yet): client-scoped node ids, every saved
layer field and the document-level data (styles, variables, comments, images…) as synced
@@ -602,6 +605,7 @@ Carried over from the ROADMAP's "Shipped so far" (2026-10-10). The test count th
| Date | Change | Summary |
|---|---|---|
| 2026-10-12 | minor | Comments and version history behaviour suite written from the public documentation (15 tests, about 80 table rows plus stepwise checks; 4 tests failed before the fixes) and its fixes: in a live session, threads made in the session couldn't be replied to, edited, reacted to, resolved, moved, deleted or opened (their ids, from their creator's id space, were refused as out of range); restoring a version brought back that version's comments, losing newer threads and replies (comments now stay, those on layers the version lacks staying where they were); restoring now keeps the replaced design in the history as an autosave first, unless a version of it was just saved or restored; giving an autosave a title makes it a named version (it could be dropped to make room); merging a branch adds the main file as it was and then a `Merged “<branch>”` version to its history. Pinned where the documentation is silent: pins go to the innermost frame under them, copies, duplicates and duplicated pages come without comments, replying reopens a resolved thread, versions stay with whoever saved them in a live session (a shared history needs accounts). Left: a branch's own version history, comparing two versions. Comments, versions, find, misc 85%/60% → 85%/62%, 2–5 h → 2–4 h; mainstream weekly areas 71.0% → 71.1%; percentages unchanged at this rounding; full parity ~306–595 h → ~306–594 h |
| 2026-10-11 | minor | Canvas navigation, rulers, guides, layout grids, outline mode and measuring behaviour suite written from the public documentation (18 tests, about 120 table rows and checks) and its fixes: the pixel grid shows from 400% (it waited for 800%); guides belong to the page or a top-level frame (a guide dropped over a nested frame goes to the frame holding it, and a frame moved into another keeps its guides but they stop showing, snapping and measuring); a guide can be selected, deleted with Delete, nudged with the arrows and removed from the context menu (`guide.select`, `guide.remove` without an index); Alt-dragging a guide drops a copy and holding Alt while dragging one measures to the nearest edges in the frame it crosses; columns and rows count Auto (as many fixed-size ones as fit); layout grids don't show or snap on a rotated frame; in outline mode shapes are clicked on their outlines, reaching layers behind. Left: outline mode's Include hidden layers and Include object bounds. Canvas & navigation 97%/72% → 98%/74%, 2–5 h → 1–4 h; feature breadth (~80%), ready for real work (~49%), core editor (~68%), essentials (~57%) and mainstream (~46%) unchanged at this rounding; full parity ~320–615 h → ~319–614 h |
| 2026-10-11 | minor | Export and inspect behaviour suite written from the public documentation (139 cases in 19 tests; 47 failed before the fixes) and its fixes: an export covers what the layer paints, so a drop shadow adds room only where it falls, strokes on boxes and ellipses reach their real width (they added up to four times as much), hidden layers take no room and a mask group exports the mask's area; a slice exports everything under it; slashes in layer names export into folders; Copy as PNG copies the whole selection. Added: the export settings' contents only and include bounding box, and for SVG outline text (off writes `<text>`), unique id attributes and simplified strokes (stroke attributes where exact); Inspect colour formats (hex, RGB, CSS, HSL, HSB), CSS in rem, a Blend row, positions measured from the frame around a layer (groups aren't frames), CSS for rotation, blend modes, gradient directions and kinds, text alignment, case and decoration; icons and images in the asset list (`file.exportLayers {assets}`). Import/export 80%/50% → 82%/53%; Dev Mode 90%/64% → 93%/70%; file formats 55% → 56%; mainstream weekly areas 68.1% → 68.4%; feature breadth (~80%), ready for real work (~49%), essentials (~57%), mainstream (~46%) and full parity hours unchanged at this rounding |
| 2026-10-11 | minor | `.fig` import's tail (gap 1): vectors open as editable vector networks (points, curved segments, filled areas with their winding, per-point corner radius and handle mirroring, end caps from the end points), falling back to outlines when the network is missing or damaged; sticky notes, shapes with text, connectors, tables, code blocks, slides and similar layers import as the closest frames, text layers and vectors with a warning instead of being dropped; set-variable, set-variable-mode and conditional prototype actions come across. New parsers fuzzed on fixtures generated in code. File formats 55% → 58%, 8–15 h → 5–10 h; import/export breadth 80% → 82%, ready 50% → 54%; feature and area totals and ready for real work (~49%) unchanged; beta ~173–310 h → ~170–305 h; full parity ~321–618 h → ~318–613 h |