Directed
Every element of a chart, made twice or three times over: once by Claude Code working from the dataset alone, then again with a named skill or a real tool loop run on top. Same model, same data, same module contract. The method is the only thing that changes.
14 of 48 rows built · 34 of 107 cells · every cell generated by actually running its method, hashed at generation, and re-rendered on every build · 6 published as null results.
Method: what contaminates this comparison, and every cell that shipped without moving its lever →
- Claude default
- The dataset and the module contract, nothing else. Three runs; the median by SVG element count ships.
- With a skill
- A named skill invoked explicitly, one run, on the default arm's own output.
- With a tool
- A real loop — screenshot compare-and-fix, an image model, a charting library. One run.
- refine · from-scratch
- Each row declares one. refine runs the directed arms on the default arm's output, so the lever is the only difference; from-scratch generates each arm independently, because there the lever is the generation decision.
Type
3 of 5 rows · 8 cellsTypeface, size hierarchy, weight, figures, casing.
Typeface
refine fixturetable12 Type scale and size hierarchy
refine fixturetable12 Tabular vs proportional figures
refine fixturetable12 clean subagent, naive prompt dataviz Premise not engaged. dataviz cut 24 numeric annotations down to 2 without ever reaching for font-variant-numeric, font-feature-settings, or a tabular-figure font; both arms keep the same Helvetica stack. That is a real annotation-density edit, not the tabular-vs-proportional lever this row names, which stays untested. The row was deliberately not relabelled to fit the outcome — picking the hypothesis after seeing the result is the move this project argues against. Method →
Planned in this family
- Weight and contrast 2 arms
- Casing, tracking, label wrapping 2 arms
Colour
3 of 6 rows · 8 cellsCategorical, sequential and diverging palettes; ground, accent discipline, CVD safety.
Categorical palette
refine fixturetable12 Diverging scale, spectral within poles
refine fixturetable12 Accent vs neutral discipline
refine fixturetable12 Planned in this family
- Sequential ramp 3 arms
- Light vs dark ground 2 arms
- Colour-vision-deficiency safety 3 arms
Mark
5 of 7 rows · 8 cellsWhat a datum is drawn as — glyph, gradient, halo, texture, size, overlap.
Default rect/circle vs designed custom mark
from-scratch fixturehero8 Flat fill vs one radialGradient per datum
refine fixturehero8 Glow / outer halo filter
refine fixturehero8 Pattern / texture fill
refine fixturehero8 Overplotting: opacity, jitter, ordering
refine fixturehero8 clean subagent, naive prompt dataviz Premise not engaged. dataviz recoloured every mark and thickened its stroke while leaving all 16 circles' cx/cy/r/fill-opacity byte-identical to Arm A. The cause is upstream of the skill: the hero8 baseline's eight bubbles are already disjoint (smallest clearance about 7px), so there was no overplotting available to fix. Testing this lever needs a fixture that actually overplots, not a prompt that forces an edit onto a chart that does not. Method →
/impeccable craft Premise not engaged. /impeccable craft collapsed five secondary text greys into one and changed no circle attribute at all — a typographic-hierarchy edit. Same cause as Arm B: the hero8 baseline does not overplot, so this row's premise was never available to engage on either of its treated arms. Method →
Planned in this family
- Stroke/halo separation on overlap 2 arms
- Size encoding honesty (area vs radius) 2 arms
Axis
1 of 5 rows · 2 cellsLines, ticks, gridlines, the zero baseline, and how the frame is labelled.
Gridlines: whether, how faint, which direction
refine fixturetable12 clean subagent, naive prompt /impeccable distill Premise not engaged. /impeccable distill deleted all twelve delta labels under the bars and shortened the baseline annotation from World baseline: 73.48 to World baseline, cutting the chart from 46 text elements to 34. It changed no gridline at all: the six horizontal rules keep the same positions, the same 1px weight and the same light grey, and the dashed baseline rule and the axis line are byte-identical too. Whether, how faint, which direction is the one thing this row names, and the one thing distill left alone — it read the chart's clutter as annotation density rather than as grid. Method →
Planned in this family
- Axis line presence and weight 2 arms
- Tick density and format 2 arms
- Zero-baseline and truncation honesty 2 arms
- Direct labelling vs a framed axis box 2 arms
Layout
1 of 5 rows · 2 cellsAspect ratio, margins, sort order, faceting, cartesian versus radial.
Sort order as an editorial decision
refine fixturetable12 Planned in this family
- Aspect ratio choice 2 arms
- Margins and whitespace 2 arms
- Small multiples / faceting 3 arms
- Cartesian vs radial / polar 3 arms
Annotation
5 rows planned- Generic title vs headline-as-finding 2 arms
- In-chart callouts on the marks that carry the finding 2 arms
- Leader lines: short, uncrossed, distinct from marks 2 arms
- Source and method note 2 arms
- Showing uncertainty / caveats 2 arms
Legend
2 of 3 rows · 2 cellsDetached key versus labels pinned to marks; colour bars; legend as artwork.
Detached legend vs labels pinned to marks
refine fixturetable12 Legend-as-art / hand-feel
refine fixturetable12 Planned in this family
- Continuous colour legend quality 2 arms
Motion
2 rows planned- Entrance animation 2 arms
- Transition / scroll-scrub. Must respect the known GSAP hazard: never drive one transform property with both a from() entrance and a scrub tween 2 arms
Interaction
3 rows planned- Hover / highlight behaviour 2 arms
- Tooltip content and wording 2 arms
- Keyboard, focus order, screen-reader description 2 arms
Medium
1 of 3 rows · 2 cellsSVG versus canvas, dark and light theming, the share render.
Dark / light theming of the same chart
refine fixturetable12 clean subagent, naive prompt /impeccable adapt Premise not engaged. /impeccable adapt read adapt as responsive sizing rather than as theming: it added a preserveAspectRatio attribute and an inline style that lets the chart scale fluidly with whatever container embeds it, and touched not one colour. All 41 fills and strokes are identical to Arm A in document order, the white ground included, so the shipped cell is the same light chart the baseline was. Dark versus light theming is what this row names; the skill's own adapt remit turned out to be a different kind of adaptation, and the theming lever stays untested. Method →
Planned in this family
- SVG vs canvas crispness at the same size 2 arms
- Share / OG render of the chart 2 arms
Numbers
1 of 2 rows · 2 cellsUnits, rounding, formatting and locale.
Units and rounding
refine fixturetable12 clean subagent, naive prompt dataviz Premise not engaged. dataviz replaced the entire palette, added 12 path elements and moved mark geometry — a large, real edit — but wrote every number exactly as Arm A did: same rounding, same units, same separators, so both arms probe identically on numeric-text and numeric-format. Units and rounding is the one thing this row names and the one thing the skill left alone. Method →
Planned in this family
- Number formatting and locale 2 arms
Library
2 rows planned- Preset chart library vs Observable Plot (function-mark escape hatch) vs raw D3/SVG, same brief 3 arms
- Element-anchored editing (pass the DOM id) vs vague prose. Low-expectation row, published even if the effect is nil 3 arms