From 20355f798f3bb7dadcc1f5e8269d8128b0997d9d Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Tue, 30 Jun 2026 22:57:13 +0000 Subject: [PATCH 1/5] feat(altair): implement dumbbell-basic MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Regen from quality 89. Addressed: - Canvas size: switched to width=576/height=374 + scale_factor=4.0 + PIL padding to exact 3200×1800 (previously used width=1600/height=900/scale=3.0 producing 4800×2700 — now gate-compliant) - DE-03/LM-02: added transform_calculate diff labels (+N pts) showing gain immediately for each dumbbell — uses Altair-native transform, visible story - Title: added missing "python" language token - Style: aligned font sizes to library prompt (10/12px ticks/axis labels), fixed palette comment "Okabe-Ito" → "Imprint" --- .../implementations/python/altair.py | 71 +++++++++++++------ 1 file changed, 49 insertions(+), 22 deletions(-) diff --git a/plots/dumbbell-basic/implementations/python/altair.py b/plots/dumbbell-basic/implementations/python/altair.py index 5b47fc177d..59c6ccd7d9 100644 --- a/plots/dumbbell-basic/implementations/python/altair.py +++ b/plots/dumbbell-basic/implementations/python/altair.py @@ -1,13 +1,14 @@ -""" anyplot.ai +"""anyplot.ai dumbbell-basic: Basic Dumbbell Chart Library: altair 6.1.0 | Python 3.14.4 -Quality: 89/100 | Updated: 2026-04-26 +Quality: 89/100 | Updated: 2026-06-30 """ import os import altair as alt import pandas as pd +from PIL import Image # Theme-adaptive chrome @@ -17,7 +18,7 @@ INK = "#1A1A17" if THEME == "light" else "#F0EFE8" INK_SOFT = "#4A4A44" if THEME == "light" else "#B8B7B0" -# Okabe-Ito palette positions 1 and 2 +# Imprint palette positions 1 and 2 COLOR_BEFORE = "#009E73" COLOR_AFTER = "#C475FD" @@ -41,57 +42,68 @@ } ) data["difference"] = data["After"] - data["Before"] -data = data.sort_values("difference", ascending=True) +data = data.sort_values("difference", ascending=True).reset_index(drop=True) # Long-form data for the two dot series dots_data = pd.melt( data, id_vars=["category", "difference"], value_vars=["Before", "After"], var_name="period", value_name="score" ) -x_scale = alt.Scale(domain=[45, 90]) +title = "Employee Satisfaction · dumbbell-basic · python · altair · anyplot.ai" +n = len(title) +title_fontsize = round(16 * (67 / n)) if n > 67 else 16 + +x_scale = alt.Scale(domain=[45, 92]) y_sort = alt.EncodingSortField(field="difference", order="ascending") # Connecting lines (theme-adaptive subtle ink) lines = ( alt.Chart(data) - .mark_rule(strokeWidth=3, color=INK_SOFT, opacity=0.55) + .mark_rule(strokeWidth=3, color=INK_SOFT, opacity=0.45) .encode(y=alt.Y("category:N", sort=y_sort, title=None), x=alt.X("Before:Q", scale=x_scale), x2=alt.X2("After:Q")) ) # Dots for Before / After values dots = ( alt.Chart(dots_data) - .mark_circle(size=420, opacity=1.0, stroke=PAGE_BG, strokeWidth=2) + .mark_circle(size=350, opacity=1.0, stroke=PAGE_BG, strokeWidth=2) .encode( y=alt.Y("category:N", sort=y_sort, title=None), x=alt.X("score:Q", scale=x_scale, title="Employee Satisfaction Score (%)"), color=alt.Color( "period:N", scale=alt.Scale(domain=["Before", "After"], range=[COLOR_BEFORE, COLOR_AFTER]), - legend=alt.Legend(title="Policy Change", labelFontSize=16, titleFontSize=18), + legend=alt.Legend(title="Policy Change", labelFontSize=10, titleFontSize=12), ), tooltip=["category:N", "period:N", "score:Q"], ) ) +# Difference labels via transform_calculate — shows the gain at a glance +diff_labels = ( + alt.Chart(data) + .transform_calculate(label="'+' + toString(datum.difference) + ' pts'") + .mark_text(align="left", dx=8, fontSize=9, fontWeight="bold", clip=False) + .encode( + y=alt.Y("category:N", sort=y_sort, title=None), + x=alt.X("After:Q", scale=x_scale), + text=alt.Text("label:N"), + color=alt.value(INK_SOFT), + ) +) + chart = ( - (lines + dots) + (lines + dots + diff_labels) .properties( - width=1600, - height=900, - title=alt.Title( - "Employee Satisfaction · dumbbell-basic · altair · anyplot.ai", - fontSize=28, - color=INK, - anchor="start", - offset=20, - ), + width=576, + height=374, + title=alt.Title(title, fontSize=title_fontsize, color=INK, anchor="start", offset=16), background=PAGE_BG, ) .configure_view(fill=PAGE_BG, stroke=None) .configure_axis( - labelFontSize=18, - titleFontSize=22, + labelFontSize=10, + titleFontSize=12, domainColor=INK_SOFT, tickColor=INK_SOFT, gridColor=INK, @@ -100,8 +112,23 @@ titleColor=INK, ) .configure_title(color=INK) - .configure_legend(fillColor=ELEVATED_BG, strokeColor=INK_SOFT, labelColor=INK_SOFT, titleColor=INK, padding=12) + .configure_legend(fillColor=ELEVATED_BG, strokeColor=INK_SOFT, labelColor=INK_SOFT, titleColor=INK, padding=10) ) -chart.save(f"plot-{THEME}.png", scale_factor=3.0) +chart.save(f"plot-{THEME}.png", scale_factor=4.0) + +# Pad to exact 3200×1800 canvas (vl-convert pads outside width/height) +TW, TH = 3200, 1800 +_img = Image.open(f"plot-{THEME}.png").convert("RGB") +_w, _h = _img.size +if _w > TW or _h > TH: + raise SystemExit( + f"altair vl-convert produced {_w}×{_h}, exceeds target {TW}×{TH}. " + f"Shrink chart .properties(width=, height=) values and re-render." + ) +if _w < TW or _h < TH: + _canvas = Image.new("RGB", (TW, TH), PAGE_BG) + _canvas.paste(_img, ((TW - _w) // 2, (TH - _h) // 2)) + _canvas.save(f"plot-{THEME}.png") + chart.save(f"plot-{THEME}.html") From 19ccc7723590dd34fb377887d38a4163a9bfc8aa Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Tue, 30 Jun 2026 22:57:24 +0000 Subject: [PATCH 2/5] chore(altair): add metadata for dumbbell-basic --- .../metadata/python/altair.yaml | 247 +----------------- 1 file changed, 11 insertions(+), 236 deletions(-) diff --git a/plots/dumbbell-basic/metadata/python/altair.yaml b/plots/dumbbell-basic/metadata/python/altair.yaml index 6bcbf9b19f..f7f4206660 100644 --- a/plots/dumbbell-basic/metadata/python/altair.yaml +++ b/plots/dumbbell-basic/metadata/python/altair.yaml @@ -1,246 +1,21 @@ +# Per-library metadata for altair implementation of dumbbell-basic +# Auto-generated by impl-generate.yml + library: altair language: python specification_id: dumbbell-basic created: '2025-12-23T13:02:07Z' -updated: '2026-04-26T02:08:06Z' -generated_by: claude-opus -workflow_run: 24945139784 +updated: '2026-06-30T22:57:23Z' +generated_by: claude-sonnet +workflow_run: 28480646536 issue: 945 -python_version: 3.14.4 -library_version: 6.1.0 +language_version: 3.13.14 +library_version: 6.2.2 preview_url_light: https://storage.googleapis.com/anyplot-images/plots/dumbbell-basic/python/altair/plot-light.png preview_url_dark: https://storage.googleapis.com/anyplot-images/plots/dumbbell-basic/python/altair/plot-dark.png preview_html_light: https://storage.googleapis.com/anyplot-images/plots/dumbbell-basic/python/altair/plot-light.html preview_html_dark: https://storage.googleapis.com/anyplot-images/plots/dumbbell-basic/python/altair/plot-dark.html -quality_score: 89 +quality_score: null review: - strengths: - - 'Perfect visual quality across both themes: all font sizes explicitly set, correct - Okabe-Ito palette, correct backgrounds, readable in both light and dark modes' - - Excellent use of Altair's layer composition (mark_rule + mark_circle) with the - idiomatic x/x2 encoding for connecting lines - - Clean KISS code structure with pd.melt for proper long-form data; dot stroke halos - add professional polish - - 'Fully spec-compliant: horizontal orientation, sorted by difference, correct title - format, distinct colors for Before/After' - weaknesses: - - 'DE-03: Sorting reveals the pattern but there is no visual emphasis on the extremes - — color contrast variation, a size differential on the largest-gain category, - or a subtle annotation would help the viewer immediately see the story' - - 'DE-01: The overall design is clean but flat — all categories are presented with - equal visual weight; a focal point (e.g., slightly larger or brighter dot for - the max-difference row) would elevate sophistication' - - 'LM-02: The implementation uses Altair''s correct dumbbell idiom but misses an - opportunity to use Altair-specific transforms (e.g., calculate transform for diff - labels) or interactive selection for highlighting individual dumbbells' - image_description: |- - Light render (plot-light.png): - Background: Warm off-white (#FAF8F1) — correct, not pure white - Chrome: Title "Employee Satisfaction · dumbbell-basic · altair · anyplot.ai" in dark ink, clearly readable. Y-axis category labels (IT, R&D, Legal, Operations, Finance, HR, Marketing, Sales, Engineering, Customer Support) in dark ink. X-axis label "Employee Satisfaction Score (%)" clearly visible. Tick labels visible at appropriate size. - Data: Green dots (#009E73) for Before, orange dots (#D55E00) for After, each with a PAGE_BG stroke halo. Thin semi-transparent gray connecting lines. Legend box with elevated light fill, labeled "Policy Change" with Before/After entries. - Legibility verdict: PASS - - Dark render (plot-dark.png): - Background: Warm near-black (#1A1A17) — correct, not pure black - Chrome: Title in light-colored text, clearly readable against dark surface. Y-axis category labels in light text — no dark-on-dark failures. X-axis label in light text, clearly visible. Tick labels in light tone, readable. - Data: Green (#009E73) and orange (#D55E00) dots identical to light render — only chrome flips. Legend box uses elevated dark fill (#242420) with light-colored labels. - Legibility verdict: PASS - criteria_checklist: - visual_quality: - score: 30 - max: 30 - items: - - id: VQ-01 - name: Text Legibility - score: 8 - max: 8 - passed: true - comment: All font sizes explicitly set (title=28, axis=22, ticks=18, legend=16); - both themes fully readable - - id: VQ-02 - name: No Overlap - score: 6 - max: 6 - passed: true - comment: 10 categories evenly spaced on Y-axis; no label collisions - - id: VQ-03 - name: Element Visibility - score: 6 - max: 6 - passed: true - comment: Dots size=420 with stroke halo; connecting lines strokeWidth=3 at - 55% opacity - - id: VQ-04 - name: Color Accessibility - score: 2 - max: 2 - passed: true - comment: 'Okabe-Ito positions 1+2 (#009E73 vs #D55E00); high contrast, CVD-safe' - - id: VQ-05 - name: Layout & Canvas - score: 4 - max: 4 - passed: true - comment: 4800x2700px canvas; chart fills canvas well; legend not overlapping - data - - id: VQ-06 - name: Axis Labels & Title - score: 2 - max: 2 - passed: true - comment: X-axis includes units '(%)'; Y-axis title=None acceptable for labeled - categories - - id: VQ-07 - name: Palette Compliance - score: 2 - max: 2 - passed: true - comment: 'Before=#009E73, After=#D55E00; backgrounds #FAF8F1/#1A1A17 correct; - both renders theme-correct' - design_excellence: - score: 12 - max: 20 - items: - - id: DE-01 - name: Aesthetic Sophistication - score: 5 - max: 8 - passed: true - comment: Above configured-default look with dot stroke halos and correct palette; - no focal point or emphasis on extremes - - id: DE-02 - name: Visual Refinement - score: 4 - max: 6 - passed: true - comment: configure_view(stroke=None) removes border; gridOpacity=0.10 very - subtle; connecting line opacity=0.55 - - id: DE-03 - name: Data Storytelling - score: 3 - max: 6 - passed: false - comment: Sort by difference is good but all dots same size/weight; viewer - must find the insight themselves - spec_compliance: - score: 15 - max: 15 - items: - - id: SC-01 - name: Plot Type - score: 5 - max: 5 - passed: true - comment: Correct horizontal dumbbell/connected dot plot - - id: SC-02 - name: Required Features - score: 4 - max: 4 - passed: true - comment: Two distinct-color dots, thin connecting line, sorted by difference, - horizontal orientation - - id: SC-03 - name: Data Mapping - score: 3 - max: 3 - passed: true - comment: Categories on Y-axis, score values on X-axis; all 10 categories shown - - id: SC-04 - name: Title & Legend - score: 3 - max: 3 - passed: true - comment: Title contains dumbbell-basic, altair, anyplot.ai; legend labels - Before/After with Policy Change title - data_quality: - score: 15 - max: 15 - items: - - id: DQ-01 - name: Feature Coverage - score: 6 - max: 6 - passed: true - comment: 'Shows all dumbbell aspects: paired endpoints, connecting lines, - multiple categories, variation in differences (6-26 pts)' - - id: DQ-02 - name: Realistic Context - score: 5 - max: 5 - passed: true - comment: Employee satisfaction before/after policy changes; neutral business - scenario - - id: DQ-03 - name: Appropriate Scale - score: 4 - max: 4 - passed: true - comment: Score range 45-90 with data 52-85%; realistic for employee satisfaction - surveys; 10 categories appropriate - code_quality: - score: 10 - max: 10 - items: - - id: CQ-01 - name: KISS Structure - score: 3 - max: 3 - passed: true - comment: 'Linear: imports -> constants -> data -> chart layers -> configure - -> save; no functions or classes' - - id: CQ-02 - name: Reproducibility - score: 2 - max: 2 - passed: true - comment: Fully deterministic hardcoded data - - id: CQ-03 - name: Clean Imports - score: 2 - max: 2 - passed: true - comment: os, altair, pandas — all used - - id: CQ-04 - name: Code Elegance - score: 2 - max: 2 - passed: true - comment: Clean layer composition; pd.melt for long-form conversion; no over-engineering - - id: CQ-05 - name: Output & API - score: 1 - max: 1 - passed: true - comment: Saves plot-{THEME}.png (scale_factor=3.0) and plot-{THEME}.html - library_mastery: - score: 7 - max: 10 - items: - - id: LM-01 - name: Idiomatic Usage - score: 4 - max: 5 - passed: true - comment: mark_rule with x+x2 encoding is correct Altair idiom; layer composition - and configure_* API all used properly - - id: LM-02 - name: Distinctive Features - score: 3 - max: 5 - passed: true - comment: mark_rule with x2 for dumbbell connector and layer composition are - distinctively Altair; misses calculate transform or interactive selection - verdict: REJECTED -impl_tags: - dependencies: [] - techniques: - - layer-composition - - hover-tooltips - - html-export - patterns: - - data-generation - - wide-to-long - dataprep: [] - styling: - - alpha-blending - - edge-highlighting + strengths: [] + weaknesses: [] From 13c1747fe6a8a76f0adf2d524d2e163d5bdf58df Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Tue, 30 Jun 2026 23:02:54 +0000 Subject: [PATCH 3/5] chore(altair): update quality score 89 and review feedback for dumbbell-basic --- .../implementations/python/altair.py | 4 +- .../metadata/python/altair.yaml | 243 +++++++++++++++++- 2 files changed, 238 insertions(+), 9 deletions(-) diff --git a/plots/dumbbell-basic/implementations/python/altair.py b/plots/dumbbell-basic/implementations/python/altair.py index 59c6ccd7d9..f0ff99fa89 100644 --- a/plots/dumbbell-basic/implementations/python/altair.py +++ b/plots/dumbbell-basic/implementations/python/altair.py @@ -1,6 +1,6 @@ -"""anyplot.ai +""" anyplot.ai dumbbell-basic: Basic Dumbbell Chart -Library: altair 6.1.0 | Python 3.14.4 +Library: altair 6.2.2 | Python 3.13.14 Quality: 89/100 | Updated: 2026-06-30 """ diff --git a/plots/dumbbell-basic/metadata/python/altair.yaml b/plots/dumbbell-basic/metadata/python/altair.yaml index f7f4206660..6026a0c6a6 100644 --- a/plots/dumbbell-basic/metadata/python/altair.yaml +++ b/plots/dumbbell-basic/metadata/python/altair.yaml @@ -1,11 +1,8 @@ -# Per-library metadata for altair implementation of dumbbell-basic -# Auto-generated by impl-generate.yml - library: altair language: python specification_id: dumbbell-basic created: '2025-12-23T13:02:07Z' -updated: '2026-06-30T22:57:23Z' +updated: '2026-06-30T23:02:54Z' generated_by: claude-sonnet workflow_run: 28480646536 issue: 945 @@ -15,7 +12,239 @@ preview_url_light: https://storage.googleapis.com/anyplot-images/plots/dumbbell- preview_url_dark: https://storage.googleapis.com/anyplot-images/plots/dumbbell-basic/python/altair/plot-dark.png preview_html_light: https://storage.googleapis.com/anyplot-images/plots/dumbbell-basic/python/altair/plot-light.html preview_html_dark: https://storage.googleapis.com/anyplot-images/plots/dumbbell-basic/python/altair/plot-dark.html -quality_score: null +quality_score: 89 review: - strengths: [] - weaknesses: [] + strengths: + - Excellent use of Altair layer composition (mark_rule + mark_circle + mark_text) + for a clean dumbbell without workarounds + - Data sorted ascending by difference creates an immediately readable narrative + — Customer Support gains the most, IT the least + - Per-row difference labels (+N pts) computed via transform_calculate make gains + quantifiable without reading the x-axis + - 'Complete and correct theme adaptation: background, text, grid, legend, and dot + stroke all use adaptive tokens; data colors stay fixed across themes' + - mark_circle stroke=PAGE_BG gives dots a clean edge against both the background + and the connecting lines + weaknesses: + - Difference label fontSize=9 is very small — at mobile scale (~400 px wide) annotations + shrink to ~4 px; increase to fontSize=10 or 11 for better accessibility + - Left Y-axis domain line is still visible (domainColor=INK_SOFT); removing it (domainOpacity=0 + or domainColor=transparent) would improve visual refinement + image_description: |- + Light render (plot-light.png): + Background: warm off-white (#FAF8F1) — correct, not pure white + Chrome: Title "Employee Satisfaction · dumbbell-basic · python · altair · anyplot.ai" in dark ink (#1A1A17), clearly readable. Y-axis category labels in muted dark (#4A4A44), X-axis label "Employee Satisfaction Score (%)" in dark ink. Tick labels at 10pt, all readable. Difference labels (+N pts) at fontSize=9 in muted ink — small but legible at desktop scale. + Data: Before dots in brand green (#009E73), After dots in lavender (#C475FD). Connecting rules in grey at 45% opacity. Dots have PAGE_BG stroke for edge definition. All 10 categories visible and clearly distinguishable. + Legibility verdict: PASS + + Dark render (plot-dark.png): + Background: warm near-black (#1A1A17) — correct, not pure black + Chrome: Title and axis labels flip to light cream (#F0EFE8), tick labels and difference annotations to #B8B7B0. Legend box uses elevated dark surface (#242420) with muted stroke. No dark-on-dark text failure observed — all labels and tick text are clearly visible against the near-black background. + Data: Before dots remain #009E73 (brand green), After dots remain #C475FD (lavender) — identical to light render. Connecting lines adapt slightly in perceived contrast but are still subtly visible. + Legibility verdict: PASS + criteria_checklist: + visual_quality: + score: 29 + max: 30 + items: + - id: VQ-01 + name: Text Legibility + score: 7 + max: 8 + passed: true + comment: All text readable in both themes; difference labels at fontSize=9 + are small but legible at desktop; may be marginal at mobile scale + - id: VQ-02 + name: No Overlap + score: 6 + max: 6 + passed: true + comment: No overlapping elements; category labels, dots, diff labels, and + legend all cleanly separated + - id: VQ-03 + name: Element Visibility + score: 6 + max: 6 + passed: true + comment: size=350 dots are prominent for 10 sparse datapoints; connecting + lines at 45% opacity appropriately subtle; both colors clearly distinguishable + - id: VQ-04 + name: Color Accessibility + score: 2 + max: 2 + passed: true + comment: Imprint positions 1 (#009E73) and 2 (#C475FD) are CVD-safe; dots + have PAGE_BG stroke for definition + - id: VQ-05 + name: Layout & Canvas + score: 4 + max: 4 + passed: true + comment: Canvas gate passed (3200x1800); proportions well-balanced; title + ~70% width; good whitespace + - id: VQ-06 + name: Axis Labels & Title + score: 2 + max: 2 + passed: true + comment: X-axis label descriptive with units; Y-axis title suppressed (categories + self-explanatory); title format correct + - id: VQ-07 + name: Palette Compliance + score: 2 + max: 2 + passed: true + comment: Before=#009E73 (pos 1), After=#C475FD (pos 2); backgrounds correct; + chrome adapts; data colors identical across themes + design_excellence: + score: 12 + max: 20 + items: + - id: DE-01 + name: Aesthetic Sophistication + score: 5 + max: 8 + passed: true + comment: 'Intentional design: sorted data, stroked dots, correct palette; + thoughtful but not exceptional' + - id: DE-02 + name: Visual Refinement + score: 3 + max: 6 + passed: true + comment: Subtle 10% grid, no view border, polished legend padding; Y-axis + domain line still visible + - id: DE-03 + name: Data Storytelling + score: 4 + max: 6 + passed: true + comment: Sort ascending by difference is strong storytelling; per-row diff + annotations make gains immediately readable + spec_compliance: + score: 15 + max: 15 + items: + - id: SC-01 + name: Plot Type + score: 5 + max: 5 + passed: true + comment: 'Correct horizontal dumbbell: two colored dots connected by horizontal + rule' + - id: SC-02 + name: Required Features + score: 4 + max: 4 + passed: true + comment: Two distinct colors; thin connecting line; horizontal orientation; + sorted by difference + - id: SC-03 + name: Data Mapping + score: 3 + max: 3 + passed: true + comment: 'X: score values; Y: 10 department categories; color: period (Before/After); + all data shown' + - id: SC-04 + name: Title & Legend + score: 3 + max: 3 + passed: true + comment: Title 'Employee Satisfaction · dumbbell-basic · python · altair · + anyplot.ai' correct; legend 'Policy Change' with Before/After labels + data_quality: + score: 15 + max: 15 + items: + - id: DQ-01 + name: Feature Coverage + score: 6 + max: 6 + passed: true + comment: Both endpoints shown; range via connecting line; diff annotations; + sort reveals direction of change + - id: DQ-02 + name: Realistic Context + score: 5 + max: 5 + passed: true + comment: Employee satisfaction before/after policy change is canonical dumbbell + use case; values 52-85 realistic; neutral and professional + - id: DQ-03 + name: Appropriate Scale + score: 4 + max: 4 + passed: true + comment: X-scale [45,92] fits data with padding; 10 categories within spec's + 5-20 range; values realistic for satisfaction scores + code_quality: + score: 10 + max: 10 + items: + - id: CQ-01 + name: KISS Structure + score: 3 + max: 3 + passed: true + comment: No functions or classes; three-layer chart composition is direct + and readable + - id: CQ-02 + name: Reproducibility + score: 2 + max: 2 + passed: true + comment: Data is hardcoded (deterministic); no random elements + - id: CQ-03 + name: Clean Imports + score: 2 + max: 2 + passed: true + comment: All four imports (os, altair, pandas, PIL.Image) are actually used + - id: CQ-04 + name: Code Elegance + score: 2 + max: 2 + passed: true + comment: No fake UI; transform_calculate for labels is idiomatic; PIL padding + block follows canonical pattern + - id: CQ-05 + name: Output & API + score: 1 + max: 1 + passed: true + comment: Saves plot-{THEME}.png (with padding) and plot-{THEME}.html; uses + scale_factor=4.0 + library_features: + score: 8 + max: 10 + items: + - id: LM-01 + name: Idiomatic Usage + score: 5 + max: 5 + passed: true + comment: Layer composition via +; mark_rule with x/x2 for range lines; EncodingSortField; + configure_axis/configure_legend — all canonical Altair patterns + - id: LM-02 + name: Distinctive Features + score: 3 + max: 5 + passed: true + comment: mark_rule with x2 is the correct Altair idiom; transform_calculate + for inline label computation is a nice touch; overall structure not exclusively + Altair + verdict: APPROVED +impl_tags: + dependencies: + - pillow + techniques: + - layer-composition + - hover-tooltips + - html-export + patterns: + - wide-to-long + dataprep: [] + styling: + - edge-highlighting + - alpha-blending From 435d24fc749ac831187301c91e6b184b58d1800a Mon Sep 17 00:00:00 2001 From: "claude[bot]" <41898282+claude[bot]@users.noreply.github.com> Date: Tue, 30 Jun 2026 23:05:27 +0000 Subject: [PATCH 4/5] fix(altair): address review feedback for dumbbell-basic Attempt 1/3 - fixes based on AI review --- plots/dumbbell-basic/implementations/python/altair.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/plots/dumbbell-basic/implementations/python/altair.py b/plots/dumbbell-basic/implementations/python/altair.py index f0ff99fa89..4655574d9e 100644 --- a/plots/dumbbell-basic/implementations/python/altair.py +++ b/plots/dumbbell-basic/implementations/python/altair.py @@ -1,4 +1,4 @@ -""" anyplot.ai +"""anyplot.ai dumbbell-basic: Basic Dumbbell Chart Library: altair 6.2.2 | Python 3.13.14 Quality: 89/100 | Updated: 2026-06-30 @@ -83,7 +83,7 @@ diff_labels = ( alt.Chart(data) .transform_calculate(label="'+' + toString(datum.difference) + ' pts'") - .mark_text(align="left", dx=8, fontSize=9, fontWeight="bold", clip=False) + .mark_text(align="left", dx=8, fontSize=11, fontWeight="bold", clip=False) .encode( y=alt.Y("category:N", sort=y_sort, title=None), x=alt.X("After:Q", scale=x_scale), @@ -105,6 +105,7 @@ labelFontSize=10, titleFontSize=12, domainColor=INK_SOFT, + domainOpacity=0, tickColor=INK_SOFT, gridColor=INK, gridOpacity=0.10, From c1704d9123d74471532b0f48cc4c0eafcb8b669a Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Tue, 30 Jun 2026 23:11:58 +0000 Subject: [PATCH 5/5] chore(altair): update quality score 92 and review feedback for dumbbell-basic --- .../implementations/python/altair.py | 4 +- .../metadata/python/altair.yaml | 148 +++++++++--------- 2 files changed, 74 insertions(+), 78 deletions(-) diff --git a/plots/dumbbell-basic/implementations/python/altair.py b/plots/dumbbell-basic/implementations/python/altair.py index 4655574d9e..97a48ed7a8 100644 --- a/plots/dumbbell-basic/implementations/python/altair.py +++ b/plots/dumbbell-basic/implementations/python/altair.py @@ -1,7 +1,7 @@ -"""anyplot.ai +""" anyplot.ai dumbbell-basic: Basic Dumbbell Chart Library: altair 6.2.2 | Python 3.13.14 -Quality: 89/100 | Updated: 2026-06-30 +Quality: 92/100 | Updated: 2026-06-30 """ import os diff --git a/plots/dumbbell-basic/metadata/python/altair.yaml b/plots/dumbbell-basic/metadata/python/altair.yaml index 6026a0c6a6..e837c9e678 100644 --- a/plots/dumbbell-basic/metadata/python/altair.yaml +++ b/plots/dumbbell-basic/metadata/python/altair.yaml @@ -2,7 +2,7 @@ library: altair language: python specification_id: dumbbell-basic created: '2025-12-23T13:02:07Z' -updated: '2026-06-30T23:02:54Z' +updated: '2026-06-30T23:11:57Z' generated_by: claude-sonnet workflow_run: 28480646536 issue: 945 @@ -12,35 +12,38 @@ preview_url_light: https://storage.googleapis.com/anyplot-images/plots/dumbbell- preview_url_dark: https://storage.googleapis.com/anyplot-images/plots/dumbbell-basic/python/altair/plot-dark.png preview_html_light: https://storage.googleapis.com/anyplot-images/plots/dumbbell-basic/python/altair/plot-light.html preview_html_dark: https://storage.googleapis.com/anyplot-images/plots/dumbbell-basic/python/altair/plot-dark.html -quality_score: 89 +quality_score: 92 review: strengths: - - Excellent use of Altair layer composition (mark_rule + mark_circle + mark_text) - for a clean dumbbell without workarounds - - Data sorted ascending by difference creates an immediately readable narrative - — Customer Support gains the most, IT the least - - Per-row difference labels (+N pts) computed via transform_calculate make gains - quantifiable without reading the x-axis - - 'Complete and correct theme adaptation: background, text, grid, legend, and dot - stroke all use adaptive tokens; data colors stay fixed across themes' - - mark_circle stroke=PAGE_BG gives dots a clean edge against both the background - and the connecting lines + - 'Perfect Imprint palette assignment: Before=#009E73 (pos 1), After=#C475FD (pos + 2); theme-adaptive chrome correctly wired in both light and dark renders' + - 'Excellent spec compliance: horizontal dumbbell, sorted by difference, subtle + connecting lines, distinct endpoint colors - all spec requirements met' + - Bold '+X pts' difference labels via transform_calculate add immediate storytelling + clarity without extra data + - Idiomatic Altair layer composition (mark_rule + mark_circle + mark_text) is clean + and maintainable + - PIL canvas-padding block correctly handles vl-convert sizing to exact 3200x1800 weaknesses: - - Difference label fontSize=9 is very small — at mobile scale (~400 px wide) annotations - shrink to ~4 px; increase to fontSize=10 or 11 for better accessibility - - Left Y-axis domain line is still visible (domainColor=INK_SOFT); removing it (domainOpacity=0 - or domainColor=transparent) would improve visual refinement + - 'Grid density: 23 vertical grid lines (every 2 units from 46-92) is slightly noisy; + reducing to every 5 or 10 units (e.g., configure_axis tickCount=10 or tickMinStep=5) + would improve visual refinement' + - 'Tick label granularity: ticks every 2 units creates a crowded axis; fewer ticks + at rounder values would improve readability at small scales' + - 'LM-02 ceiling: conditional encodings (e.g., highlight the department with the + highest gain) are Altair-exclusive and would demonstrate more distinctive library + mastery' image_description: |- Light render (plot-light.png): - Background: warm off-white (#FAF8F1) — correct, not pure white - Chrome: Title "Employee Satisfaction · dumbbell-basic · python · altair · anyplot.ai" in dark ink (#1A1A17), clearly readable. Y-axis category labels in muted dark (#4A4A44), X-axis label "Employee Satisfaction Score (%)" in dark ink. Tick labels at 10pt, all readable. Difference labels (+N pts) at fontSize=9 in muted ink — small but legible at desktop scale. - Data: Before dots in brand green (#009E73), After dots in lavender (#C475FD). Connecting rules in grey at 45% opacity. Dots have PAGE_BG stroke for edge definition. All 10 categories visible and clearly distinguishable. + Background: Warm off-white #FAF8F1 - correct + Chrome: Title "Employee Satisfaction · dumbbell-basic · python · altair · anyplot.ai" in dark ink, top-left, ~75% width. Y-axis category labels in dark soft-ink. X-axis label "Employee Satisfaction Score (%)" in dark ink. Tick labels in soft-ink #4A4A44. All readable. + Data: Green #009E73 dots for Before values, lavender #C475FD dots for After values. Semi-transparent gray connecting lines. Bold "+X pts" difference labels right of each After dot. Legend box with elevated background, labeled "Policy Change". Legibility verdict: PASS Dark render (plot-dark.png): - Background: warm near-black (#1A1A17) — correct, not pure black - Chrome: Title and axis labels flip to light cream (#F0EFE8), tick labels and difference annotations to #B8B7B0. Legend box uses elevated dark surface (#242420) with muted stroke. No dark-on-dark text failure observed — all labels and tick text are clearly visible against the near-black background. - Data: Before dots remain #009E73 (brand green), After dots remain #C475FD (lavender) — identical to light render. Connecting lines adapt slightly in perceived contrast but are still subtly visible. + Background: Warm near-black #1A1A17 - correct + Chrome: Title in light #F0EFE8 ink, clearly visible. Y-axis and X-axis labels in light ink. Tick labels in soft #B8B7B0. Legend box uses elevated dark fill #242420. No dark-on-dark failures observed. + Data: Colors identical to light render - #009E73 green for Before, #C475FD lavender for After. Connecting lines and diff labels also visible. Legibility verdict: PASS criteria_checklist: visual_quality: @@ -52,75 +55,74 @@ review: score: 7 max: 8 passed: true - comment: All text readable in both themes; difference labels at fontSize=9 - are small but legible at desktop; may be marginal at mobile scale + comment: All font sizes explicitly set; well-proportioned in both themes. + Minor deduction for dense tick labels (every 2 units, ~23 ticks) - id: VQ-02 name: No Overlap score: 6 max: 6 passed: true - comment: No overlapping elements; category labels, dots, diff labels, and - legend all cleanly separated + comment: No text collisions; diff labels well-spaced - id: VQ-03 name: Element Visibility score: 6 max: 6 passed: true - comment: size=350 dots are prominent for 10 sparse datapoints; connecting - lines at 45% opacity appropriately subtle; both colors clearly distinguishable + comment: size=350 dots prominent for sparse 10-category data; connecting lines + clearly visible - id: VQ-04 name: Color Accessibility score: 2 max: 2 passed: true - comment: Imprint positions 1 (#009E73) and 2 (#C475FD) are CVD-safe; dots - have PAGE_BG stroke for definition + comment: CVD-safe green/lavender pair; PAGE_BG dot stroke adds definition - id: VQ-05 name: Layout & Canvas score: 4 max: 4 passed: true - comment: Canvas gate passed (3200x1800); proportions well-balanced; title - ~70% width; good whitespace + comment: Canvas gate passed 3200x1800; plot fills space well with legend in + upper right - id: VQ-06 name: Axis Labels & Title score: 2 max: 2 passed: true - comment: X-axis label descriptive with units; Y-axis title suppressed (categories - self-explanatory); title format correct + comment: X-axis 'Employee Satisfaction Score (%)' descriptive with units; + title correctly formatted - id: VQ-07 name: Palette Compliance score: 2 max: 2 passed: true - comment: Before=#009E73 (pos 1), After=#C475FD (pos 2); backgrounds correct; - chrome adapts; data colors identical across themes + comment: 'Before=#009E73 (Imprint pos 1), After=#C475FD (Imprint pos 2); backgrounds + #FAF8F1/#1A1A17; data colors identical across themes' design_excellence: - score: 12 + score: 14 max: 20 items: - id: DE-01 name: Aesthetic Sophistication - score: 5 + score: 6 max: 8 passed: true - comment: 'Intentional design: sorted data, stroked dots, correct palette; - thoughtful but not exceptional' + comment: 'Strong design above defaults: Imprint palette, PAGE_BG dot-stroke, + semi-transparent lines, bold diff labels. Not quite publication-level polish.' - id: DE-02 name: Visual Refinement - score: 3 + score: 4 max: 6 passed: true - comment: Subtle 10% grid, no view border, polished legend padding; Y-axis - domain line still visible + comment: Domain lines removed (domainOpacity=0), no border frame (stroke=None), + subtle 10% grid, styled legend. Grid density slightly high (23 lines every + 2 units). - id: DE-03 name: Data Storytelling score: 4 max: 6 passed: true - comment: Sort ascending by difference is strong storytelling; per-row diff - annotations make gains immediately readable + comment: Sort by difference + bold '+X pts' labels creates clear story; viewer + immediately sees Customer Support improved most (+26 pts) spec_compliance: score: 15 max: 15 @@ -130,29 +132,28 @@ review: score: 5 max: 5 passed: true - comment: 'Correct horizontal dumbbell: two colored dots connected by horizontal - rule' + comment: Correct dumbbell/connected dot plot with two endpoints per category - id: SC-02 name: Required Features score: 4 max: 4 passed: true - comment: Two distinct colors; thin connecting line; horizontal orientation; - sorted by difference + comment: Horizontal orientation, distinct colors, connecting lines, sorted + by difference - all present - id: SC-03 name: Data Mapping score: 3 max: 3 passed: true - comment: 'X: score values; Y: 10 department categories; color: period (Before/After); - all data shown' + comment: Categories on Y-axis, satisfaction scores on X-axis, Before/After + correctly mapped - id: SC-04 name: Title & Legend score: 3 max: 3 passed: true - comment: Title 'Employee Satisfaction · dumbbell-basic · python · altair · - anyplot.ai' correct; legend 'Policy Change' with Before/After labels + comment: Title uses descriptive prefix + mandatory format; legend 'Policy + Change' with correct labels data_quality: score: 15 max: 15 @@ -162,22 +163,20 @@ review: score: 6 max: 6 passed: true - comment: Both endpoints shown; range via connecting line; diff annotations; - sort reveals direction of change + comment: 10 departments with varying improvement magnitudes (5-26 pts) - id: DQ-02 name: Realistic Context score: 5 max: 5 passed: true - comment: Employee satisfaction before/after policy change is canonical dumbbell - use case; values 52-85 realistic; neutral and professional + comment: Employee satisfaction before/after policy changes; neutral business + scenario with real department names - id: DQ-03 name: Appropriate Scale score: 4 max: 4 passed: true - comment: X-scale [45,92] fits data with padding; 10 categories within spec's - 5-20 range; values realistic for satisfaction scores + comment: Scores 52-85 on 0-100 scale; plausible improvements; coherent narrative code_quality: score: 10 max: 10 @@ -187,36 +186,35 @@ review: score: 3 max: 3 passed: true - comment: No functions or classes; three-layer chart composition is direct - and readable + comment: Imports -> data -> chart layers -> save; no functions or classes - id: CQ-02 name: Reproducibility score: 2 max: 2 passed: true - comment: Data is hardcoded (deterministic); no random elements + comment: Hardcoded deterministic data; no random seed needed - id: CQ-03 name: Clean Imports score: 2 max: 2 passed: true - comment: All four imports (os, altair, pandas, PIL.Image) are actually used + comment: os, altair, pandas, PIL - all used, none superfluous - id: CQ-04 name: Code Elegance score: 2 max: 2 passed: true - comment: No fake UI; transform_calculate for labels is idiomatic; PIL padding - block follows canonical pattern + comment: Clean Altair layer composition, concise transform_calculate, appropriate + complexity - id: CQ-05 name: Output & API score: 1 max: 1 passed: true - comment: Saves plot-{THEME}.png (with padding) and plot-{THEME}.html; uses - scale_factor=4.0 - library_features: - score: 8 + comment: Saves plot-{THEME}.png and plot-{THEME}.html; current Altair 6.x + API + library_mastery: + score: 9 max: 10 items: - id: LM-01 @@ -224,16 +222,15 @@ review: score: 5 max: 5 passed: true - comment: Layer composition via +; mark_rule with x/x2 for range lines; EncodingSortField; - configure_axis/configure_legend — all canonical Altair patterns + comment: Expert layer composition, x2 encoding for dumbbell lines, EncodingSortField, + transform_calculate - all canonical Altair patterns - id: LM-02 name: Distinctive Features - score: 3 + score: 4 max: 5 passed: true - comment: mark_rule with x2 is the correct Altair idiom; transform_calculate - for inline label computation is a nice touch; overall structure not exclusively - Altair + comment: transform_calculate, x2 encoding, and EncodingSortField are Altair-specific. + Could further use conditional encodings to highlight top-performer row. verdict: APPROVED impl_tags: dependencies: @@ -247,4 +244,3 @@ impl_tags: dataprep: [] styling: - edge-highlighting - - alpha-blending