makepad-ports/plans/ROADMAP.md
andodeki bcd362ed0d Deep assessment v2 (brutal, evidence-based) + phased improvement roadmap
- makepad_ports_deep_assessment.md: architecture/design/performance/bugs/security/quality,
  scored 5.4/10 with file:line evidence; key findings: unpinned dev checkout (S1),
  commit-on-down + zero animators (D1/D2), undo deep-copies scene (P1), god-router +
  full chrome resync (A2/A3), copy-coupled UI tests (B3), test-shaped product (A4)
- plans/ROADMAP.md: Phases 0-5 mapping findings to plans 000-005 + engine hardening,
  tranche discipline per phase
2026-09-01 18:59:16 +00:00

6 KiB
Raw Permalink Blame History

Roadmap — phased improvement of the makepad-ports codebase

Companion to makepad_ports_deep_assessment.md (findings A*/D*/P*/B*/S*/Q*) and the self-contained plans 000005. Each phase ends as a tested tranche: full test matrix green, git fetch reconcile, then push. No phase starts on top of an unpushed predecessor.

Phase 0          Phase 1        Phase 2            Phase 3           Phase 4      Phase 5
Trust the build  Foundations    Interaction        Motion            Visual       Engine & test
& measure   ───► craft crate ─► correctness   ───► adoption     ───► polish  ───► hardening
(S1,S2,Q3,Q5)    (plan 000)     (plan 001, D3)     (plans 002-004)   (plan 005)   (A2,A3,P1-P5,B1-B4)

Phase 0 — Trust the build, measure the baseline (no product code changes)

The gate everything else passes through. You cannot claim 140-green while the thing under test is an unpinned branch tip (S1).

  1. Pin upstream: setup_makepad.sh checks out b41e740 explicitly (git fetch --depth 1 origin b41e740 && git checkout b41e740); git apply --check failure aborts loudly. Pin the Rust toolchain (--default-toolchain 1.98.0). (S1, S2)
  2. Coverage harness (this tranche): temp-env cargo-llvm-cov + llvm-tools-preview in /var/tmp (ephemeral, wiped with the sandbox — nothing pollutes the repo); engine tests (--lib --test integration, all three crates) and controller/UI tests (MAKEPAD=headless --test ui) instrumented; upstream makepad code and unreachable platform startup (main.rs, lib.rs registration glue) excluded via --ignore-filename-regex; summary committed to docs/coverage/COVERAGE.md; uncovered model branches get unit tests in the same tranche; artifacts (.profraw, cov target dir, tool binaries) cleaned after.
  3. CI-as-script: ci.sh = fmt check + clippy (-D warnings, allowlist documented) + the three-layer test matrix; README states it as the pre-push contract. (Q3)
  4. Token rotation on gitdab; pushes via credential helper. (S4)
  5. Vendor policy one-liner in skills/README.md: vendor/ is data, never doctrine. (S3)

Exit: pinned reproducible build, measured coverage with a committed report, ci.sh green.

Phase 1 — Foundations (plan 000)

The shared craft crate: easing/duration/color tokens on the mod object, Pressable, CraftToast, pure motion.rs (project/rubberband/settle) with unit tests. Kills the triplication channel (A1) before behavior work multiplies it further.

Exit: four crates build; tokens reachable from all apps; baseline + new units green.

Phase 2 — Interaction correctness (plan 001 + D3 minimum)

  • Press contract everywhere: feedback on down (0.96 snap-in), commit on up-if-over, tap-cancel; documented act-on-down exceptions only (koboyo drag-arming tools, scrims). Clears every HIGH in the craft audit.
  • A11y minimum riding the same migration: since every tappable becomes a Pressable, give it focusable + Enter/Space activation + a visible focus state in the same widget — one fix, forty call sites, D3 mostly closed for free.
  • New UI tests: tap-cancel per crate; keyboard activation smoke test.

Exit: grep finger_down(actions) returns only documented exceptions; matrix + new tests green.

Phase 3 — Motion adoption (plans 002, 003, 004)

Order: 002 (toast, all crates — smallest, proves the enter/exit pattern) → 003 (insurance sheet settle: projection, velocity handoff, rubber-band, multi-touch guard fixing B1, grab-mid-settle) → 004 (koboyo drawer/popovers origin-aware + animated camera-fit; fixes B4 focus-before-visible). 003 and 004 may run in parallel — disjoint crates.

Exit: zero set_visible pops for toasts/drawer/popovers; sheet settles with velocity; all restraint cases (canvas 1:1, PageFlip) untouched; matrix green.

Phase 4 — Visual & token polish (plan 005)

Hex → semantic tokens; concentric radius pass with measured paddings (closes B5); emoji → drawn icons with state recoloring; tabular figures; not .... DSL-only, zero redesign — today's rendered pixels reproduced from tokens. UI-test locators migrate from copy strings to ids as each screen is touched (B3 partial).

Exit: hex grep clean outside model-driven values; radius table in PR; matrix green.

Phase 5 — Engine & test hardening (the assessment's structural debt)

  1. Router: replace handle_actions if-chains with a dispatch table (&[(LiveId, Msg)]fn update(flow, Msg) -> Fx), one per crate; exhaustive, testable. (A2)
  2. Dirty-flag chrome: refresh_chrome takes the Fx/diff of what changed; full resync only on screen change. Prerequisite for animations not being stomped. (A3, P3)
  3. Undo rework: command-pattern deltas (or Arc<[Element]> structural snapshots) replacing 60 deep copies; property test: undo∘redo = id across random edit scripts. (P1)
  4. Hot-path shapes: precomputed lowercase search haystack (P4); sheet drag position as shader-instance offset instead of margin relayout (P2); document the linear-scan element threshold or add a grid index if koboyo is meant to scale (P5).
  5. Scroll container back into insurance + teach UI tests to scroll-to-widget, removing the 390×1280 hack. (A4)
  6. Test debt: id-based locators everywhere (B3 done); panic idioms → if let/Option combinators (B2); rename Mut/Wht/Deep to speaking names (Q2).

Exit: assessment re-scored; target ≥ 7.5 overall with Design ≥ 7.

Standing rules for every phase

  • Tranche discipline (user requirement): fetch → reconcile (remote improvements win where they're better; local reorganizations preserved; no force-push) → run the matrix → push. One tranche per phase minimum, more when a phase touches all three crates.
  • DSL landmines list (plans/README.md) applies to every executor.
  • Coverage report regenerated at the end of Phases 2, 3 and 5; deltas quoted in tranche messages.
  • The restraint list (canvas 1:1, PageFlip, wheel zoom) is load-bearing: PRs that "improve" those get rejected.