Skip to content

Migrate the remaining 294 MUI X implementations to MUI X 9 in three chunks #12296

Open

Description

@MarkusNeusinger

Goal

Migrate the remaining 294 MUI X implementations of the catalogue from the MUI X 7 API to MUI X 9.16 (React 19, Material 9.5), restructure each to the adaptable-code convention, and hand them over so that the pipeline's Opus review finds no defect line, on a gemini/* branch in three chunks of 98 specs. After every hand-over Claude reviews the chunk and feeds it through the pipeline's adopt mode (render, Opus review, repair, merge) from the handed-over commit, while you continue with the next chunk. Nothing from this branch is merged directly.

Context

  • The first batch of 20 files (Migrate 20 MUI X implementations to MUI X 9 and the adaptable-code convention #12267, draft feat(muix): migrate batch 1 (20 specs) to MUI X 9 and adaptable-code convention #12275, pipeline PRs feat(muix): implement alluvial-basic #12276–feat(muix): implement scatter-annotated #12295) measured the route: every file bundled and rendered, the Opus review scored them 77–89 at first sight, and 19 of 20 went through a repair round. What sent them to repair was not the design level: a review merges without repair when it scores 80 or more, names no defect line, and has every one of the 19 technical items (VQ, SC, DQ, CQ) at its maximum (docs/workflows/overview.md, "Nothing to repair"). The first batch lost that on small things: text under 13 px inside marks, helper functions and components outside the default export, dead branches, abstract names such as "Model A", a truncated label, marks nudged off their coordinates, chrome drawn in a palette colour. The checklist under Constraints turns every one of those into a rule; it is the primary deliverable. The design and library levels (DE-01 to DE-03, LM-02) start at their defaults and are a bonus, see "Design level" under Constraints.
  • An independent review of the first batch also found 12 defects of the adaptable-code convention; they are in the checklist as well.
  • The render stack moved to MUI X 9.16 in deps(js): bump MUI X Charts to 9.16 with React 19 and Material 9.5 #12243. Of the 323 muix.tsx files, 164 no longer bundle (the @mui/x-charts/ChartContainer path is gone), 157 render differently (legend hidden prop, v7 legend position and styling, v7 axis and font-size props, removed CSS classes; 67 with a blank axis). The per-spec measurement is in the first batch's issue (gh issue view 12267 --json title,body).
  • Worked examples of the target shape on origin/main after git fetch origin: plots/area-basic/implementations/javascript/muix.tsx, plots/alluvial-basic/…, plots/hexbin-basic/…, plots/recurrence-basic/…, plots/genome-track-multi/…, plots/calibration-beer-lambert/…. Do not copy the header of gauge-basic or confusion-matrix on main: both still carry a stale second header block below line 5, a pipeline defect that is being fixed separately.
  • The rules: prompts/library/muix.md (section "MUI X v9 API — the pinned version" lists every API change; "The harness contract"; "Data block"; "When MUI X can't express the spec"; "Forbidden patterns"), prompts/adaptable-code.md (the JavaScript form: one record array as the data block, role constants, plot code that reads only the constants; the "Data shapes" section decides table, matrix, network or generated per spec), prompts/plot-generator.md and prompts/default-style-guide.md (canvas, palette, imprint, sizing in CSS px, animation off, "Ordered Categories"), and prompts/quality-criteria.md (what the review scores; read VQ-01, VQ-07, SC-01 "Variant creep", SC-02, SC-03, DQ-02, CQ-01, CQ-04, DE-03, LM-02).
  • Each spec lives in plots/<spec>/specification.md; its current implementation is plots/<spec>/implementations/javascript/muix.tsx.
  • The harness renders a file locally without credentials, from the repository root: ANYPLOT_THEME=light node automation/js-render/render.mjs plots/<spec>/implementations/javascript/muix.tsx and the same with ANYPLOT_THEME=dark. It writes plot-light.png / plot-light.html (or dark) into the current directory, not next to the file. Node 24 and the root package.json dependencies are needed (npm ci at the repository root, npx playwright install chromium); your clone has them from the first batch.
  • The canvas check: PYTHON_DOTENV_DISABLED=1 uv run python -c "from core.canvas import check_png; print(check_png('plot-light.png', 'muix'))" must report the target size for both themes (3200×1800, or 2400×2400 for a square spec).
  • Claude never pushes to your branch during this task. Its fixes for a chunk go to a separate ref, and the pipeline takes each chunk from the commit SHA you name in the hand-over, so you keep committing while a chunk runs. At the start of a later session, git status and git log origin/main..HEAD tell you where you stopped; no pull, no merge, no rebase, even when GitHub marks the draft PR as conflicting (chunks that merged to main rewrite the headers, and that conflict is expected).

Steps

  • git fetch origin, render one already migrated file in both themes to confirm the local setup still works (for example plots/hexbin-basic/implementations/javascript/muix.tsx), then git switch -c gemini/<this issue number>-muix-9-remaining origin/main.
  • Chunk 1, first ten specs: one commit per spec (feat(muix): migrate <spec> to MUI X 9): read the specification and the current file, port the API to MUI X 9, restructure to the convention, apply the checklist, render both themes, run the canvas check, look at both PNGs (axes, ticks, legend, labels and imprint visible and inside the canvas, no blank axis, no cropped bottom, text readable at thumbnail size). After the tenth spec hand over: push, open the draft PR with the table for these ten and the hand-over commit SHA, and tell the owner "chunk 1a handed over at ". This early hand-over lets Claude catch a systematic misreading before 284 more files repeat it. Continue with the rest of chunk 1 right away.
  • Chunk 1, remaining 88 specs; hand over by pushing and updating the PR body (gh api -X PATCH, see the hand-over format) with the table and the SHA; tell the owner "chunk 1 handed over at ".
  • Chunk 2, the same.
  • Chunk 3, the same.

The chunks, in order:

Chunk 1 (98 specs): alluvial-opinion-flow, arc-basic, bar-3d-categorical, bar-error, bar-pareto, bar-permutation-importance, bifurcation-basic, biplot-pca, box-basic, box-grouped, box-horizontal, box-notched, boxen-basic, bubble-basic, bubble-packed, campbell-basic, candlestick-basic, candlestick-volume, cat-box-strip, chernoff-basic, chessboard-basic, chord-basic, circlepacking-basic, circos-basic, climograph-walter-lieth, coefficient-confidence, column-stratigraphic, contour-filled, contour-map-geographic, curve-dose-response, dendrogram-basic, dendrogram-radial, diagnostic-regression-panel, dot-matrix-proportional, dumbbell-basic, energy-level-atomic, errorbar-asymmetric, errorbar-basic, facet-grid, feynman-basic, flamegraph-basic, flowmap-origin-destination, forest-basic, frontier-efficient, funnel-basic, heatmap-annotated, heatmap-basic, heatmap-chromagram, heatmap-clustered, heatmap-cohort-retention, heatmap-loss-triangle, heatmap-mandelbrot, heatmap-polar, heatmap-risk-matrix, histogram-capability, histogram-density, histogram-epidemic, histogram-kde, histogram-returns-distribution, hive-basic, icicle-basic, indicator-ichimoku, indicator-macd, indicator-rsi, lightcurve-transit, line-3d-trajectory, line-growth-percentile, line-reaction-coordinate, line-tanabe-sugano, line-training-load-pmc, logistic-regression, lollipop-basic, lollipop-grouped, ma-differential-expression, map-connection-lines, map-projections, map-route-path, marimekko-basic, mohr-circle, network-basic, network-bipartite, network-directed, network-force-directed, network-hierarchical, network-transport-static, network-weighted, ohlc-bar, parallel-basic, parallel-categories-basic, parliament-basic, piano-roll-midi, point-and-figure-basic, point-basic, polar-bar, polar-basic, polar-line, polar-scatter, probability-weibull

Chunk 2 (98 specs): qq-basic, qrcode-basic, quiver-basic, radar-basic, radar-innovation-timeline, radar-multi, raincloud-basic, renko-basic, ridgeline-basic, rug-basic, sankey-basic, scatter-3d, scatter-ashby-material, scatter-basic, scatter-complex-plane, scatter-embedding, scatter-lag, scatter-pitch-events, scatter-regression-linear, scatter-regression-lowess, scatter-regression-polynomial, scatter-shot-chart, skewt-logp-atmospheric, smith-chart-basic, sn-curve-basic, spc-xbar-r, spectrogram-basic, spectrogram-mel, spiral-timeseries, star-chart-constellation, stem-basic, stereonet-equal-area, streamline-basic, strip-basic, surface-basic, swarm-basic, ternary-basic, tree-decision, tree-phylogenetic, treemap-basic, venn-basic, venn-labeled-items, violin-box, violin-grouped-swarm, violin-split, violin-swarm, voronoi-basic, waffle-basic, waterfall-basic, windbarb-basic, windrose-basic, wireframe-3d-basic, area-cumulative-flow, area-elevation-profile, audiogram-clinical, band-basic, bar-diverging, bar-diverging-likert, bar-feature-importance, barcode-ean13, bland-altman-basic, bubble-map-geographic, bump-basic, chessboard-pieces, contour-3d, contour-basic, contour-decision-boundary, contour-density, density-basic, density-rug, ecdf-basic, elbow-curve, funnel-meta-analysis, gain-curve, heatmap-geographic, heatmap-rainflow, histogram-2d, histogram-cumulative, histogram-stepwise, indicator-bollinger, indicator-ema, indicator-sma, line-annotated-events, line-arrhenius, line-basic, line-confidence, line-multi, line-pca-variance-cumulative, line-stock-comparison, line-stress-strain, line-timeseries-rolling, pdp-basic, phase-diagram-pt, psychrometric-basic, pyramid-basic, range-interval, residual-plot, roc-curve

Chunk 3 (98 specs): root-locus-basic, scatter-categorical, scatter-connected-temporal, scatter-constellation-diagram, scatter-hr-diagram, scatter-map-geographic, shap-summary, silhouette-basic, span-basic, spectrum-basic, spectrum-nmr, spirometry-flow-volume, step-basic, titration-curve, waveform-audio, andrews-curves, area-mountain-panorama, area-stacked-confidence, area-stacked-percent, bar-grouped, bar-heart-rate-zones, bar-horizontal, bar-spine, bar-stacked, bar-stacked-labeled, bar-stacked-percent, bar-tornado-sensitivity, barcode-code128, bode-basic, bullet-basic, burndown-sprint, cartogram-area-distortion, count-basic, crossword-basic, curve-bias-variance-tradeoff, curve-oc, curve-power-duration, dashboard-metrics-tiles, depth-order-book, donut-basic, donut-nested, drawdown-basic, ecg-twelve-lead, eye-diagram-basic, frequency-polygon-basic, gantt-basic, gantt-dependencies, heatmap-adjacency, heatmap-calendar, heatmap-correlation, heatmap-stripes-climate, hexbin-map-geographic, histogram-basic, histogram-overlapping, histogram-stacked, ice-basic, kagi-basic, ks-test-comparison, lift-curve, line-cycle-seasonal, line-filled, line-impurity-comparison, line-load-duration, line-markers, line-parametric, line-retention-cohort, line-timeseries, line-win-probability, line-yield-curve, manhattan-gwas, map-tilegrid, maze-circular, maze-printable, mosaic-categorical, nyquist-basic, pictogram-basic, pp-basic, precision-recall, rose-basic, scatter-marginal, scatter-matrix, scatter-text, shap-waterfall, slope-basic, sparkline-basic, stock-event-flags, streamgraph-basic, subplot-grid, subplot-mosaic, sudoku-basic, sunburst-basic, swimmer-clinical-timeline, timeline-basic, timeseries-decomposition, timeseries-forecast-uncertainty, upset-basic, volcano-basic, wordcloud-basic

Constraints

  • Change only the 294 files plots/<spec>/implementations/javascript/muix.tsx named above. No metadata files, no PNGs or HTML committed (rm -f plot-light.png plot-dark.png plot-light.html plot-dark.html in the repository root before each commit; stage only the one .tsx file; git status must show nothing else), no other plots, no prompts, no workflows, no changelog fragment (catalogue-only changes are exempt).
  • Header. Exactly one header block of four // lines at the top of the file (// anyplot.ai, the spec line, the Library: line, the Quality: line); keep its Quality: and Updated:/Created: values as they are, the pipeline rewrites them. For a square spec the directive //# anyplot-orientation: square goes on line 5, directly below the header, not on line 1: the pipeline's header writer replaces the leading // block and stops at a //# line, and a directive on line 1 makes it prepend a second header (the stale-header defect you see on 131 of these files). Remove every stale second header block. A landscape spec needs no directive.
  • Frozen after hand-over. Once a chunk is handed over, its files are frozen on your branch: the pipeline took them from that SHA. A later fix for one of them is a note in the next table, never a commit.
  • Keep each file self-contained the way the harness contract requires: a default-exported React component, no manual mount, no network, no animation (skipAnimation on every chart component and on ChartsContainer), sizes from window.ANYPLOT_SIZE, colours from window.ANYPLOT_TOKENS (t.palette, t.ink, t.inkSoft, t.pageBg, t.elevatedBg, t.grid, t.amber, t.seq, t.div; there is no t.muted).
  • The scenario and the chart type of the old file stay: same plot type, same story, same data unless it violates the convention, the spec, or the checklist. This is a migration plus a defect sweep, not a redesign.
  • Data shape. The spec's ## Data roles decide the shape per "Data shapes" in prompts/adaptable-code.md: table (the default), matrix, or generated. For a generated spec (boards, puzzles, encoded text, fractals, formula surfaces, diagrams such as Feynman or energy levels) the block holds named parameters, with no record array and no column constants, and checklist items 4, 5, 7, 9 and 10 do not apply. Geometry a chart needs beside its data (a coastline polygon, a board layout) is a named constant table in the Data block, not rows of data. Networks are not a MUI X shape (prompts/library/muix.md, "Forbidden patterns").
  • Design level. DE-01 to DE-03 and LM-02 start at their defaults and the review raises them only for evidence beyond what the spec and the library prompt require. Within that: a subtitle or caption line that states a scenario or scale fact computed from the data (n, span, unit, a fit statistic), never an interpretation; quiet chrome (t.grid, t.inkSoft) under clear data; realistic, specific names in the data. On a spec whose id ends in -basic: no focal element, no highlighted mark or band, no added reference line, fit, callout or annotation layer, no colour channel the spec does not offer (prompts/quality-criteria.md, SC-01 "Variant creep"; one such addition costs more than any DE credit it could earn). On every other spec: one focal element only where the Notes do not already prescribe a hierarchy, chosen by a rule over the data and applied through weight or contrast while the palette order stays canonical. ChartsLegend and ChartsGrid are the baseline, not mastery; LM credit comes only from a feature beyond the requirements (a colorMap on the axis that carries a quantity, hook-driven layers in data coordinates, a second y axis with position: "right"). Never replace a working custom layer by a component that cannot draw the same thing.
  • Checklist. Every file you hand over satisfies all of these:
    1. Nothing spec-compliant from the old file is dropped: every reference line, annotation, identity line, curve type and multi-series legend entry that the spec requires or offers as optional is still there, or the table says why v9 cannot draw it. On a -basic spec, drop the unrequested trend lines, mean lines, callouts and single-series legends the old file added, and note each removal in the table.
    2. No axis limit, padding, bin size, radius or grid step is typed in data units below the Data block; they come from the data extent, through a unit-free share in // Constants where padding or a bin count is needed. A threshold the plot type or the spec defines (RSI 30 and 70, a target the spec names) and a fixed mathematical domain (0–1, 0–100, 0–360) are typed constants in // Constants.
    3. No column name, sample category, label text or unit string is typed in plot code (a callout says only what its rule guarantees; the unit comes from the column constant or the formatter). An encoding note that is true for any data stays.
    4. Every record cell is a scalar: no arrays or objects inside a record (two thresholds are two columns).
    5. No role column duplicates another; a class or category list is derived from every column that carries it (both label columns of a confusion matrix), in order of first appearance.
    6. t.palette[i] by group position in order of first appearance, never % t.palette.length. Where a semantic map fixes a colour (loss red, a status), the remaining groups take the unused palette positions in order. Ordered categories (Likert, sentiment, risk levels) take a ramp (t.seq, t.div) per "Ordered Categories" in the style guide.
    7. A series label comes from the rows that make up the series, not from the position of a value in a Set.
    8. A statistic's constant is looked up from the data's size, never fixed for the sample (a t quantile for df = n − 2 from a table, not 2.571).
    9. Every declared column constant is read by the plot code; a numeric or date x is sorted before lines are drawn, a categorical x keeps its order of appearance.
    10. Which renderer, panel or band a group gets is decided by a rule over its rows, not by its position in the data, and every renderer handles an empty group.
    11. Axis extents are padded so reference elements and outermost marks sit inside the drawing area.
    12. Marks sit at their exact data coordinates: no collision relaxation, force pass, jitter or nudge on plotted points (labels may move, marks never). On a geographic map, px per degree of latitude equals px per degree of longitude divided by cos(mean latitude); on a geometric plot (circles, complex plane, Smith chart, Voronoi) px per unit is equal on both axes.
    13. Every text element is 14 px or larger, in-mark labels, counts and reference labels included; axis and legend text 14–16 px, title about 22 px; no label is truncated in code (slice), size the band instead. Text on a coloured mark uses a fixed ink chosen by the mark's luminance (#1A1A17 or #FAF8F1), never t.pageBg or t.ink, which flip with the theme while data colours do not.
    14. Non-data chrome (basemap, water, background bands, borders, separators) uses t.inkSoft, t.grid or t.elevatedBg, never a t.palette slot.
    15. No helper function or component beyond the default export and the custom layers that need a hook (useXScale, useYScale, useDrawingArea); statistics, binning and layout are flat module-level statements; axis styles set once in the xAxis/yAxis configs, not again on <ChartsXAxis />; no branch that cannot fire (a title-size branch for a fixed title).
    16. None of the v7 names remains: ChartContainer, ResponsiveChartContainer, DefaultChartsLegend, Unstable_, hidden: true inside slotProps.legend, labelStyle, padding, itemMarkWidth, itemMarkHeight, markGap, itemGap inside slotProps.legend, labelFontSize, tickFontSize, topAxis/leftAxis/bottomAxis/rightAxis, .MuiAreaElement-root, .MuiLineElement-series-*, .MuiBarElement-root, .MuiMarkElement-root, .MuiScatterElement-root, .MuiPieArc-root, lineElementClasses, areaElementClasses, barElementClasses, markElementClasses, pieArcClasses, pieArcLabelClasses.
  • Branch gemini/<this issue number>-muix-9-remaining from origin/main; a draft PR only. The draft is reviewed chunk by chunk and fed to the pipeline file by file; it is closed afterwards without a merge, so do not expect CI on it to be the acceptance.

Acceptance

For every one of the 294 files, from the repository root:

ANYPLOT_THEME=light node automation/js-render/render.mjs plots/<spec>/implementations/javascript/muix.tsx
ANYPLOT_THEME=dark  node automation/js-render/render.mjs plots/<spec>/implementations/javascript/muix.tsx
PYTHON_DOTENV_DISABLED=1 uv run python -c "from core.canvas import check_png; print(check_png('plot-light.png', 'muix'), check_png('plot-dark.png', 'muix'))"
head -5 plots/<spec>/implementations/javascript/muix.tsx
grep -nE 'ResponsiveChartContainer|[^s]ChartContainer|DefaultChartsLegend|Unstable_|hidden: *true|labelFontSize|tickFontSize|\b(top|left|bottom|right)Axis\b|MuiAreaElement-root|MuiLineElement-series-|MuiBarElement-root|MuiMarkElement-root|MuiScatterElement-root|MuiPieArc-root|lineElementClasses|areaElementClasses|barElementClasses|markElementClasses|pieArcClasses|pieArcLabelClasses|itemMarkWidth|itemMarkHeight|markGap|itemGap|t\.muted' plots/<spec>/implementations/javascript/muix.tsx

Both renders exit 0 and both canvas checks report the target size; the first five lines are one header block and, for a square spec, the directive on line 5; the grep finds nothing; the PNGs show every axis, tick label, legend and the imprint; the checklist holds for every file. The existing rules still win where they conflict with a mechanical port or with the design level: the eight-hue palette order and "never recycle colours", the 3200×1800 canvas with sizes in CSS px, the imprint text, a legend outside the SVG that reserves its own height, the -basic variant rule above, and the data shape the spec's roles decide.

Hand-over format

The PR body carries one table per hand-over, appended each time, with the hand-over commit (git rev-parse HEAD) in its heading: spec, what changed (API, convention, checklist items that needed a change), render result, anything you could not solve or had to drop. Then the sections of the gemini-task hand-over format (Summary, Plan, Test plan, Decisions, Open steps and questions). Write the body into a temp file and apply it with gh api -X PATCH repos/{owner}/{repo}/pulls/<pr> -F body=@<file> (gh pr edit fails on this repository).

Decide yourself / report back

  • Decide yourself: constant names, padding shares, how a lookup table is written, how a stale header is resolved, which v9 feature carries a custom layer, the subtitle fact per chart. Document the choices in the chunk's table.
  • Report back in the table, do not guess: a spec whose old file draws something v9 cannot express (use the documented fallback from "When MUI X can't express the spec" in the library prompt and say so); a spec whose old file contradicts its specification; a file that does not render on 9 for a reason outside the file (harness, dependency); and any checklist item you could not satisfy.

Activity

  1. added
    geminiTask for Gemini in the owner's interactive agy session (gemini-task skill)
    on Oct 23, 2026
  2. changed the title [-]Migrate the remaining 294 MUI X implementations to MUI X 9 in six chunks[/-] [+]Migrate the remaining 294 MUI X implementations to MUI X 9 in three chunks[/+] on Oct 23, 2026
  3. 176 remaining items

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    geminiTask for Gemini in the owner's interactive agy session (gemini-task skill)

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions