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

101 lines
6 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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.