Skip to content

spec: Phase 31 — the desktop-app surface - #244

Merged
vicmaster merged 1 commit into
masterfrom
phase-31-spec
Nov 9, 2026
Merged

vicmaster merged 1 commit into
masterfrom
phase-31-spec

Conversation

@vicmaster

Copy link
Copy Markdown
Owner

Planning artifact for Phase 31 (v2.5), the desktop-app surface. No code: docs/specs/PHASE-31-SPEC.md plus the VISION entry.

The thesis: framesmith judges an application screen as if it were a marketing page. Run on its own viewer, version 2.4.0 scored every page's usability 100 with zero findings, though the viewer has a 17px-tall Back link and 21 click targets that are plain spans. The web hit-target rule measures only the four form controls, and imported buttons, links and tabs are plain frames. At the same time, page rules misfired on the app: the sidebar project list was read as a data table, the dense 13/14px type steps failed the scale ratio, and the projects' identity dots counted as competing accents. This phase adds a third canvas type, desktop-app, for a tool you work in (persistent chrome, panes, dense controls, a current selection), in a browser tab or a native window.

Slices

A. The type. canvas_create({ type: "desktop-app" }) gives a 1440×900 window. The type-scale ratio check gets a rule id so the desktop-app ruleset can replace it. Three corrections apply on every type: the WCAG 2.5.8 spacing exception on the 24px target floor, navigation lists that never read as tables, and identity dots that never count as accents. Evaluate and import results shrink so an agent can read them on a large screen. generate_design_system gives a 14px body plus state, focus-ring and strong-border tokens. The baseline canvases are committed as fixtures.
B. Vocabulary. A 24px button with an accessible name, plus link, text-input, nav-item, tabs, tree-row, menu-row, property-row and divider.
C. App rules. Every click target is measured. Hand-built click targets and icon-only actions without a name are reported. Each navigation group has exactly one current item. The type ladder accepts dense steps. Table rows stay consistent, truncation stays honest, and one primary button per region is advised. A canvas must declare its type when it contains app primitives.
D. Layouts. Structure resolution works for any number of types, and six desktop-app layouts ship under the existing pattern gate: workbench, list-detail, editor with inspector, browser, dashboard and settings.
E. Overlays. tooltip, popover, menu, modal, toast and drawer. The renderer lifts every overlay into one layer at the root, with a fixed stacking order by kind, so a menu opened from a sticky toolbar is never clipped.
F. Overlay rules. One modal at a time, text-only tooltips, no large tables in a modal, and overlays inside the window. Stacked toasts and error toasts are reported as advisories.
G. Element states. Hover, focus, pressed and disabled are a property on each interactive primitive, drawn from state tokens.
H. State checks. Focus rings, active indicators, disabled renders and control borders are checked against the token colors on every interactive primitive, without the agent drawing any state.
I. Acceptance. The viewer's gallery, detail page with inspector, and archive are rebuilt as canvases, with the comment-popover and delete-confirm states. Each must reach CLEAN in both modes and both themes, with every click target a primitive and each of six baseline viewer defects fixed by name.

Decisions I'd like your eyes on

Each is decided with a recommendation in the spec's Clarify section, and each could go the other way:

  1. The name is desktop-app (C1). app is ambiguous because phone screens are apps too, and desktop reads as a wide web page. The cost is an asymmetry with mobile.
  2. Element states are a property, not variant canvases (C4). The research suggested drawing each state as its own canvas. A property lets the renderer draw states from tokens, so every interactive primitive gets checked on every canvas, not only the states an agent happened to draw. Open menus, dialogs and toasts stay variant canvases, because they change what is on screen.
  3. The spacing exception warns in fast mode (C10). The exception needs real element positions, which only detailed mode has. A target below 24px therefore blocks in fast mode until a detailed run clears or confirms it. Primitives are 24px or more by design, so this lands on explicit small sizes and hand-made controls.
  4. Three corrections change web behaviour (C6). The spacing exception, navigation lists not being tables, and identity dots not being accents are wrong on every type, so they are fixed everywhere. Everything else stays behind the desktop-app ruleset.
  5. Overlays are positioned by x and y, not anchored to their trigger (C5). Anchored rendering needs CSS anchor positioning, which not every browser supports, or a layout pass before rendering. An overlay can still name its trigger, and the rules use that name.
  6. Rules whose thresholds no source validated are advisories (C9). These are row heights within 1px, one primary button per region, a 4-character truncation floor, stacked toasts and error toasts. They inform until the pattern gate or the acceptance run shows they should block.

The main risks, plainly

  • Scope. Nine slices, more than Phase 30's seven, chosen over a smaller foundation-only phase. The baseline could not test slices E to H, because the viewer's static pages never show an open menu or dialog. If the acceptance run finds an overlay or state rule misfiring on a correct design, the fix lands in the acceptance slice with its evidence.
  • Web verdicts move. On web, a button with an explicit height below 24px is measured for the first time. A form control still below 24px after its padded row changes from an error in both modes to a fast-mode warning plus a detailed-mode error. The slice A PR has to list every existing fixture whose verdict moved.
  • The output shape changes for every caller. Repeated advisories fold into one entry with a count and a list of node ids. A CI gate that counts advisories will see fewer entries. Errors and warnings are not folded, and canvas_autofix reads the unfolded list.
  • Several constants are house values. These include the 11px smallest text, the 12px prose floor, the 13px data-dense body, the 2.5 type-ratio cap, the sidebar and modal widths, and the 1.1 disabled-visibility threshold. The spec marks each one, and each lives in one place.

Verification

Three independent verifiers checked the first draft: one for code references, one for fidelity to the research and the baseline, and one that tried to break every pass/fail rule. A second round checked the rewrite. Every blocker and major issue they raised is resolved in the text.

@vicmaster
vicmaster merged commit abb35b2 into master Nov 9, 2026
3 checks passed
@vicmaster
vicmaster deleted the phase-31-spec branch November 9, 2026 17:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant