Repository navigation
Add the mobile ruleset (Phase 30 slice C) - #236
Merged
Merged
Conversation
Pins rule ids, severities and the measurement rules the FR rows leave open, and corrects FR-C2's acceptance (Ridgeline's targets meet the floor). Records the root-render gap for slice D.
Phase 30 slice C. Six rule ids register in the ruleset table and run when on: mobile-touch-target (error), mobile-safe-area and mobile-type-floor (warnings), mobile-handbuilt-target and mobile-one-column (infos), and mobile-artboard on every type. Findings carry a rule field. Stress records the canvas type; canvas_set_type names variants left on the old type.
A spacer directly under the fixed-height root shrinks to nothing on a screen taller than its artboard; one inside the content frame keeps its height.
Stretching rows count as full width and full-height rows don't; positioned images are background; the safe-area walks cache per tree instead of copying ancestors. Docs name detailed mode, the padding formula and the fixes. Tests gain the mutation round's boundary fixtures.
A stretching row takes its host's known width, not the artboard's, and a positioned image is full-bleed only when its containing block spans the artboard. Both first fixes passed small targets.
3 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Phase 30 slice C. Slice B gave a canvas a declared type but no rule used it, so a phone screen was still judged as a web page. This PR adds the mobile ruleset: six rules that register in the ruleset table and run when the canvas type turns them on.
The rules
Every finding from these rules carries a new
rulefield naming its id. Thesurfacereport lists the ids that ran inrulesOn.mobile-touch-targetmobile-safe-areamobile-type-floormobile-handbuilt-targetmobile-one-columnmobile-artboardTouch targets. On a mobile canvas a toggle, checkbox, radio or select whose target is below 44px in either dimension is an error. A control's target extends to its row only when the row is a horizontal frame holding that one control. A row with no width stretches to its parent's width when that width is known. A lone checkbox inside a padded card is measured at its own size, because a card is not a row. Web canvases keep the 24px error and the 44px phone-width info unchanged. The slice D primitives join this rule as they land.
Safe areas. Content under the 47px status bar or the 34px home indicator warns. With
safeAreaon the root the renderer already reserves both insets, so fast mode checks only positioned content. Without it, the first and last content must clear the insets. Fast mode measures padding as the renderer draws it: padding of 32px or more scales down on a phone, so 48px renders about 13px. Detailed mode checks rendered positions and is the authority.Type floor. These warn on a phone:
fontSizeis$bodyand resolves below 16px;Long copy of twelve or more words at 13 to 15px is an info. Figures and their units do not count as words, so a metrics line stays legal at 12px.
Hand-built tap targets. A frame shaped like a tap target (one icon, or one icon plus a label of three words or fewer) whose box is below 44px is an info. It never blocks, because a frame cannot say it is decorative.
One column. Prose set side by side on a phone is an info.
Artboard. This rule runs on every type, so it can catch canvases the mobile ruleset is not on for. A mobile canvas 500px or wider warns. An undeclared canvas narrower than 500px warns until
canvas_set_typedeclares it either way. A canvas declaredwebat that width gets an info.Stress and the type
canvas_stressrecords the canvas type it ran under. The evaluate result'sstressfield gainstype, andcurrentis true only when both the version hash and the type still match. A FRAGILE run still blocks after a type change. The directive's note then names the earlier type instead of blaming an edit. On a mobile canvas thelong-textperturbation leaves strings of three characters or fewer alone, so a monogram no longer reads as a layout break. The stress engine also gained a table of primitive text props and treats runs of siblinglist-rows as lists. Both are dormant until slice D adds those node types.Smaller changes
canvas_set_typenow returnsvariantsOutOfSync, listing each state variant whose type differs from the base after the change. Variants keep the type they were created with.Disabled web rules (FR-C7)
None qualified. The original Ridgeline screen was evaluated as
mobile, and no existing check fired on a correct mobile idiom. Its remaining findings were APCA advisories, the coverage demands for its run list, and the "no component instances" advisory, which slice D resolves by counting primitives as reuse. The mobiledisablelist stays empty.Spec changes
The slice C build contract and its "As built" notes in
docs/specs/PHASE-30-SPEC.mdrecord every decision the FR rows left open. Three of them change what the spec said:safeArea. The root renders at a fixed height, so its bottom padding does not extend past overflowing content. A long screen therefore really does end under the home indicator.Until slice D lands, fast mode trusts the
safeAreareservation on long screens and only detailed mode catches that case. The docs say so where the rule is introduced.Docs
The canvas_evaluate, canvas_autofix, canvas_stress and canvas_set_type docstrings,
INSTRUCTIONS,GOTCHAS, the README and a new "The mobile ruleset" section indocs/GUIDELINES.mdcover the rules, their thresholds and fixes. They also say how to run detailed mode. The stale "no rule ids are registered yet" text is gone.test-discoverability.tsnow checks that every registered rule id and therulefield are documented.Testing
test-mobile-rules.ts(Chrome-free) covers every rule's positive, negative and boundary cases, the stress engine on mobile, the directive's type note, and the real tools over MCP stdio.test-mobile-rules-detailed.tscovers detailed-mode safe areas and the stress record's type through the real tools, including a FRAGILE run followed by a type change.mobile-artboard. Mutation testing ran 104 mutants and the surviving gaps were closed with boundary tests. A review found a cubic slowdown on deeply nested trees, now fixed: an 800-deep chain went from about 2s to about 40ms.npm run test:fullpasses (109/109), andtscis clean.