Follows the procedure in MANUAL_TESTING.md. Spec source:
workspace/panels/artboards.yaml,
workspace/dialogs/artboard_options.yaml,
workspace/dialogs/rearrange_artboards.yaml (phase 2, not yet created).
Design doc: transcripts/ARTBOARDS.md.
Primary platform for manual runs: Flask (jas_flask), then each native app. Propagation order per CLAUDE.md is Flask → Rust → Swift → OCaml → Python; all five are now feature-complete for phase-1 scope (data model, panel, dialog, canvas rendering, ALIGN_TO_ARTBOARD). Session P parity covers per-app walkthroughs.
This suite was defined before implementation per the test-first rule
in CLAUDE.md. Automated coverage landed alongside each port (see
Automation coverage below); the remaining gap is live manual
walkthroughs in each native app — sessions A–O per port, tracked in
Session P.
Last reviewed: 2026-04-21
- ART-900 [deferred: ARTBOARDS.md §Phase-1 deferrals — Artboard Tool] No canvas-side create / click-to-activate / drag-to-move / drag-to-resize. Users interact with artboards only through the panel in phase 1.
- ART-901 [deferred: ARTBOARDS.md §Phase-1 deferrals — Convert to
Artboards] Menu and context-menu entries present but grayed with
Coming soontooltip. - ART-902 [deferred: ARTBOARDS.md §Phase-1 deferrals — Rearrange
Dialogue] Menu entry
Rearrange…and footerREARRANGE_BUTTONgrayed withComing soontooltip. Blue-dot accent on the footer button begins firing on the first list change; since the Dialogue never opens in phase 1, the dot stays lit. - ART-903 [deferred: ARTBOARDS.md §Canvas appearance —
update_while_dragging] Toggle persists through save/load but has no observable effect (no canvas artboard drag exists yet). - ART-904 [deferred: ARTBOARDS.md §Canvas appearance —
video_ruler_pixel_aspect_ratio] Value persists and round-trips through the Dialogue; no non-square-pixel distortion applied to canvas rendering. - ART-905 [deferred: ARTBOARDS.md §Printing] All print-related
behavior. Fill-as-page-background, per-artboard display toggles being
screen-only, and LAYERS.md
LAYER_PRINTinteraction are pinned in the spec but not implemented.
Last synced: 2026-04-21
Python (shared interpreter) —
workspace_interpreter/tests/test_artboards_effects.py
(115 tests). Full phase-1 data-layer coverage:
color_or_transparentschema type coercion (5).- At-least-one-artboard invariant + load-time repair (6).
- StateStore load-repair contract (3).
- Artboard id generation (4): 8-char base36, deterministic seed.
next_artboard_namerule (6): empty list, skip used, fill gaps, ignore custom names, case-sensitive pattern, non-dict entries.- StateStore
create_artboardmethod (6): append, overrides, name fallback, collision retry. doc.create_artboardeffect (3): append,as:binding, overrides.- Snapshot preserves ids (2).
- Active-document view surface (6): artboards with derived
number, options, next-name, current_artboard_id, panel-selection ids. - Default-seeded fixture contract (2).
- StateStore artboard helpers: find_by_id, delete_by_id, set_artboard_field, duplicate_artboard (7).
doc.delete_artboard_by_id+doc.duplicate_artboard+doc.set_artboard_field+doc.set_artboard_options_field+doc.move_artboards_up/downeffects (6).current_artboardfield in view (3).- Action dispatch against real workspace/actions.yaml:
- New Artboard (4): silent create, size inheritance, placement rule, snapshot count, rearrange_dirty flip.
- Delete Artboards (4): selected, multi-delete, clears selection, snapshot.
- Duplicate Artboards (1).
- Rename flow (4): begin, confirm, cancel, single snapshot.
- Panel-select modifier=none (2), select_all (1).
- Reset panel (1).
- Reorder swap-skip-selected rule (10): middle row, top/bottom no-ops, contiguous block, discontiguous {1,3,5} producing [1,3,2,5,4], all-selected no-op, empty selection, non-existent id, Move Down symmetric with {1,3} → [2,1,4,3,5].
- Move actions (3): snapshot, symmetry, rearrange_dirty.
- Panel-selection tracks id across reorder (1, ART-107).
- Anchor-offset builtins (5): center = size/2, top_left = 0, bottom_right = full size, cross-axis cases.
- Artboard Options Dialogue (7): open populates dialog, pulls global options, confirm writes all fields, single undo, closes dialog, reference-point transforms display (ART-199), top_left anchor shows raw.
- Delete-from-dialog + blue-dot + phase-1 deferrals (14).
Python — jas_flask/tests/test_artboards_panel.py (23 tests).
Structural + integration coverage of the panel yaml:
- Panel spec loads with correct summary and renders.
- State block carries the five phase-1 fields.
- Menu contains all 10 entries with correct enabled_when
predicates (Convert/Rearrange deferred as
"false"). - Row template has three cells + selection-background bind via
mem(ab.id, active_document.artboards_panel_selection_ids). - Footer has five buttons in the specified order, with invariant-respecting Delete disablement and always-enabled New.
- Keyboard shortcuts: Delete/Backspace/F2/Enter/Meta+A/Alt+Arrows.
- Panel renders inside a dock.
- Row context_menu has the 5 expected entries; root and list containers have no context_menu (empty-area no-menu rule).
- Theming contract: no hardcoded hex colors outside of preset comparators.
- Reset Panel menu entry wired to
reset_artboards_panel.
Rust — jas_dioxus/src/interpreter/renderer.rs (~10 artboard-
specific test functions) + geometry roundtrip fixtures. Data
model serialization (byte-for-byte against Flask via
geometry/test_json.rs), the seven doc-effect handlers (new /
delete / duplicate / set-field / set-options-field / move-up /
move-down), the canonical {1,3,5} → [1,3,2,5,4] swap-skip-
selected case, apply_artboard_override per-field sweep, and
reference-point builtins (anchor_offset_x/y). Canvas layers
(canvas/render.rs) lean on the shared roundtrip fixtures for
data integrity; pixel output is manual-verified (Session G).
Swift — JasSwift/Tests/Interpreter/ArtboardActionTests.swift
(~28 tests). Mirrors Rust coverage with Swift idioms. Also covers
the three Phase F follow-ups landed on the artboards-panel branch:
render-time dialog outer scope (buildDialogEvalContext merges
panel / active_document under dialog / param), store → SwiftUI
overlay bridge (yamlDialogStateFromStore round-trip), dialog-body
widget action dispatch (artboard_options_confirm field writes +
close-dialog sync; delete_artboard_from_dialog removes and
closes). Full suite: 1283 Swift tests pass, no regressions.
OCaml — jas_ocaml/test/panels/panel_menu_test.ml. Panel-menu
structure test verifies the Artboards panel_menu returns the
expected labels (New / Duplicate / Delete / Rename / Delete Empty /
Convert / Options / Rearrange / Reset / Close). Core effect-handler
coverage rides on the shared
workspace_interpreter/tests/test_artboards_effects.py fixtures
(the OCaml actions pipeline runs the same compiled
workspace/actions.yaml). Cairo canvas helpers (Z-layers 2–8) land
with the port but aren't unit-tested — they're manual-verified in
Session G per port.
Python native (jas/) —
jas/panels/panel_menu_test.py (+9 artboard effect tests),
jas/panels/active_document_view_test.py (+4 sync tests),
jas/panels/align_apply_test.py (+3 ALIGN-to-artboard tests),
jas/canvas/canvas_test.py (+9 canvas draw smoke tests),
jas/document/artboard_test.py (14 unit tests). Full phase
B–G coverage: platform handlers mutate model.document.artboards
via dataclasses.replace; canvas paintEvent renders all seven
Z-layers; ALIGN references current artboard bounds with
selection-bounds fallback. Full suite: 1336 pass, no regressions.
Manual-suite items still requiring live verification:
- Canvas rendering visuals across ports (Session G, H-170-172, F-107): native apps each have their own renderer; automated smoke passes guarantee no-crash, not pixel-correct.
- Cross-app parity walkthroughs (Session P): sessions A–O pass individually against each app. Not yet executed interactively.
- Live Artboard-Tool and Rearrange Dialogue behaviors (ART-900, ART-902, ART-904, ART-905) — tracked in Known broken.
Unless a session or test says otherwise:
- Launch the primary app (
jas_flaskfor sessions A–O; per-app for P). - Open the default workspace with a fresh document. The default fixture
contains exactly one artboard:
Artboard 1, top-left(0, 0),612 × 792 pt, transparent fill, all display toggles off, freshid. - Open the Artboards Panel via Window → Artboards (or the default layout's docked location).
- Appearance: Dark (
workspace/appearances/).
Tests that need a richer fixture build it inline (New Artboard repeated;
Rectangle tool draws shapes; Object → Group) or state the delta on a
Setup: line.
- P0 — existential. If this fails, the panel is broken. Crash, layout collapse, complete non-function. 5-minute smoke confidence.
- P1 — core. Control does its primary job (click / drag / enter / select / toggle).
- P2 — edge & polish. Bounds, keyboard-only paths, focus / tab order, appearance variants, hit-target precision, invariant enforcement.
| Session | Topic | Est. | IDs |
|---|---|---|---|
| A | Smoke & lifecycle | ~5m | 001–009 |
| B | Panel row rendering + hit targets | ~6m | 010–029 |
| C | New / Delete / Duplicate | ~8m | 030–059 |
| D | Rename flow | ~5m | 060–079 |
| E | Delete Empty Artboards | ~5m | 080–099 |
| F | Reordering (drag / buttons / keyboard) | ~8m | 100–129 |
| G | Canvas rendering | ~10m | 130–169 |
| H | Fade overlay + global toggles | ~5m | 170–189 |
| I | Artboard Options Dialogue | ~15m | 190–239 |
| J | Menu + right-click context menu | ~6m | 240–269 |
| K | Keyboard shortcuts + Tab order | ~5m | 270–289 |
| L | At-least-one invariant | ~5m | 290–309 |
| M | Coordinates + reference-point widget | ~5m | 310–329 |
| N | Phase-1 deferrals (grayed verification) | ~4m | 330–349 |
| O | Appearance theming | ~3m | 350–369 |
| P | Cross-app parity | ~10m | 400–449 |
Full pass: ~105 min. A gates the rest; otherwise sessions stand alone.
If any P0 here fails, stop and flag.
-
ART-001 [unwired] Panel opens via Window menu. Do: Window → Artboards. Expect: Artboards Panel appears in dock or floating; default "Artboard 1" row is visible; no console error. — last: —
-
ART-002 [unwired] All panel sections render without collapse. Do: Visually scan the open panel. Expect: Row body with at least one row; footer button row shows five buttons (Rearrange left-cluster; Move Up / Move Down / New / Delete right-cluster). No overlapping controls, no truncated names. — last: —
-
ART-003 [unwired] Panel collapses and re-expands. Do: Click the panel header to collapse; click again to expand. Expect: Content hides / reveals; header stays visible; no crash. — last: —
-
ART-004 [unwired] Panel closes via context menu / X button. Do: Right-click panel header → Close, or click the close affordance. Expect: Panel disappears; Window → Artboards reopens it. — last: —
-
ART-005 [unwired] Panel floats out of the dock. Do: Drag the panel header out of the dock. Expect: Becomes a floating window; controls remain interactive; returns to dock on drag back. — last: —
-
ART-006 [unwired] Default document has exactly one Artboard 1. Setup: Fresh document. Expect: Row body shows one row with
ARTBOARD_NUMBER = 1andARTBOARD_NAME = "Artboard 1". Canvas shows one white-bordered rectangle labeled1 Artboard 1. — last: —
P0
- ART-010 [unwired] Each row renders three cells in order.
Setup: Default Artboard 1.
Do: Inspect the row.
Expect:
ARTBOARD_NUMBER(narrow, 1-wide col),ARTBOARD_NAME(wide, 10-wide col),ARTBOARD_OPTIONS_BUTTON(narrow, 1-wide col). No truncation at panel default width. — last: —
P1
-
ART-011 [unwired] Hovering a row paints the theme hover tint. Do: Mouse over a row. Expect: Background tint appears; leaves on mouse-out. Panel selection background, if any, is preserved. — last: —
-
ART-012 [unwired] Click on
ARTBOARD_NAMEpanel-selects the row. Setup: 3 artboards, none panel-selected. Do: Click the name cell of row 2. Expect: Row 2 gains the selection background; rows 1 and 3 do not. — last: — -
ART-013 [unwired] Click on
ARTBOARD_NUMBERmakes that row the sole panel-selected row. Setup: 3 artboards, rows 1 and 3 panel-selected. Do: Click the number cell of row 2. Expect: Row 2 is panel-selected; rows 1 and 3 are no longer selected. Same effect as a plain row click, but the hit target is the number cell specifically. — last: — -
ART-014 [unwired] Click on
ARTBOARD_OPTIONS_BUTTONopens the Dialogue for that row regardless of selection. Setup: 3 artboards, only row 3 panel-selected. Do: Click the options button on row 2. Expect: Artboard Options Dialogue opens for row 2. Panel-selection is unchanged (row 3 still selected after Cancel). — last: —
P2
-
ART-015 [unwired] Long names truncate with ellipsis. Setup: Rename
Artboard 1to a 120-char name. Expect: The name cell shows the start of the name followed by…; hover tooltip shows the full name. — last: — -
ART-016 [unwired] Number column stays 1..N with no gaps after a delete. Setup: 5 artboards. Do: Delete artboard at position 3. Expect: Column shows
1, 2, 3, 4immediately — no1, 2, _, 4, 5transient; the previous position 4 becomes position 3, previous position 5 becomes position 4. — last: —
P0
-
ART-030 [unwired]
New Artboardbutton creates silently. Setup: Fresh document (1 artboard). Do: Click theNEW_ARTBOARD_BUTTONin the footer. Expect: A second row appears at the top of the list (above row 1); no Dialogue opens; canvas shows a new artboard offset by(20, 20)pt from the prior top-left; name is"Artboard 2". — last: — -
ART-031 [unwired]
New Artboardinherits size from topmost existing artboard. Setup: Resize Artboard 1 to 400 × 300 pt via Dialogue. Do: New Artboard. Expect: The new artboard is 400 × 300 pt, not Letter. — last: — -
ART-032 [unwired]
Delete Artboardsvia trash footer button. Setup: 3 artboards, row 2 panel-selected. Do: ClickDELETE_ARTBOARD_BUTTON. Expect: Row 2 is removed; list showsArtboard 1andArtboard 3, now at positions 1 and 2; canvas redraws to show two remaining artboards. — last: —
P1
-
ART-033 [unwired]
Duplicate Artboardscopies the source. Setup: 2 artboards, row 1 panel-selected. Do: Panel menu → Duplicate Artboards. Expect: A new row appears; the duplicate has a fresh"Artboard N"name (not"Artboard 1 copy"); its bounds are offset by(20, 20)pt from the source. — last: — -
ART-034 [unwired] Duplicate copies contained elements. Setup: Draw a red rectangle fully within Artboard 1. Do: Panel-select Artboard 1; Duplicate Artboards. Expect: A duplicate rectangle appears fully within the duplicated artboard, offset by
(20, 20)pt from the original. — last: — -
ART-035 [unwired] Duplicate skips elements partially outside. Setup: Rectangle straddles Artboard 1's right edge. Do: Duplicate Artboard 1. Expect: The straddling rectangle is not duplicated. Only fully contained elements are copied. — last: —
-
ART-036 [unwired] Delete via Delete / Backspace key. Setup: Row 2 panel-selected, panel focused. Do: Press Delete. Expect: Same result as the trash button. — last: —
-
ART-037 [unwired] Undo restores a deleted artboard at its prior position with its prior id. Setup: 3 artboards, note the name and position of the row 2 artboard. Do: Delete it; Cmd-Z. Expect: Row 2 reappears at position 2 with the original name. Panel-selection state restored. — last: —
P2
-
ART-038 [unwired] New Artboard default placement with no panel-selection. Setup: Fresh document; no panel-selection. Do: New Artboard. Expect: The new artboard appears at the end of the list (position 2), not above nothing. Offset
(20, 20)pt from the default artboard's top-left. — last: — -
ART-039 [unwired] Fresh name skips used numbers. Setup: Rename Artboard 1 to "Cover"; create a New Artboard; delete Artboard 2; rename Artboard 1 back to "Artboard 1"; now create New Artboard. Expect: The new artboard is named
"Artboard 2"(smallest unused N is 2, since "Artboard 1" is now taken). — last: —
P0
- ART-060 [unwired] Click-and-wait on the name cell enters
inline rename.
Setup: Row 1 panel-selected.
Do: Click
ARTBOARD_NAME; hold ~500ms. Expect: Inline text field replaces the cell; the prior name is pre-selected. — last: —
P1
-
ART-061 [unwired] F2 enters rename on a single selection. Setup: Row 1 panel-selected, panel focused. Do: Press F2. Expect: Same rename mode as ART-060. — last: —
-
ART-062 [unwired] Enter commits; Escape cancels. Setup: In rename mode with buffer
"Cover". Do: Press Enter. Expect: Name column now shows"Cover". Repeat with Escape: prior name restored. — last: — -
ART-063 [unwired] Empty rename reverts silently. Setup: In rename mode; clear the buffer; press Enter. Expect: Prior name restored; no error dialog or toast. — last: —
-
ART-064 [unwired] Whitespace-only rename reverts silently. Setup: In rename mode; type
" "; press Enter. Expect: Prior name restored. — last: — -
ART-065 [unwired] Trim on commit. Setup: Rename to
" Cover "; press Enter. Expect: Stored and displayed name is"Cover"(no surrounding whitespace). — last: —
P2
-
ART-066 [unwired] Rename menu entry enabled only on single selection. Setup: Rows 1 and 2 panel-selected. Expect: Panel menu
Renameis grayed. — last: — -
ART-067 [unwired] 256-char truncation. Setup: Paste a 400-char string into the rename field; press Enter. Expect: Stored name is exactly 256 characters. — last: —
-
ART-068 [unwired] Duplicate names allowed. Setup: Rename row 1 to
"Cover"; rename row 2 also to"Cover". Expect: Both rows show"Cover". Number column distinguishes them. — last: —
P1
-
ART-080 [unwired] Sweeps all empty artboards in one undo op. Setup: 4 artboards. Place a shape so it intersects only artboards 1 and 3. Artboards 2 and 4 are empty. Do: Panel menu → Delete Empty Artboards. Expect: Artboards 2 and 4 removed in one op. List shows two rows (prior 1 and prior 3), now at positions 1 and 2. Cmd-Z restores both. — last: —
-
ART-081 [unwired] Preserves position 1 when all are empty. Setup: 3 artboards; no elements. Do: Delete Empty Artboards. Expect: Only the artboard at position 1 remains. List length == 1. — last: —
-
ART-082 [unwired] Menu entry grayed when no empty artboards. Setup: Every artboard intersects some element. Expect: Panel menu
Delete Empty Artboardsis grayed. — last: — -
ART-083 [unwired] Menu entry grayed at N=1 when the lone artboard is empty. Setup: Fresh document (1 empty artboard). Expect:
Delete Empty Artboardsis grayed (preserving position 1 means no deletion would occur). — last: —
P2
-
ART-084 [unwired] Hidden elements count as non-empty. Setup: Rectangle inside Artboard 1; set the containing layer to invisible. Do: Delete Empty Artboards. Expect: Artboard 1 is not deleted. The hidden element still counts. — last: —
-
ART-085 [unwired] Locked elements count as non-empty. Setup: Rectangle inside Artboard 1; lock the element. Do: Delete Empty Artboards. Expect: Artboard 1 is not deleted. — last: —
-
ART-086 [unwired] Intersect, not contain. Setup: Rectangle partially overlapping Artboard 2's edge but mostly outside. Do: Delete Empty Artboards. Expect: Artboard 2 is not deleted — any intersection counts. — last: —
P1
-
ART-100 [unwired] Drag row 3 above row 1. Setup: 5 artboards. Do: Drag row 3 above row 1, drop. Expect: List order is now
[3, 1, 2, 4, 5]; number column renumbers to1..5; the dragged artboard now shows asARTBOARD_NUMBER = 1. — last: — -
ART-101 [unwired] Horizontal insertion line during drag. Setup: 3 artboards. Do: Start dragging row 1; hover between rows 2 and 3 without dropping. Expect: A horizontal line appears between rows 2 and 3; no row commitment until drop. — last: —
-
ART-102 [unwired] Move Up button moves a contiguous selection. Setup: 5 artboards; rows 3 and 4 panel-selected. Do: Click
MOVE_UP_BUTTON. Expect: List order now[1, 3, 4, 2, 5]. — last: — -
ART-103 [unwired] Move Up with discontiguous selection uses swap-skip-selected rule. Setup: 5 artboards; rows 1, 3, 5 panel-selected. Do: Move Up. Expect: List order now
[1, 3, 2, 5, 4]. Row 1 stays (already at top); row 3 swaps with row 2; row 5 swaps with row 4. — last: — -
ART-104 [unwired] Move Down is symmetric. Setup: 5 artboards; rows 1, 3 panel-selected. Do: Move Down. Expect: List order now
[2, 1, 4, 3, 5]. Row 1 swaps with row 2; row 3 swaps with row 4. — last: — -
ART-105 [unwired] Option+Up / Option+Down keyboard parity. Setup: Same as ART-102. Do: Press Option+Up. Expect: Same result as Move Up button. — last: —
-
ART-106 [unwired] Move Up button disabled at top. Setup: Row 1 panel-selected. Expect:
MOVE_UP_BUTTONgrayed. — last: — -
ART-107 [unwired] Panel-selection follows the moved artboard. Setup: 5 artboards; row 3 panel-selected. Do: Move Up twice. Expect: The panel-selected artboard is now at position 1, and the selection background is visibly on position 1 — the selection tracked by
id, not by index. — last: —
P2
- ART-108 [unwired] Single reorder is one undo op. Setup: Post-reorder from ART-100. Do: Cmd-Z once. Expect: Entire reorder reverts in one step (not per-swap). — last: —
P0
-
ART-130 [unwired] Default artboard paints a white-bordered rectangle on gray canvas. Setup: Fresh document. Expect: A rectangle with a 1px screen-space dark border; fill is canvas gray (transparent default, canvas shows through). — last: —
-
ART-131 [unwired] Label
N Nameappears above the top-left. Expect:1 Artboard 1visible just above the top-left corner, left-aligned, screen-pixel size. — last: —
P1
-
ART-132 [unwired] Transparent fill shows canvas gray. Setup: Fill set to Transparent. Expect: No paint inside the border; canvas gray visible. — last: —
-
ART-133 [unwired] White fill paints the rectangle. Setup: Fill set to White. Expect: Rectangle is solid white; canvas gray no longer visible inside. — last: —
-
ART-134 [unwired] Arbitrary color fill paints the rectangle. Setup: Fill set via Custom… color picker to
#FFCC00. Expect: Rectangle paints solid#FFCC00. — last: — -
ART-135 [unwired] Accent border on panel-selected. Setup: 2 artboards. Panel-select row 2. Expect: Row 2's canvas artboard shows a second border (2px outside the 1px default, theme accent color; total visual thickness 3px). Row 1 shows only the default 1px border. — last: —
-
ART-136 [unwired] Accent border tracks panel-selection changes. Setup: 2 artboards. Do: Panel-select row 1; then row 2; then Cmd-click row 1 to extend; then click row 1 alone. Expect: Accent border moves and extends accordingly. — last: —
-
ART-137 [unwired] Overlapping artboards: later fill wins. Setup: Artboard 2 overlaps Artboard 1 and has fill
#FF0000; Artboard 1 has white fill. Expect: In the overlap region, red is visible (Artboard 2 is later in the list, so paints over Artboard 1). — last: —
P2
-
ART-138 [unwired] Show Center Mark. Setup: Enable
show_center_markon Artboard 1. Expect: A small cross appears at the geometric center; screen- pixel size, theme muted-foreground. — last: — -
ART-139 [unwired] Show Cross Hairs. Setup: Enable
show_cross_hairs. Expect: A horizontal line at vertical-center and a vertical line at horizontal-center, each spanning artboard bounds. — last: — -
ART-140 [unwired] Show Video Safe Areas. Setup: Enable
show_video_safe_areas. Expect: Two nested rectangles centered on the artboard at 90% and 80% of width/height, theme muted-foreground. — last: — -
ART-141 [unwired] Video Pixel Aspect Ratio persists but has no visual effect. Setup: Dialogue, set Video Ruler Pixel Aspect Ratio to 2.0. Expect: Value is stored and reappears on reopen. Canvas render is unchanged (phase-1 deferral ART-904). — last: —
-
ART-142 [unwired] Labels may overlap when artboards are close. Setup: Two artboards with near-touching top edges. Expect: Both labels render; they may overlap each other; no collision avoidance applied. — last: —
-
ART-143 [unwired] Border is zoom-independent. Setup: Zoom from 25% to 400%. Expect: Border thickness stays 1px screen-space at every zoom. — last: —
-
ART-144 [unwired] Label is zoom-independent. Expect: Label text size is constant across zooms; only its position relative to the artboard scales. — last: —
P1
-
ART-170 [unwired] Fade overlay on (default) dims elements outside artboards. Setup: Rectangle entirely outside any artboard; Fade Region On. Expect: The rectangle renders at ~50% opacity; canvas gray beneath it is unchanged. — last: —
-
ART-171 [unwired] Fade off restores full opacity. Setup: Dialogue, uncheck
FADE_REGION_CHECKBOX, OK. Expect: The off-artboard rectangle now renders at full opacity. — last: — -
ART-172 [unwired] Fade is global — affects all artboards. Setup: Open the Dialogue for Artboard 2, uncheck Fade Region, OK. Expect: Fade is also off for Artboard 1 (single document flag, not per-artboard). — last: —
-
ART-173 [unwired] Update While Dragging persists but is no-op in phase 1. Setup: Toggle
UPDATE_WHILE_DRAGGING_CHECKBOX; OK; reopen Dialogue. Expect: Checkbox state preserved. No observable canvas effect (ART-903). — last: —
P2
- ART-174 [unwired] Update-while-dragging disabled when fade is
off.
Setup: Uncheck Fade Region.
Expect:
UPDATE_WHILE_DRAGGING_CHECKBOXbecomes disabled (grayed), preserving any prior checked state for when Fade Region is re-enabled. — last: —
P0
-
ART-190 [unwired] Dialogue opens via row button. Do: Click
ARTBOARD_OPTIONS_BUTTONon row 1. Expect: Dialogue opens with Name pre-selected; all fields show current artboard values. — last: — -
ART-191 [unwired] Dialogue opens via panel menu → Artboard Options…. Setup: Row 2 panel-selected. Expect: Dialogue opens for row 2 (topmost panel-selected). — last: —
P1
-
ART-192 [unwired] Name commit on OK. Do: Type
"Cover"into Name; OK. Expect: Row 1's name is now"Cover"in the panel and on the canvas label. — last: — -
ART-193 [unwired] Preset sets Width and Height only. Setup: Dialogue open for an artboard at non-default position. Do: Pick
A4preset; OK. Expect: Width = 595.28, Height = 841.89. X and Y unchanged. — last: — -
ART-194 [unwired] Custom appears when W/H doesn't match any preset. Setup: Width 500, Height 500. Expect: Preset dropdown shows
Custom(non-selectable). — last: — -
ART-195 [unwired] Width / Height direct edit. Do: Edit Width to 800; OK. Expect: Canvas artboard is 800 pt wide. Reference-point anchor stays fixed on screen. — last: —
-
ART-196 [unwired] Chain-link proportional resize. Do: Engage
CHAIN_LINK_BUTTON; edit Width; observe Height. Expect: Height scales to maintain the ratio captured at engage. Engaging, editing, disengaging, and re-engaging captures a fresh ratio each time. — last: — -
ART-197 [unwired] Chain-link resets on Dialogue re-open. Do: Engage chain; OK. Reopen Dialogue. Expect: Chain is off (default state; session-only). — last: —
-
ART-198 [unwired] Reference-point default is center and persists across Dialogue opens. Setup: Default artboard at (0,0,612,792). Expect: First Dialogue open shows
X: 306, Y: 396(center anchor). Change anchor to top-left; OK. Reopen Dialogue on a different artboard; top-left anchor is preselected. — last: — -
ART-199 [unwired] Reference-point widget changes X/Y display, not storage. Setup: Dialogue for artboard at
(x=0, y=0, w=612, h=792). Do: Change anchor from center to top-left. Expect: X/Y fields now show0, 0. OK. Reopen: with anchor still top-left, shows0, 0. Canvas artboard has not moved. — last: — -
ART-200 [unwired] Orientation toggle swaps W/H around anchor. Setup: Dialogue, anchor = center. W=612, H=792. X=306, Y=396. Do: Click the landscape icon. Expect: W becomes 792, H becomes 612. X stays 306, Y stays 396. Canvas: artboard rotates around its center. — last: —
-
ART-201 [unwired] Fill dropdown → White paints white. Do: Fill dropdown → White; OK. Expect: Canvas artboard fills white; swatch indicator shows white. — last: —
-
ART-202 [unwired] Fill dropdown → Custom… opens color picker. Do: Fill dropdown → Custom…. Expect: Free-color picker opens; chosen color becomes fill; swatch indicator updates. — last: —
-
ART-203 [unwired] Fill → Transparent drops the fill. Do: Fill → Transparent; OK. Expect: Canvas shows gray through the border; swatch indicator shows the transparent red-slash. — last: —
-
ART-204 [unwired] Display toggles map 1:1 to fields. Do: Toggle each display checkbox; OK. Reopen Dialogue. Expect: Each state persisted. — last: —
-
ART-205 [unwired] Artboards count info reflects current N. Setup: 4 artboards. Expect: Dialogue info section shows
Artboards: 4. — last: — -
ART-206 [unwired] Delete button deletes this artboard and closes Dialogue. Setup: 3 artboards; Dialogue open for row 2. Do: Click Delete. Expect: Dialogue closes; list shows 2 rows (prior 1 and prior 3); row 2's artboard is gone. — last: —
-
ART-207 [unwired] Cancel discards all edits. Do: Change Name, Width, Fill; Cancel. Expect: No document changes; panel and canvas unchanged. — last: —
-
ART-208 [unwired] OK commits as a single undo op. Do: Change 5 fields; OK; Cmd-Z. Expect: All 5 changes revert in one undo step. — last: —
P2
-
ART-209 [unwired] Name empty-on-OK reverts. Do: Clear Name; OK. Expect: Name field silently reverts to the prior name on OK; Dialogue commits other changes. — last: —
-
ART-210 [unwired] Min Width/Height is 1. Do: Try Width 0; OK. Expect: Value clamps to 1, or OK is blocked with a validation indicator. Either is acceptable; behavior is consistent across ports. — last: —
-
ART-211 [unwired] Delete button grayed at N=1. Setup: Fresh document; open Dialogue for Artboard 1. Expect: Delete button is grayed; tooltip
At least one artboard must remain.— last: —
P0
- ART-240 [unwired] Panel hamburger menu opens with all 10 entries (plus separators). Expect: New Artboard, Duplicate Artboards, Delete Artboards, Rename, ───, Delete Empty Artboards, ───, Convert to Artboards, Artboard Options…, Rearrange…, ───, Reset Panel. Convert and Rearrange grayed; Reset Panel always enabled. — last: —
P1
-
ART-241 [unwired] Right-click a non-selected row replaces panel-selection. Setup: Row 1 panel-selected. Do: Right-click row 2. Expect: Panel-selection becomes just row 2; context menu opens. — last: —
-
ART-242 [unwired] Right-click an already-selected row preserves the selection. Setup: Rows 1, 2, 3 panel-selected. Do: Right-click row 2. Expect: Rows 1, 2, 3 stay selected; context menu opens. — last: —
-
ART-243 [unwired] Context menu entries mirror panel menu. Expect: Artboard Options…, Rename, Duplicate Artboards, Delete Artboards, ───, Convert to Artboards (grayed). Enable rules match panel-menu counterparts. — last: —
-
ART-244 [unwired] Right-click empty panel area opens nothing. Setup: Click below the last row. Do: Right-click in the empty area. Expect: No menu appears. — last: —
P2
-
ART-245 [unwired] Cmd-held right-click does not toggle. Setup: Rows 1, 2 panel-selected. Do: Cmd-right-click row 1. Expect: Rows 1, 2 stay selected (not
{2}alone); context menu opens. — last: — -
ART-246 [unwired] Reset Panel leaves document data unchanged. Setup: Rename an artboard; scroll panel. Do: Panel menu → Reset Panel. Expect: Panel scroll returns to top; column widths reset if they were changed; artboard names and data unchanged. — last: —
P1
-
ART-270 [unwired] Up / Down moves focus one row. Setup: 4 artboards; panel focused; row 1 focused. Do: Press Down. Expect: Focus on row 2; panel-selection is just row 2. — last: —
-
ART-271 [unwired] Shift+Up/Down extends range selection. Setup: Row 2 panel-selected (anchor). Do: Press Shift+Down twice. Expect: Rows 2, 3, 4 all panel-selected; anchor still row 2. — last: —
-
ART-272 [unwired] Cmd+A selects all artboards. Expect: Every row gains panel-selection background. — last: —
-
ART-273 [unwired] Escape during rename cancels. Setup: In inline rename mode. Do: Escape. Expect: Prior name restored; rename field closes. — last: —
-
ART-274 [unwired] Escape outside rename is no-op. Setup: 3 rows panel-selected. Do: Escape. Expect: Selection unchanged; no state visible state change. — last: —
P2
-
ART-275 [unwired] Tab enters panel at first row. Setup: Focus outside the panel. Do: Tab into the panel. Expect: Focus lands on the first (or most-recently-focused) row. — last: —
-
ART-276 [unwired] Tab order continues through footer buttons. Setup: Row focused. Do: Tab. Expect: Focus steps through
REARRANGE_BUTTON,MOVE_UP_BUTTON,MOVE_DOWN_BUTTON,NEW_ARTBOARD_BUTTON,DELETE_ARTBOARD_BUTTONin order, then leaves the panel. — last: — -
ART-277 [unwired] Tab does not step between rows. Setup: Row 1 focused. Do: Tab. Expect: Focus moves to the first footer button, not row 2. (Up/Down is the row navigator.) — last: —
P1
-
ART-290 [unwired] Delete Artboards grayed when selection spans all. Setup: 2 artboards; Cmd+A. Expect:
Delete Artboardsmenu entry grayed;DELETE_ARTBOARD_BUTTONgrayed; tooltipAt least one artboard must remain.— last: — -
ART-291 [unwired] Delete key no-op when selection spans all. Setup: Same as ART-290. Do: Press Delete. Expect: No deletion; no beep chaos; state unchanged. — last: —
-
ART-292 [unwired] Dialogue Delete button grayed at N=1. Setup: Fresh document; Dialogue open. Expect: Delete button grayed; tooltip present. — last: —
-
ART-293 [unwired] Empty artboards file loads with default inserted. Setup: Load a YAML with
artboards: []. Expect: Document opens with exactly one defaultArtboard 1at origin. App log containsDocument had no artboards; inserted default.— last: — -
ART-294 [unwired] Missing artboards key loads same as empty. Setup: Load a YAML with no
artboards:key at all. Expect: Same as ART-293. — last: —
P2
- ART-295 [unwired] Can't delete past 1 via partial deletes.
Setup: 3 artboards.
Do: Delete all three one by one (the last delete should refuse).
Expect: After two deletes, the third
DELETE_ARTBOARD_BUTTONis grayed; one artboard remains. — last: —
P1
-
ART-310 [unwired] Default anchor center reports
(306, 396). Setup: Default document; Dialogue open for Artboard 1. Expect: X=306, Y=396 with center anchor selected. — last: — -
ART-311 [unwired] Top-left anchor reports
(0, 0). Setup: Same artboard. Do: Click top-left anchor on the reference-point widget. Expect: X/Y fields update to0, 0without any document change. — last: — -
ART-312 [unwired] Edit X under center anchor moves the artboard. Setup: Anchor = center; X = 306. Do: Change X to 500; OK. Expect: Artboard's top-left becomes
500 - 306 = 194. Canvas artboard moves right by 194 pt. — last: — -
ART-313 [unwired] Y-down convention: Y=50 moves the artboard down, not up. Setup: Anchor = top-left; Y = 0. Do: Change Y to 50; OK. Expect: Artboard moves downward by 50 pt on canvas (toward the bottom of the screen). — last: —
P2
-
ART-314 [unwired] Anchor preference persists across Dialogue opens but not across document save/load. Do: Change anchor; OK; reopen Dialogue on a different artboard. Expect: Same anchor preselected. Close app; reopen; behavior may reset to center (it's a panel preference, not a document field — implementation may or may not persist it across sessions; either is acceptable, but consistent across ports). — last: —
-
ART-315 [unwired] Anchor preference is not per-document. Setup: Change anchor; open a different document in a new tab/ window if supported. Expect: The other document's Dialogue shows the same anchor preference. — last: —
These tests exist specifically to confirm deferred features stay deferred and display the expected affordances.
P2
-
ART-330 [unwired]
Convert to Artboardsgrayed in panel menu. Setup: Draw a rectangle; select it as element-selection. Expect: Panel menuConvert to Artboardsgrayed with tooltipComing soon. — last: — -
ART-331 [unwired]
Convert to Artboardsgrayed in context menu. Expect: Same grayed state and tooltip. — last: — -
ART-332 [unwired]
Rearrange…menu entry grayed. Setup: 2 artboards. Expect: Panel menuRearrange…grayed with tooltipComing soon. — last: — -
ART-333 [unwired]
REARRANGE_BUTTONgrayed. Expect: Footer Rearrange button grayed with tooltipComing soon. — last: — -
ART-334 [unwired] Blue-dot accent appears on first list change. Setup: 1 artboard; note the footer Rearrange button. Do: New Artboard (first change). Expect: Blue dot accent appears on
REARRANGE_BUTTON. Because the Dialogue never opens in phase 1, the dot remains lit for the rest of the session (ART-902). — last: — -
ART-335 [unwired] Artboard Tool does not exist yet. Setup: Scan the toolbar / tools panel. Expect: No Artboard Tool entry. Click-to-move / drag-to-resize on canvas artboards does nothing (ART-900). — last: —
-
ART-336 [unwired] Print menu items or shortcuts do nothing artboard-specific. Expect: Any print-related UI is absent or no-op; the spec's print semantics are forward-reference only (ART-905). — last: —
P2
-
ART-350 [unwired] Dark appearance: panel readable. Setup: Appearance → Dark. Expect: Row text, button glyphs, and borders are visible against the dark panel background; no low-contrast surprises. — last: —
-
ART-351 [unwired] Medium Gray appearance: panel readable. Expect: Same visibility. — last: —
-
ART-352 [unwired] Light appearance: panel readable. Expect: Same visibility. — last: —
-
ART-353 [unwired] Canvas artboard border visible across all appearances. Expect: 1px border readable on Dark/Medium/Light canvas gray. — last: —
-
ART-354 [unwired] Accent border color tracks theme. Expect: Panel-selected artboard's accent border uses the current appearance's accent, not a hardcoded color. — last: —
All five apps are feature-complete for phase-1 scope. These manual walkthroughs execute sessions A–O interactively in each app; the automated suite per port already covers the data / effect / canvas layers (see Automation coverage).
P1
-
ART-400 [unwired] Flask parity pass. Run Sessions A–O inline in the Flask app. Every P0/P1 item passes; P2 items documented where they fail. — last: —
-
ART-410 [unwired] Rust (jas_dioxus) parity pass. Implementation complete (phases A–G). Canvas renders all 7 artboard Z-layers; Artboard Options Dialogue opens via
open_artboard_optionsand commits on OK. — last: — -
ART-420 [unwired] Swift (JasSwift) parity pass. Implementation complete (phases A–G + 3 Phase F follow-ups: render-time dialog outer scope, store→overlay bridge, dialog- body button dispatch). Artboard Options Dialogue is end-to-end functional: menu → overlay shown, populated values, OK commits all fields + dismisses, Cancel dismisses, Delete removes and dismisses. — last: —
-
ART-430 [unwired] OCaml (jas_ocaml) parity pass. Implementation complete (phases A–G). Cairo canvas draws the seven Z-layers; reference-point transforms resolve against panel + active_document outer scope. — last: —
-
ART-440 [unwired] Python (jas) parity pass. Implementation complete (phases A–G). Qt paintEvent threads all nine layers (bg → fills → elements → fade → borders → accent → labels → marks → selection → tool). ALIGN_TO_ARTBOARD references current artboard bounds with selection-bounds fallback when the document has no artboards. — last: —
P2
-
ART-441 [unwired] YAML round-trip across apps. Save a multi-artboard document in one app; open in each of the other four. Expect: Identical panel state, canvas rendering, and Dialogue values everywhere. Stable
ids preserved; derivednumbers identical; no fields lost or reformatted. Note: 32 cross-language JSON roundtrip fixtures already pass byte-for-byte at the automated layer (cross_language_test.py) — this manual item verifies the user-visible equivalence on top of that contract. — last: — -
ART-442 [unwired] At-least-one invariant enforced in every app. Run ART-290 through ART-295 in each app. Expect: Same gray-out behavior; same load-time repair; same log line on malformed load. — last: —