design:os · docs
Live-canvas verification checklist (owner-manual)
The one verification layer CI cannot reach: everything below needs a real Figma Desktop with the plugin loaded, because it either drives the canvas or opens an editor (FigJam / Slides) a headless test can’t. Consolidated across absorption phases #10/#13/#26/#28 so it runs in a single connected session instead of four scattered PR bodies.
Setup (once)
Figma hotloads code.js/ui.html from disk — a normal rebuild propagates to the running
plugin with no re-import. BUT manifest.json is read only at plugin load, and the
absorption phases changed it (editorType widened to ["figma","figjam","slides"]). So this
one time you must re-register so Figma picks up the widened manifest AND its new path (the
plugin moved out of the monorepo; the old dev entry points at the deleted location):
- Figma Desktop → Plugins → Development → re-import the manifest from
/Users/jang/Products/design-os-figma-plugin/plugin/manifest.json. (Only needed because the manifest itself changed — code-only changes after this hotload as usual.) - Confirm the panel opens and reads “design:os by JANG”, status shows Connected.
figma-agent statusfrom a terminal →plugin.editorType: "figma", no errors. If it still reports the old manifest (no figjam/slides), Figma didn’t pick up the re-import — remove the dev plugin entry and add it again.
A. Design file (regression — MUST be unchanged)
The absorption phases widened editorType to ["figma","figjam","slides"]. This section proves
the existing design-file path is byte-unaffected — the one real risk of the manifest change.
- ☐ Open a normal Figma Design file. Panel connects,
editorType: "figma". - ☐ Run a known-good command (e.g.
ui figma reconcile --applyon a bound file, or a smallfigma-agent exec-jsthat reads a node) — behaves exactly as before the phases. - ☐
ui.componentSet(...)/ui.slot.*still work in a design file (the reverse guard must NOT wrongly refuse here). - ☐
ui.figjam.*andui.slides.*REFUSE in the design file with an actionable message naming the editor they need (forward guard fires). - ☐ Gap-fill / sync still capture design-file edits normally (no regression from the widen).
B. FigJam (new surface — phase-03)
- ☐ Open a FigJam board. Panel connects,
figma-agent status→editorType: "figjam". - ☐
ui.figjam.sticky(...)creates a sticky;ui.figjam.connector(...),.shape,.table,.codeBlock,.sectioneach create their node; reply names what was made (no fabrication). - ☐
ui.figjam.board()reads the board;ui.figjam.connections()lists edges — an unresolved endpoint showsunresolved: true, never a dropped edge. - ☐
ui.figjam.arrange(...)with one bad id → the bad id lands inskipped[], the rest arrange. - ☐ A design-only command (
ui.componentSet,ui.slot.*) REFUSES in FigJam, naming the editor. - ☐ Make a manual edit (move a sticky) → it appears in the change feed with
nodeType: "STICKY"verbatim (honest-by-construction — never a fabricated design-file fact).
C. Slides (new surface — phase-04)
- ☐ Open a Figma Slides deck. Panel connects,
editorType: "slides". - ☐
ui.slides.list()/.grid()/.content(slideId)read the deck honestly. - ☐
ui.slides.background(slideId, color)sets the slide fill directly (no rectangle appears on the slide — it usessetFillsAsync, methodslide-fill). - ☐ The single-slide-view trap (the load-bearing correctness test): switch to single-slide
view, focus slide X, then
ui.slides.addText(targetSlide=Y, ...)→ the text lands on Y, NOT the focused slide X. (This is the silent-misattribution guard; if it lands on X, that’s a real bug to report.) - ☐
ui.slides.reorder(...)with a grid that drops or duplicates a slide → REFUSES, naming the missing/duplicate id (never silently drops a slide). - ☐
ui.slides.setTransition(...)applies;ui.slides.transition(slideId)reads it back. - ☐ Undo honesty: run an exec-js that navigates (
ui.slides.focus/viewMode) then throws →rolledBack: truecovers the CONTENT, but you are left on a different slide (navigation is not undoable — this is documented, verify the message is honest about it).
Report back
For each section: pass / fail-with-detail. Any failure in A is a regression (blocks — tell the team). Failures in B/C are new-surface bugs (file as board issues). All-pass on A + a working sticky/slide in B/C = the cross-editor absorption is live-verified.