From 575748f079f485f670b2816d208b6e2d991ad08e Mon Sep 17 00:00:00 2001 From: dev Date: Wed, 22 Apr 2026 00:23:05 +0200 Subject: [PATCH] =?UTF-8?q?morfo:=20permutation=20runner=20v2=20=E2=80=94?= =?UTF-8?q?=20URL-driven=20state=20seeds=20+=20RTL=20variant?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit v1 shipped click-based state cycles. v2 adds URL-seeded initial state so the runner can reach any state the component exposes without walking a click sequence, and runs every instrumented demo TWICE in CI (LTR + RTL) to catch direction-specific regressions like the slider thumb transform that landed this week. ## New test-route infrastructure - `src/routes/test/soma/_perms.svelte.ts` — parses `?perm.X=Y` query params into a typed `Perms` record (naive coercion: `'true'` → boolean, digits → number, else string). Exposed via `Perms.getOr({})` context. Underscore prefix so SvelteKit does not route it. - `+layout.svelte` — parses perms once at mount, sets context, honours `?perm.dir=rtl` and `?perm.locale=en` by routing through `App.setDir` / `App.setLocale` so the existing control strip stays in sync. ## Demo opt-in Three demos seed initial state from URL params (v1 + v2 combined): - `dialog` — `?perm.open=true` lands open. - `tabs` — `?perm.value=tab-2` lands on that tab. - `toolbar` — `?perm.format=bold,italic` + `?perm.align=center` preselect toggles. ## Runner extension `scripts/permutation-check.ts` now runs each instrumented demo under a matrix of URL variants (currently `ltr` + `rtl`), validates morfo at the URL-seeded state BEFORE any clicks (logged as `[initial seed]`), then runs the v1 click cycle. Output format updated to show per-variant blocks. Result: 3 instrumented demos × 2 variants = 22 step validations per CI run. RTL seeding reproduces the specific state machine the slider `translate(50%, -50%)` bug needed to fail — had v2 been in place that day, the regression would have fired before shipping. ## Docs `src/uix/morfo/PERMUTATION_RUNNER.md` gains the v2 section (layout plumbing, demo opt-in, URL variant table, `[initial seed]` step semantics) and marks v1 + v2 as shipped 2026-04-22. v3 (morfo-inferred per-component axis matrix) and v4 (MutationObserver ordering for Sema) remain on the roadmap. ## Verification - `npm run check`: 0 errors in soma/morfo/test-route scope. - `npm run smoke`: 65/65 routes. - `npm run morfo:check`: 66/66 morfos. - `npm run perm:check`: 3/3 demos · 22 steps across 2 variants. Co-Authored-By: Claude Opus 4.7 (1M context) --- scripts/permutation-check.ts | 216 +++++++++++++++------- src/routes/test/soma/+layout.svelte | 21 +++ src/routes/test/soma/_perms.svelte.ts | 69 +++++++ src/routes/test/soma/dialog/+page.svelte | 7 +- src/routes/test/soma/tabs/+page.svelte | 5 +- src/routes/test/soma/toolbar/+page.svelte | 12 +- src/uix/morfo/PERMUTATION_RUNNER.md | 52 +++++- 7 files changed, 309 insertions(+), 73 deletions(-) create mode 100644 src/routes/test/soma/_perms.svelte.ts diff --git a/scripts/permutation-check.ts b/scripts/permutation-check.ts index 2fd1c8396..d2e85313a 100644 --- a/scripts/permutation-check.ts +++ b/scripts/permutation-check.ts @@ -218,6 +218,25 @@ async function executeStep(page: Page, step: PermStep): Promise { await page.waitForTimeout(step.settle); } +// ── URL variant matrix (v2) ───────────────────────────────────────────────── + +/** + * Universal URL variants applied to every instrumented demo. The layout at + * `src/routes/test/soma/+layout.svelte` reads `?perm.dir` / `?perm.locale` + * and re-seeds the presentation context; the runner validates the full + * click cycle under each variant so RTL-only reactivity bugs (e.g. the + * slider thumb-transform regression) fail cleanly instead of shipping. + * + * Per-component axes (component-specific state like `?perm.open=true`, + * `?perm.variant=alertdialog`, `?perm.value=tab-2`) are declared by the + * demo itself via ` diff --git a/src/uix/morfo/PERMUTATION_RUNNER.md b/src/uix/morfo/PERMUTATION_RUNNER.md index a0af81c31..876b28227 100644 --- a/src/uix/morfo/PERMUTATION_RUNNER.md +++ b/src/uix/morfo/PERMUTATION_RUNNER.md @@ -133,14 +133,58 @@ Demos without `data-perm-step` are skipped with a `SKIP` line (they haven't opte --- +## v2 — URL-driven state injection + +v1 covers "click through a state sequence and validate after each step." v2 adds **URL-seeded initial state**: the demo reads `?perm.X=Y` params from the URL and uses them as initial `$state` values. Every instrumented demo now runs TWICE in CI — once under `ltr` (no params), once under `rtl` (`?perm.dir=rtl`). Universal axes are run across every demo; per-component axes are just defaults in the demo's script. + +### Layout plumbing + +`src/routes/test/soma/+layout.svelte` parses `?perm.*` params once at mount, exposes them via a context at `src/routes/test/soma/_perms.svelte.ts`, and also honours `?perm.dir=ltr|rtl` and `?perm.locale=es|en` by routing through the existing `App.setDir` / `App.setLocale` path (so the control strip stays in sync). + +### Demo opt-in + +Read the perms and use them as **initial** state (not live-bound — the user can still click through transitions after landing): + +```svelte + +``` + +Type coercion is naive: `'true'` / `'false'` → boolean, bare digits → number, everything else stays a string. Cast to the component's actual union at the read site. + +### URL variants + +The runner runs each instrumented demo under a matrix of base URL variants defined in `scripts/permutation-check.ts`: + +| Variant | URL suffix | +|---------|------------| +| `ltr` | `` (no params) | +| `rtl` | `?perm.dir=rtl` | + +Per-component axes (`?perm.open=true`, `?perm.variant=alertdialog`, `?perm.value=tab-2`) are NOT enumerated by the runner yet — they're just defaults the demo honours when the URL provides them. Adding them to the matrix is a v3 task (the runner would read the morfo's `states` + `data.values` to generate the cartesian product). + +### `[initial seed]` step + +At each URL variant, the runner validates morfo BEFORE running any click step. That validation appears in the log as `[initial seed]` and catches morfo drift that exists at the URL-seeded state — exactly the gap a click-only cycle can't reach. + +--- + ## Roadmap -- **v1 (current)** — click-based state transitions, morfo re-validation after each step. -- **v2** — URL-param-driven state injection (`?perm=open,dir=rtl,disabled`) so headless permutations don't need a click sequence. -- **v3** — derive the permutation set automatically from the morfo's `states` and `data` enum values; no per-demo instrumentation needed for the baseline cycles. +- **v1 (shipped 2026-04-22)** — click-based state transitions, morfo re-validation after each step. +- **v2 (shipped 2026-04-22)** — URL-seeded initial state, universal axes (`dir`, `locale`), `[initial seed]` validation step before clicks. Demo layout reads `?perm.*` params, demos seed initial `$state` from them. +- **v3** — derive the per-component axis matrix automatically from the morfo's `states` and `data.values`. No per-demo instrumentation needed for the baseline cycles; the runner generates `?perm.X=Y` URLs from the morfo itself. - **v4** — integrate with `MutationObserver` to validate `data-last-action` / `data-state` ordering for Sema. -The convention (`data-perm-step` / `data-perm-mode`) is forward-compatible: v2+ infrastructure adds alternative drivers without invalidating v1 annotations. +The convention (`data-perm-step` / `data-perm-mode` / `perm.X=Y`) is forward-compatible: v3+ infrastructure adds automation without invalidating v1/v2 annotations. ---