Skip to content

spec: Phase 30 — the mobile surface - #233

Merged
vicmaster merged 7 commits into
masterfrom
phase-30-spec
Oct 31, 2026
Merged

vicmaster merged 7 commits into
masterfrom
phase-30-spec

Conversation

@vicmaster

Copy link
Copy Markdown
Owner

Planning artifact for Phase 30 (v2.4), the mobile surface. No code: docs/specs/PHASE-30-SPEC.md plus the VISION entry.

The thesis: framesmith treats mobile as a screen size, not a surface. The mobile attempt built one iOS screen on v2.2.0 and got 100/100 and READY TO PRESENT without a single mobile check running, because the touch-target rule only looks at form controls and the screen had none. This phase gives a canvas a declared type (web or mobile) and builds what a surface needs: rules that judge a phone, the vocabulary to build one, and starting points.

Slices

A. Untangle the declarations. Genre and preset share one field today, so apply_preset silently overwrites a genre. Genre gets its own field, stored canvases keep their score through a legacy read, and data becomes the canonical purpose genre with dashboard as its alias.
B. The type axis. canvas_create({ type: "mobile" }) gives a 390×844 artboard whose root reserves the safe-area insets. A new canvas_set_type tool declares the type on an existing canvas. A ruleset table keyed by type, genre and preset composes by union and can turn rules on, not only relax cliché tells. Every evaluation reports which rules ran.
C. The mobile ruleset. Tap targets below 44px are an error on every tappable primitive. Content may not sit in the safe areas or under a pinned bar. There is a type floor. A phone-width canvas that never declared a type must declare one. Stress learns the new primitives.
D. Vocabulary. fixed and sticky positioning, plus seven primitives: status-bar, home-indicator, nav-bar, tab-bar, button, list-row, sheet.
E. Starting points. A structure now separates the screen kind (anatomy) from its per-type layout (realisation). Six mobile realisations ship, named <anatomy>-mobile, and the pattern gate covers them.
F. The viewer. Thumbnails at the artboard's real proportions, and a device frame with a safe-area overlay.
G. Acceptance. The attempt screen is rebuilt from a mobile starting point and must reach CLEAN with every tap target a primitive, in fewer nodes than the 93 it took by hand.

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 type never changes what renders (C10). It changes which rules run, the generator's defaults, the structures offered and the viewer frame, but nothing about the pixels. So the insets live on the root node as safeArea, and button heights are 32 / 44 / 52 on every type. The cost is that size: "sm" fails the 44px rule on a phone by design. The alternative, sizes that depend on the type, would let a screenshot change without versionHash moving, which breaks what a CI verify means.
  2. An undeclared phone-width canvas blocks until declared (C11). The attempt was built exactly that way, with width: 390 and no type. A responsive web page designed at 390 pays one canvas_set_type("web") call.
  3. Hand-built tap targets are reported, not blocked (C5). Blocking would need a way for a frame to say it is decorative, which is the tappable flag the surface model rejected. So the gate covers primitives fully and names hand-built candidates as advisories. The mobile starting points are what make primitives the default path.
  4. material stays both a preset and a genre (C3). Its relaxation is keyed to the preset. It stays accepted as a genre because the init gotchas recommend genre: "material" for editors and admin forms today, and dropping it would change those agents' verdicts.
  5. A per-call genre now keeps the stamped preset's relaxation. Today an explicit genre: "commerce" on a material-preset canvas drops the material relaxation. After this phase it keeps it, because the material style is still on the canvas. This is a deliberate behaviour change, described in FR-A2.
  6. No static PNG thumbnails. PR Viewer performance: the gallery was quadratic in the size of the whole store #208 deferred them to this work, but artboard sizing alone fixes what mobile needs, and no measurement shows a performance need.

The main risks, plainly

  • The type is still on the honour system. An agent can explicitly declare web on a phone app screen to avoid the mobile errors. The spec closes the silent path and makes the declaration visible in every result and in the viewer, but it does not prevent the dodge. Preventing it would need width-based inference, which would make a responsive web page designed at 390 impossible to express.
  • Several device constants come from secondary sources. Apple's HIG pages could not be fetched, so the insets (47 / 34), bar heights and list-row heights are marked medium confidence. Slice B re-checks them before they land in code.
  • Moving the genre field touches stored data. The legacy read keeps every stored score. The visible change is that a preset name stored by the old canvas_set_genre now reads as a preset, so the genre report's active value goes to null.

How the spec was checked

Before freezing, one verifier tried to make each pass/fail rule give a wrong verdict. It found 22 problems, and about ten of them were real wrong verdicts. The spec was revised around them, including the render rule in decision 1. After freezing, three more checks ran. A citation check confirmed 54 of 60 code references and the remaining six were corrected. A conformance check covered the agreed surface model and the gap catalog. A reader given only the spec confirmed it is buildable from the document alone. Three narrower rounds then verified the fixes. The last four edits, in commit c5abe13, were reviewed only by the author.

@vicmaster
vicmaster merged commit 5e9e7da into master Oct 31, 2026
3 checks passed
@vicmaster
vicmaster deleted the phase-30-spec branch October 31, 2026 19:37
@vicmaster vicmaster mentioned this pull request Nov 2, 2026
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