From a60e65711ecae60abd9480f9b181557686428235 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Tue, 30 Jun 2026 22:54:42 +0000 Subject: [PATCH 1/5] feat(pygal): implement dumbbell-basic Regen from quality 87. Addressed: - canvas fixed from 4800x2700 to canonical 3200x1800 (Step 0 contract) - font sizes scaled up to library-prompt canonical values (title 63, labels 56, ticks 44) - excess whitespace fixed: range=(0.5, n+0.5) instead of (0, n+1) - dashed grid guides removed (show_x_guides=False) for cleaner look - delta labels added to category names (e.g. "Customer Support (+24)") for storytelling - title now includes "python" language token per mandatory format - comment updated from "Okabe-Ito" to "Imprint palette" --- .../implementations/python/pygal.py | 76 ++++++++++--------- 1 file changed, 42 insertions(+), 34 deletions(-) diff --git a/plots/dumbbell-basic/implementations/python/pygal.py b/plots/dumbbell-basic/implementations/python/pygal.py index 3ad9bf8b98..0f61398c4e 100644 --- a/plots/dumbbell-basic/implementations/python/pygal.py +++ b/plots/dumbbell-basic/implementations/python/pygal.py @@ -1,7 +1,7 @@ -""" anyplot.ai +"""anyplot.ai dumbbell-basic: Basic Dumbbell Chart -Library: pygal 3.1.0 | Python 3.14.4 -Quality: 87/100 | Updated: 2026-04-26 +Library: pygal | Python 3.13 +Quality: pending | Updated: 2026-06-30 """ import os @@ -9,7 +9,7 @@ from pathlib import Path -# Remove script directory from path to avoid name collision with the pygal package +# Remove script dir from sys.path to avoid name collision with the pygal package _script_dir = str(Path(__file__).parent) sys.path = [p for p in sys.path if p != _script_dir] @@ -17,20 +17,19 @@ from pygal.style import Style # noqa: E402 -# Theme-adaptive chrome tokens +# Theme tokens THEME = os.getenv("ANYPLOT_THEME", "light") PAGE_BG = "#FAF8F1" if THEME == "light" else "#1A1A17" INK = "#1A1A17" if THEME == "light" else "#F0EFE8" INK_SOFT = "#4A4A44" if THEME == "light" else "#B8B7B0" INK_MUTED = "#6B6A63" if THEME == "light" else "#A8A79F" -# Okabe-Ito data colors (theme-independent) -BEFORE = "#009E73" # position 1 — brand -AFTER = "#C475FD" # position 2 -CONNECTOR = INK_SOFT # neutral chrome that adapts to theme +# Imprint categorical palette — positions 1 and 2 for two-series dumbbell +BEFORE = "#009E73" # Imprint position 1 — brand green, always first series +AFTER = "#C475FD" # Imprint position 2 — lavender +CONNECTOR = INK_SOFT # theme-adaptive neutral connector line -# Data — Employee satisfaction scores before and after policy changes. -# Hand-picked values include one regression (Legal) to exercise full data range. +# Data — employee satisfaction scores before and after new workplace policy categories = [ "Engineering", "Sales", @@ -45,18 +44,29 @@ before = [62, 71, 58, 45, 68, 52, 64, 73, 70] after = [78, 82, 75, 69, 74, 71, 79, 85, 67] -# Sort by improvement (largest at top) +# Sort by improvement (largest gain at top; Legal regression ends up at bottom) data = sorted(zip(categories, before, after, strict=True), key=lambda x: x[2] - x[1], reverse=True) categories = [d[0] for d in data] before = [d[1] for d in data] after = [d[2] for d in data] n = len(categories) -# Y positions: top row = biggest improvement (first sorted item) +# Top row = biggest improvement; y=n at top, y=1 at bottom y_positions = list(range(n, 0, -1)) -# Series colors map 1:1 to the order series are added below: -# n connector series (drawn first, underneath) then 2 dot series. +# Category labels include delta for at-a-glance storytelling (e.g. "Customer Support (+24)") +y_labels = [ + {"label": f"{cat} ({a - b:+d})", "value": pos} + for cat, b, a, pos in zip(categories, before, after, y_positions, strict=True) +] + +# Title — include language token; scale font size for title length +title = "Employee Satisfaction · dumbbell-basic · python · pygal · anyplot.ai" +n_chars = len(title) # 70 chars +ratio = 67 / n_chars if n_chars > 67 else 1.0 +title_font_size = max(44, round(66 * ratio)) # ≈ 63 + +# Color sequence: n neutral connectors then brand green + lavender for dots colors_tuple = (CONNECTOR,) * n + (BEFORE, AFTER) custom_style = Style( @@ -66,57 +76,55 @@ foreground_strong=INK, foreground_subtle=INK_MUTED, colors=colors_tuple, - title_font_size=32, - label_font_size=22, - major_label_font_size=20, - legend_font_size=20, - value_font_size=16, - stroke_width=4, + title_font_size=title_font_size, + label_font_size=56, + major_label_font_size=44, + legend_font_size=44, + value_font_size=36, + stroke_width=2.5, opacity=1.0, opacity_hover=0.85, ) chart = pygal.XY( - width=4800, - height=2700, + width=3200, + height=1800, style=custom_style, - title="Employee Satisfaction · dumbbell-basic · pygal · anyplot.ai", + title=title, x_title="Satisfaction Score (out of 100)", y_title="Department", show_legend=True, legend_at_bottom=True, legend_at_bottom_columns=2, - legend_box_size=36, + legend_box_size=44, margin=80, - show_x_guides=True, + show_x_guides=False, show_y_guides=False, xrange=(35, 95), - range=(0, n + 1), - y_labels=[{"label": cat, "value": pos} for cat, pos in zip(categories, y_positions, strict=True)], + range=(0.5, n + 0.5), + y_labels=y_labels, truncate_legend=-1, truncate_label=-1, - dots_size=22, stroke=False, ) -# Connector lines first so they sit underneath the dots. -# title=None suppresses the legend entry while still rendering the series. +# Connector lines drawn first so they sit underneath the dots for b, a, pos in zip(before, after, y_positions, strict=True): chart.add(None, [(b, pos), (a, pos)], stroke=True, show_dots=False, stroke_style={"width": 5, "linecap": "round"}) -# Before dots — Okabe-Ito green +# Before dots — Imprint brand green (position 1) before_points = [ {"value": (b, pos), "label": f"{cat}: {b}"} for cat, b, pos in zip(categories, before, y_positions, strict=True) ] chart.add("Before policy change", before_points, stroke=False, dots_size=24) -# After dots — Okabe-Ito vermillion +# After dots — Imprint lavender (position 2) after_points = [ {"value": (a, pos), "label": f"{cat}: {a}"} for cat, a, pos in zip(categories, after, y_positions, strict=True) ] chart.add("After policy change", after_points, stroke=False, dots_size=24) -# Save outputs +# Save PNG and interactive HTML chart.render_to_png(f"plot-{THEME}.png") with open(f"plot-{THEME}.html", "wb") as f: f.write(chart.render()) From e8fb62b5fc07b8273f36e39d582e230476d85af6 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Tue, 30 Jun 2026 22:54:54 +0000 Subject: [PATCH 2/5] chore(pygal): add metadata for dumbbell-basic --- .../dumbbell-basic/metadata/python/pygal.yaml | 244 +----------------- 1 file changed, 11 insertions(+), 233 deletions(-) diff --git a/plots/dumbbell-basic/metadata/python/pygal.yaml b/plots/dumbbell-basic/metadata/python/pygal.yaml index 0616417943..0791384dd3 100644 --- a/plots/dumbbell-basic/metadata/python/pygal.yaml +++ b/plots/dumbbell-basic/metadata/python/pygal.yaml @@ -1,243 +1,21 @@ +# Per-library metadata for pygal implementation of dumbbell-basic +# Auto-generated by impl-generate.yml + library: pygal language: python specification_id: dumbbell-basic created: '2025-12-23T13:02:31Z' -updated: '2026-04-26T01:54:43Z' -generated_by: claude-opus -workflow_run: 24945459219 +updated: '2026-06-30T22:54:54Z' +generated_by: claude-sonnet +workflow_run: 28480823048 issue: 945 -python_version: 3.14.4 -library_version: 3.1.0 +language_version: 3.13.14 +library_version: 3.1.3 preview_url_light: https://storage.googleapis.com/anyplot-images/plots/dumbbell-basic/python/pygal/plot-light.png preview_url_dark: https://storage.googleapis.com/anyplot-images/plots/dumbbell-basic/python/pygal/plot-dark.png preview_html_light: https://storage.googleapis.com/anyplot-images/plots/dumbbell-basic/python/pygal/plot-light.html preview_html_dark: https://storage.googleapis.com/anyplot-images/plots/dumbbell-basic/python/pygal/plot-dark.html -quality_score: 87 +quality_score: null review: - strengths: - - Theme-adaptive connector lines using INK_SOFT token are a deliberate, well-executed - design choice that makes the chart feel polished in both themes - - Perfect spec compliance — horizontal orientation, sorted by improvement, correct - dot colors, all required features present - - 'Excellent data storytelling: sorting by improvement and including a regression - case (Legal) creates a compelling before/after narrative' - - 'Clean, idiomatic code: creative use of pygal XY chart with mixed stroke settings; - the None-title trick for connector series is elegant' - - Full pygal interactive output (PNG + HTML) produced correctly - weaknesses: - - Noticeable blank whitespace at top and bottom of the data area — range=(0.5, n - + 0.5) would fill the canvas better - - Grid lines render as dashed (style guide requires solid thin lines at 15-25% opacity) - - No annotations or callouts on standout cases (Customer Support largest gain, Legal - only regression) — value labels would significantly improve data storytelling - image_description: |- - Light render (plot-light.png): - Background: Warm off-white (#FAF8F1) — correct theme surface - Chrome: Title "Employee Satisfaction · dumbbell-basic · pygal · anyplot.ai" in dark text, clearly readable. X-axis label "Satisfaction Score (out of 100)" and y-axis label "Department" both readable. Tick labels (40–90 on x, department names on y) readable. Legend "Before policy change" / "After policy change" at bottom readable. - Data: 9 dumbbell rows sorted by improvement. Before dots are #009E73 (brand green), after dots are #D55E00 (vermillion). Connectors are thin muted dark gray (INK_SOFT #4A4A44). Dashed x-axis vertical grid lines are subtle. - Legibility verdict: PASS - - Dark render (plot-dark.png): - Background: Near-black (#1A1A17) — correct dark theme surface - Chrome: Title and all axis labels, tick labels, and legend text render in light color against the dark background — clearly readable. No dark-on-dark failures detected. - Data: Colors identical to light render — same green #009E73 and orange #D55E00 dots. Connectors adapt to light gray (#B8B7B0, INK_SOFT dark-token), visible against dark background. - Legibility verdict: PASS - criteria_checklist: - visual_quality: - score: 28 - max: 30 - items: - - id: VQ-01 - name: Text Legibility - score: 7 - max: 8 - passed: true - comment: Font sizes well-specified (title 32px, labels 22px, ticks 20px); - readable in both themes; minor deduction as category labels appear small - at full canvas resolution - - id: VQ-02 - name: No Overlap - score: 6 - max: 6 - passed: true - comment: Nine departments well-spaced; no text or element collisions - - id: VQ-03 - name: Element Visibility - score: 6 - max: 6 - passed: true - comment: Dots size 24 and connector stroke width 5 clearly visible in both - themes - - id: VQ-04 - name: Color Accessibility - score: 2 - max: 2 - passed: true - comment: Green + vermillion is CVD-safe Okabe-Ito pair; no red-green sole - signal - - id: VQ-05 - name: Layout & Canvas - score: 3 - max: 4 - passed: true - comment: Landscape 4800x2700 appropriate; excess whitespace at top and bottom - of data area from range=(0, n+1) - - id: VQ-06 - name: Axis Labels & Title - score: 2 - max: 2 - passed: true - comment: Descriptive axis labels with units; title format correct - - id: VQ-07 - name: Palette Compliance - score: 2 - max: 2 - passed: true - comment: 'First series #009E73, second #D55E00; backgrounds #FAF8F1/#1A1A17; - colors identical across themes' - design_excellence: - score: 12 - max: 20 - items: - - id: DE-01 - name: Aesthetic Sophistication - score: 5 - max: 8 - passed: true - comment: Theme-adaptive connectors using INK_SOFT is thoughtful; sorting adds - analytical clarity; regression case adds depth; clean but not particularly - sophisticated - - id: DE-02 - name: Visual Refinement - score: 3 - max: 6 - passed: true - comment: Good choice to omit y-axis guides; subtle connectors; grid lines - are dashed (style guide requires solid); excess blank whitespace at top/bottom - - id: DE-03 - name: Data Storytelling - score: 4 - max: 6 - passed: true - comment: Sorting by improvement creates clear narrative; Legal regression - at bottom is compelling; no annotations on standout cases - spec_compliance: - score: 15 - max: 15 - items: - - id: SC-01 - name: Plot Type - score: 5 - max: 5 - passed: true - comment: Correct horizontal dumbbell chart; two dots per category connected - by a line - - id: SC-02 - name: Required Features - score: 4 - max: 4 - passed: true - comment: Horizontal orientation, distinct dot colors, thin connector, sorted - by difference, 9 categories - - id: SC-03 - name: Data Mapping - score: 3 - max: 3 - passed: true - comment: Categories on y-axis, satisfaction scores on x-axis, xrange covers - all data - - id: SC-04 - name: Title & Legend - score: 3 - max: 3 - passed: true - comment: Title includes spec-id and library; legend labels match data context - data_quality: - score: 15 - max: 15 - items: - - id: DQ-01 - name: Feature Coverage - score: 6 - max: 6 - passed: true - comment: 'Shows all dumbbell chart aspects: start/end values, connectors, - horizontal orientation, positive and negative change' - - id: DQ-02 - name: Realistic Context - score: 5 - max: 5 - passed: true - comment: Employee satisfaction by department before/after policy changes; - realistic values 45-85; neutral professional context - - id: DQ-03 - name: Appropriate Scale - score: 4 - max: 4 - passed: true - comment: 0-100 satisfaction scale appropriate; data range 45-85 realistic; - xrange 35-95 gives good visual padding - code_quality: - score: 10 - max: 10 - items: - - id: CQ-01 - name: KISS Structure - score: 3 - max: 3 - passed: true - comment: No functions or classes; linear flat script - - id: CQ-02 - name: Reproducibility - score: 2 - max: 2 - passed: true - comment: Fully deterministic hardcoded data; no random seed needed - - id: CQ-03 - name: Clean Imports - score: 2 - max: 2 - passed: true - comment: Only os, sys, pathlib.Path, pygal, pygal.style.Style; all used - - id: CQ-04 - name: Code Elegance - score: 2 - max: 2 - passed: true - comment: Loop for connectors clean; list comprehensions for dots; None-title - trick elegantly suppresses connector legend - - id: CQ-05 - name: Output & API - score: 1 - max: 1 - passed: true - comment: Saves plot-{THEME}.png and plot-{THEME}.html correctly - library_mastery: - score: 7 - max: 10 - items: - - id: LM-01 - name: Idiomatic Usage - score: 4 - max: 5 - passed: true - comment: Creative use of pygal.XY with mixed stroke=True/False per series; - y_labels dict format for custom placement; stroke_style with linecap=round - - id: LM-02 - name: Distinctive Features - score: 3 - max: 5 - passed: true - comment: Interactive HTML output produced; hover labels via dict format leverage - pygal tooltip system; SVG linecap=round is pygal/SVG-native - verdict: APPROVED -impl_tags: - dependencies: [] - techniques: - - html-export - - manual-ticks - patterns: - - data-generation - - iteration-over-groups - dataprep: [] - styling: [] + strengths: [] + weaknesses: [] From 8f59cdc0ce1e3bcf13ba0b24e1b08457c5d573e1 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Tue, 30 Jun 2026 23:00:35 +0000 Subject: [PATCH 3/5] chore(pygal): update quality score 87 and review feedback for dumbbell-basic --- .../implementations/python/pygal.py | 6 +- .../dumbbell-basic/metadata/python/pygal.yaml | 248 +++++++++++++++++- 2 files changed, 244 insertions(+), 10 deletions(-) diff --git a/plots/dumbbell-basic/implementations/python/pygal.py b/plots/dumbbell-basic/implementations/python/pygal.py index 0f61398c4e..497115136c 100644 --- a/plots/dumbbell-basic/implementations/python/pygal.py +++ b/plots/dumbbell-basic/implementations/python/pygal.py @@ -1,7 +1,7 @@ -"""anyplot.ai +""" anyplot.ai dumbbell-basic: Basic Dumbbell Chart -Library: pygal | Python 3.13 -Quality: pending | Updated: 2026-06-30 +Library: pygal 3.1.3 | Python 3.13.14 +Quality: 87/100 | Updated: 2026-06-30 """ import os diff --git a/plots/dumbbell-basic/metadata/python/pygal.yaml b/plots/dumbbell-basic/metadata/python/pygal.yaml index 0791384dd3..2e3daabc7e 100644 --- a/plots/dumbbell-basic/metadata/python/pygal.yaml +++ b/plots/dumbbell-basic/metadata/python/pygal.yaml @@ -1,11 +1,8 @@ -# Per-library metadata for pygal implementation of dumbbell-basic -# Auto-generated by impl-generate.yml - library: pygal language: python specification_id: dumbbell-basic created: '2025-12-23T13:02:31Z' -updated: '2026-06-30T22:54:54Z' +updated: '2026-06-30T23:00:35Z' generated_by: claude-sonnet workflow_run: 28480823048 issue: 945 @@ -15,7 +12,244 @@ preview_url_light: https://storage.googleapis.com/anyplot-images/plots/dumbbell- preview_url_dark: https://storage.googleapis.com/anyplot-images/plots/dumbbell-basic/python/pygal/plot-dark.png preview_html_light: https://storage.googleapis.com/anyplot-images/plots/dumbbell-basic/python/pygal/plot-light.html preview_html_dark: https://storage.googleapis.com/anyplot-images/plots/dumbbell-basic/python/pygal/plot-dark.html -quality_score: null +quality_score: 87 review: - strengths: [] - weaknesses: [] + strengths: + - 'Perfect Imprint palette usage: brand green (#009E73) first, lavender (#C475FD) + second, connector uses theme-adaptive INK_SOFT' + - 'Strong data storytelling: sort-by-improvement plus delta labels in category names + gives at-a-glance ranking without reading the x-axis' + - Includes regression outlier (Legal -3) making the dataset realistic and narratively + interesting + - 'Full spec compliance: horizontal orientation, distinct two-color encoding, thin + connectors, sorted layout' + - 'Excellent code quality: deterministic, no dead code, idiomatic pygal patterns, + sys.path workaround clearly explained' + - Both themes render correctly with no dark-on-dark or light-on-light failures + weaknesses: + - Bottom ~25% of the 1800px canvas is blank dead space below the legend — the chart + content only occupies roughly the top 75% of canvas height; tune margin/margin_bottom + to use the full canvas while staying at 3200x1800 + - Legend swatch rendered flush against label text with no spacing (pygal rendering + quirk) — adjust margin or legend sizing to compensate + - No annotation or emphasis distinguishes the Legal regression outlier (-3) — consider + using Imprint matte red (#AE3030) for negative-delta connectors to improve data + storytelling + image_description: |- + Light render (plot-light.png): + Background: Warm off-white (#FAF8F1) — correct, not pure white + Chrome: Title "Employee Satisfaction · dumbbell-basic · python · pygal · anyplot.ai" in dark text, spans ~78% of plot width (expected for 70-char title). Y-axis label "Department" and x-axis label "Satisfaction Score (out of 100)" both dark and readable. Category tick labels with delta annotations (e.g. "Customer Support (+24)") clearly visible. Legend at bottom shows two swatches with labels "Before policy change" / "After policy change". + Data: Brand green (#009E73) dots for before-policy, Imprint lavender (#C475FD) dots for after-policy; thin gray INK_SOFT connector lines. 9 department rows sorted by improvement descending. All elements distinguishable from background. + Layout note: approximately bottom 25% of canvas is blank below the legend. + Legibility verdict: PASS + + Dark render (plot-dark.png): + Background: Warm near-black (#1A1A17) — correct, not pure black + Chrome: Title and all axis/tick/legend text render in light cream-white tones, clearly visible against dark background. No dark-on-dark failures. Connector lines appear as subtle medium-gray (INK_SOFT dark-theme value). + Data: Data colors identical to light render — brand green and lavender dots consistent; only chrome has flipped to dark-theme values. Brand green #009E73 clearly visible on dark surface. + Legibility verdict: PASS + criteria_checklist: + visual_quality: + score: 28 + max: 30 + items: + - id: VQ-01 + name: Text Legibility + score: 7 + max: 8 + passed: true + comment: 'Font sizes explicitly set and readable in both themes; title scales + correctly for 70-char title; minor: some mid-chart category labels appear + slightly lighter weight' + - id: VQ-02 + name: No Overlap + score: 6 + max: 6 + passed: true + comment: No overlap between text, data elements, or legend + - id: VQ-03 + name: Element Visibility + score: 6 + max: 6 + passed: true + comment: 9 sparse data points with large dots (dots_size=24) are highly prominent; + connector lines thin and visible; both series colors clear on both backgrounds + - id: VQ-04 + name: Color Accessibility + score: 2 + max: 2 + passed: true + comment: Imprint palette; green/lavender pair is CVD-safe; before/after encoding + uses positional differentiation not color alone + - id: VQ-05 + name: Layout & Canvas + score: 3 + max: 4 + passed: true + comment: Canvas correct 3200x1800; chart content fills only ~75% of canvas + height leaving ~25% blank below legend + - id: VQ-06 + name: Axis Labels & Title + score: 2 + max: 2 + passed: true + comment: X-axis includes units (out of 100); Y-axis label appropriate; title + follows descriptive-prefix format + - id: VQ-07 + name: Palette Compliance + score: 2 + max: 2 + passed: true + comment: 'Before = #009E73 (Imprint position 1), After = #C475FD (Imprint + position 2); backgrounds correct #FAF8F1 / #1A1A17; data colors identical + across both renders' + design_excellence: + score: 12 + max: 20 + items: + - id: DE-01 + name: Aesthetic Sophistication + score: 5 + max: 8 + passed: true + comment: 'Above default (4): delta annotations in category labels and sort-by-improvement + show intentional design; limited by pygal rendering options' + - id: DE-02 + name: Visual Refinement + score: 3 + max: 6 + passed: true + comment: 'Above default (2): no grid lines, warm backgrounds, subtle connectors; + legend swatch has no spacing before text (pygal quirk); bottom blank space + reduces refinement score' + - id: DE-03 + name: Data Storytelling + score: 4 + max: 6 + passed: true + comment: 'Above default (2): sorted descending by improvement creates readable + ranking; Legal regression (-3) is strong narrative outlier; delta labels + scannable without x-axis; no annotation or color emphasis on outlier' + 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) with two dots per + row linked by connector line + - id: SC-02 + name: Required Features + score: 4 + max: 4 + passed: true + comment: Horizontal orientation, distinct colors for start/end, sorted by + difference, thin subtle connectors — all present + - id: SC-03 + name: Data Mapping + score: 3 + max: 3 + passed: true + comment: X = satisfaction score (xrange 35-95 covers all data), Y = departments + (all 9 rows), two series mapped correctly + - id: SC-04 + name: Title & Legend + score: 3 + max: 3 + passed: true + comment: Title follows descriptive+spec-id+python+pygal+anyplot.ai format; + legend labels are descriptive + data_quality: + score: 15 + max: 15 + items: + - id: DQ-01 + name: Feature Coverage + score: 6 + max: 6 + passed: true + comment: Two connected dots per category, includes both improvement and regression + cases, delta shown in labels + - id: DQ-02 + name: Realistic Context + score: 5 + max: 5 + passed: true + comment: Employee satisfaction (0-100 scale) before/after policy change in + 9 plausible corporate departments; neutral and realistic + - id: DQ-03 + name: Appropriate Scale + score: 4 + max: 4 + passed: true + comment: Scores 45-85, deltas -3 to +24; 9 categories within spec's 5-20 optimal + range + code_quality: + score: 10 + max: 10 + items: + - id: CQ-01 + name: KISS Structure + score: 3 + max: 3 + passed: true + comment: No functions or classes; linear structure; clean list comprehensions + - id: CQ-02 + name: Reproducibility + score: 2 + max: 2 + passed: true + comment: All data hardcoded; fully deterministic + - id: CQ-03 + name: Clean Imports + score: 2 + max: 2 + passed: true + comment: All imports used; sys.path manipulation justified with comment + - id: CQ-04 + name: Code Elegance + score: 2 + max: 2 + passed: true + comment: Title font scaling formula clear; zip-with-strict throughout; delta + label generation readable + - id: CQ-05 + name: Output & API + score: 1 + max: 1 + passed: true + comment: Saves plot-{THEME}.png and plot-{THEME}.html; interactive HTML correctly + included + library_mastery: + score: 7 + max: 10 + items: + - id: LM-01 + name: Idiomatic Usage + score: 4 + max: 5 + passed: true + comment: pygal.XY used idiomatically for coordinate-based scatter; Style object + carries all theme tokens; per-series stroke/show_dots overrides are idiomatic + pygal + - id: LM-02 + name: Distinctive Features + score: 3 + max: 5 + passed: true + comment: Uses y_labels dict with label/value for custom tick positioning; + truncate_label/legend=-1 to disable truncation; legend_at_bottom_columns=2; + HTML output exploits pygal interactive rendering + verdict: APPROVED +impl_tags: + dependencies: [] + techniques: + - html-export + - manual-ticks + patterns: + - iteration-over-groups + dataprep: [] + styling: [] From c4476befd05edb5295f6884f6b526e58d8e3b9ab Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Tue, 30 Jun 2026 23:04:04 +0000 Subject: [PATCH 4/5] fix(pygal): address review feedback for dumbbell-basic Attempt 1/3 - fixes based on AI review --- plots/dumbbell-basic/implementations/python/pygal.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/plots/dumbbell-basic/implementations/python/pygal.py b/plots/dumbbell-basic/implementations/python/pygal.py index 497115136c..f814dd122d 100644 --- a/plots/dumbbell-basic/implementations/python/pygal.py +++ b/plots/dumbbell-basic/implementations/python/pygal.py @@ -1,4 +1,4 @@ -""" anyplot.ai +"""anyplot.ai dumbbell-basic: Basic Dumbbell Chart Library: pygal 3.1.3 | Python 3.13.14 Quality: 87/100 | Updated: 2026-06-30 @@ -28,6 +28,7 @@ BEFORE = "#009E73" # Imprint position 1 — brand green, always first series AFTER = "#C475FD" # Imprint position 2 — lavender CONNECTOR = INK_SOFT # theme-adaptive neutral connector line +LOSS_COLOR = "#AE3030" # Imprint matte red — semantic anchor for regression/bad outcomes # Data — employee satisfaction scores before and after new workplace policy categories = [ @@ -66,8 +67,9 @@ ratio = 67 / n_chars if n_chars > 67 else 1.0 title_font_size = max(44, round(66 * ratio)) # ≈ 63 -# Color sequence: n neutral connectors then brand green + lavender for dots -colors_tuple = (CONNECTOR,) * n + (BEFORE, AFTER) +# Color sequence: neutral connectors (red for negative deltas), then dot colors +connector_colors = tuple(LOSS_COLOR if a < b else CONNECTOR for b, a in zip(before, after, strict=True)) +colors_tuple = connector_colors + (BEFORE, AFTER) custom_style = Style( background=PAGE_BG, @@ -98,6 +100,7 @@ legend_at_bottom_columns=2, legend_box_size=44, margin=80, + margin_bottom=20, show_x_guides=False, show_y_guides=False, xrange=(35, 95), From 0cde233dedf590ff4aea7509d6afe75d3c6603fb Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Tue, 30 Jun 2026 23:10:43 +0000 Subject: [PATCH 5/5] chore(pygal): update quality score 88 and review feedback for dumbbell-basic --- .../implementations/python/pygal.py | 4 +- .../dumbbell-basic/metadata/python/pygal.yaml | 160 +++++++++--------- 2 files changed, 81 insertions(+), 83 deletions(-) diff --git a/plots/dumbbell-basic/implementations/python/pygal.py b/plots/dumbbell-basic/implementations/python/pygal.py index f814dd122d..102d7cb7e7 100644 --- a/plots/dumbbell-basic/implementations/python/pygal.py +++ b/plots/dumbbell-basic/implementations/python/pygal.py @@ -1,7 +1,7 @@ -"""anyplot.ai +""" anyplot.ai dumbbell-basic: Basic Dumbbell Chart Library: pygal 3.1.3 | Python 3.13.14 -Quality: 87/100 | Updated: 2026-06-30 +Quality: 88/100 | Updated: 2026-06-30 """ import os diff --git a/plots/dumbbell-basic/metadata/python/pygal.yaml b/plots/dumbbell-basic/metadata/python/pygal.yaml index 2e3daabc7e..0a7d12277c 100644 --- a/plots/dumbbell-basic/metadata/python/pygal.yaml +++ b/plots/dumbbell-basic/metadata/python/pygal.yaml @@ -2,7 +2,7 @@ library: pygal language: python specification_id: dumbbell-basic created: '2025-12-23T13:02:31Z' -updated: '2026-06-30T23:00:35Z' +updated: '2026-06-30T23:10:43Z' generated_by: claude-sonnet workflow_run: 28480823048 issue: 945 @@ -12,45 +12,40 @@ preview_url_light: https://storage.googleapis.com/anyplot-images/plots/dumbbell- preview_url_dark: https://storage.googleapis.com/anyplot-images/plots/dumbbell-basic/python/pygal/plot-dark.png preview_html_light: https://storage.googleapis.com/anyplot-images/plots/dumbbell-basic/python/pygal/plot-light.html preview_html_dark: https://storage.googleapis.com/anyplot-images/plots/dumbbell-basic/python/pygal/plot-dark.html -quality_score: 87 +quality_score: 88 review: strengths: - - 'Perfect Imprint palette usage: brand green (#009E73) first, lavender (#C475FD) - second, connector uses theme-adaptive INK_SOFT' - - 'Strong data storytelling: sort-by-improvement plus delta labels in category names - gives at-a-glance ranking without reading the x-axis' - - Includes regression outlier (Legal -3) making the dataset realistic and narratively - interesting - - 'Full spec compliance: horizontal orientation, distinct two-color encoding, thin - connectors, sorted layout' - - 'Excellent code quality: deterministic, no dead code, idiomatic pygal patterns, - sys.path workaround clearly explained' - - Both themes render correctly with no dark-on-dark or light-on-light failures + - Delta annotations embedded in Y-axis category labels (e.g., '+24', '-3') provide + at-a-glance insight without cluttering the chart with separate annotation elements + - Sort by improvement descending creates a clear top-to-bottom narrative; Legal's + regression naturally falls to the bottom + - Semantically correct LOSS_COLOR (#AE3030) applied to regression connector, with + all improvement connectors using theme-adaptive neutral (INK_SOFT) + - Both PNG and interactive HTML generated, leveraging pygal's core differentiator + - 'Full theme-adaptive chrome: title, labels, ticks, connectors, and legend all + flip correctly between light (#FAF8F1) and dark (#1A1A17) surfaces' weaknesses: - - Bottom ~25% of the 1800px canvas is blank dead space below the legend — the chart - content only occupies roughly the top 75% of canvas height; tune margin/margin_bottom - to use the full canvas while staying at 3200x1800 - - Legend swatch rendered flush against label text with no spacing (pygal rendering - quirk) — adjust margin or legend sizing to compensate - - No annotation or emphasis distinguishes the Legal regression outlier (-3) — consider - using Imprint matte red (#AE3030) for negative-delta connectors to improve data - storytelling + - The LOSS_COLOR red connector on the Legal (-3) regression row is ambiguous at + rendered scale — 5px connector width and muted red may not visually pop against + neutral connectors; consider wider stroke (width=8) for the regression case + - No X-axis grid guides (show_x_guides=False) reduces value-reading precision for + a comparison chart where exact score differences matter — enable show_x_guides=True + with subtle foreground_subtle color image_description: |- Light render (plot-light.png): - Background: Warm off-white (#FAF8F1) — correct, not pure white - Chrome: Title "Employee Satisfaction · dumbbell-basic · python · pygal · anyplot.ai" in dark text, spans ~78% of plot width (expected for 70-char title). Y-axis label "Department" and x-axis label "Satisfaction Score (out of 100)" both dark and readable. Category tick labels with delta annotations (e.g. "Customer Support (+24)") clearly visible. Legend at bottom shows two swatches with labels "Before policy change" / "After policy change". - Data: Brand green (#009E73) dots for before-policy, Imprint lavender (#C475FD) dots for after-policy; thin gray INK_SOFT connector lines. 9 department rows sorted by improvement descending. All elements distinguishable from background. - Layout note: approximately bottom 25% of canvas is blank below the legend. - Legibility verdict: PASS + Background: Warm off-white (#FAF8F1) — correct light surface + Chrome: Title "Employee Satisfaction · dumbbell-basic · python · pygal · anyplot.ai" in dark ink at ~75-80% plot width (expected for long mandated title). Y-axis category labels with embedded delta annotations (e.g., "Customer Support (+24)") in dark text. X-axis label "Satisfaction Score (out of 100)" readable. Y-axis title "Department" vertically rotated and readable. Tick labels (35, 40, 50, 60, 70, 80, 90) all visible. Legend at bottom: "Before policy change" / "After policy change" with matching swatches. + Data: Before-policy dots in brand green (#009E73); after-policy dots in lavender (#C475FD). Connector lines in neutral gray (INK_SOFT). Legal (-3) regression connector specified as LOSS_COLOR #AE3030 but may be ambiguous at render scale. Dots size=24 large and clearly visible. + Legibility verdict: PASS — all text readable against light background. No light-on-light issues. Dark render (plot-dark.png): - Background: Warm near-black (#1A1A17) — correct, not pure black - Chrome: Title and all axis/tick/legend text render in light cream-white tones, clearly visible against dark background. No dark-on-dark failures. Connector lines appear as subtle medium-gray (INK_SOFT dark-theme value). - Data: Data colors identical to light render — brand green and lavender dots consistent; only chrome has flipped to dark-theme values. Brand green #009E73 clearly visible on dark surface. - Legibility verdict: PASS + Background: Warm near-black (#1A1A17) — correct dark surface + Chrome: All chrome elements correctly flipped to light text. Title, axis labels, tick labels, and legend text rendered in light-colored ink against the dark surface. No dark-on-dark failures observed. + Data: Data colors (green #009E73 and lavender #C475FD) visually identical to light render — only chrome flipped, consistent with Imprint palette rules. Brand green clearly visible on dark background. + Legibility verdict: PASS — all text readable against dark background. No dark-on-dark failures. criteria_checklist: visual_quality: - score: 28 + score: 29 max: 30 items: - id: VQ-01 @@ -58,51 +53,52 @@ review: score: 7 max: 8 passed: true - comment: 'Font sizes explicitly set and readable in both themes; title scales - correctly for 70-char title; minor: some mid-chart category labels appear - slightly lighter weight' + comment: 'All text readable in both themes. Title scaled to 63px for 70-char + length. Minor: ''Operations (+15)'' appears very slightly lighter in light + render, likely font-rendering artifact.' - id: VQ-02 name: No Overlap score: 6 max: 6 passed: true - comment: No overlap between text, data elements, or legend + comment: No text overlaps with other text or data elements. Category labels + well-spaced. - id: VQ-03 name: Element Visibility score: 6 max: 6 passed: true - comment: 9 sparse data points with large dots (dots_size=24) are highly prominent; - connector lines thin and visible; both series colors clear on both backgrounds + comment: Dots at size=24 large and clearly visible for 9-category sparse data. + Connectors at width=5 appropriately subtle. - id: VQ-04 name: Color Accessibility score: 2 max: 2 passed: true - comment: Imprint palette; green/lavender pair is CVD-safe; before/after encoding - uses positional differentiation not color alone + comment: Green (#009E73) and lavender (#C475FD) from Imprint palette, CVD-safe. + LOSS_COLOR not sole distinguishing signal. - id: VQ-05 name: Layout & Canvas - score: 3 + score: 4 max: 4 passed: true - comment: Canvas correct 3200x1800; chart content fills only ~75% of canvas - height leaving ~25% blank below legend + comment: Canvas 3200x1800 gate passed. Title proportions correct. Balanced + axis labels. Generous margins. No overflow or clipping. - id: VQ-06 name: Axis Labels & Title score: 2 max: 2 passed: true - comment: X-axis includes units (out of 100); Y-axis label appropriate; title - follows descriptive-prefix format + comment: '''Satisfaction Score (out of 100)'' descriptive with units; ''Department'' + clear. Title follows mandated format with optional descriptive prefix.' - id: VQ-07 name: Palette Compliance score: 2 max: 2 passed: true - comment: 'Before = #009E73 (Imprint position 1), After = #C475FD (Imprint - position 2); backgrounds correct #FAF8F1 / #1A1A17; data colors identical - across both renders' + comment: 'Before-dots: #009E73 (Imprint position 1). After-dots: #C475FD (Imprint + position 2). Connectors: theme-adaptive INK_SOFT. LOSS_COLOR: #AE3030 (Imprint + position 5) for regression. Backgrounds correct.' design_excellence: score: 12 max: 20 @@ -112,24 +108,24 @@ review: score: 5 max: 8 passed: true - comment: 'Above default (4): delta annotations in category labels and sort-by-improvement - show intentional design; limited by pygal rendering options' + comment: Above default. Delta annotations in labels, intentional sort order, + semantic LOSS_COLOR, correct Imprint palette. Good design intent beyond + defaults. - id: DE-02 name: Visual Refinement score: 3 max: 6 passed: true - comment: 'Above default (2): no grid lines, warm backgrounds, subtle connectors; - legend swatch has no spacing before text (pygal quirk); bottom blank space - reduces refinement score' + comment: No grid lines appropriate for sparse data. Minimal framing. Legend + at bottom with 2-column layout. Better than minimal but not exceptional. - id: DE-03 name: Data Storytelling score: 4 max: 6 passed: true - comment: 'Above default (2): sorted descending by improvement creates readable - ranking; Legal regression (-3) is strong narrative outlier; delta labels - scannable without x-axis; no annotation or color emphasis on outlier' + comment: 'Strong storytelling: sort by improvement top-to-bottom narrative, + delta labels for instant reading, semantic red on regression connector as + focal-point indicator.' spec_compliance: score: 15 max: 15 @@ -139,29 +135,30 @@ review: score: 5 max: 5 passed: true - comment: Correct horizontal dumbbell (connected dot plot) with two dots per - row linked by connector line + comment: 'Correct dumbbell chart: two dots per category connected by line, + horizontal orientation, categories on Y-axis.' - id: SC-02 name: Required Features score: 4 max: 4 passed: true comment: Horizontal orientation, distinct colors for start/end, sorted by - difference, thin subtle connectors — all present + difference, subtle connecting lines — all present. - id: SC-03 name: Data Mapping score: 3 max: 3 passed: true - comment: X = satisfaction score (xrange 35-95 covers all data), Y = departments - (all 9 rows), two series mapped correctly + comment: Categories on Y-axis, scores on X-axis (35-95 range covers all data), + all 9 departments displayed. - id: SC-04 name: Title & Legend score: 3 max: 3 passed: true - comment: Title follows descriptive+spec-id+python+pygal+anyplot.ai format; - legend labels are descriptive + comment: Title 'Employee Satisfaction · dumbbell-basic · python · pygal · + anyplot.ai' with optional descriptive prefix. Legend shows correct series + names with matching swatches. data_quality: score: 15 max: 15 @@ -171,22 +168,22 @@ review: score: 6 max: 6 passed: true - comment: Two connected dots per category, includes both improvement and regression - cases, delta shown in labels + comment: Before/after dots, connecting lines, sort by delta, delta in labels, + LOSS_COLOR for regression, 9 categories (within 5-20 range). Complete coverage. - id: DQ-02 name: Realistic Context score: 5 max: 5 passed: true - comment: Employee satisfaction (0-100 scale) before/after policy change in - 9 plausible corporate departments; neutral and realistic + comment: Employee satisfaction before/after workplace policy — neutral, plausible, + widely recognizable. Named real departments. - id: DQ-03 name: Appropriate Scale score: 4 max: 4 passed: true - comment: Scores 45-85, deltas -3 to +24; 9 categories within spec's 5-20 optimal - range + comment: Scores 45-85 out of 100. Improvements +6 to +24, one regression -3 + — realistic satisfaction survey magnitudes. code_quality: score: 10 max: 10 @@ -196,33 +193,34 @@ review: score: 3 max: 3 passed: true - comment: No functions or classes; linear structure; clean list comprehensions + comment: No functions or classes. Flat, sequential script. - id: CQ-02 name: Reproducibility score: 2 max: 2 passed: true - comment: All data hardcoded; fully deterministic + comment: Fully deterministic hardcoded data. - id: CQ-03 name: Clean Imports score: 2 max: 2 passed: true - comment: All imports used; sys.path manipulation justified with comment + comment: os, sys, pathlib.Path (for sys.path fix), pygal, pygal.style.Style + — all used. - id: CQ-04 name: Code Elegance score: 2 max: 2 passed: true - comment: Title font scaling formula clear; zip-with-strict throughout; delta - label generation readable + comment: sys.path manipulation is a legitimate workaround for name collision, + correctly labeled. Title font-size scaling formula handles the long mandated + title. Dynamic delta-label generation clean. - id: CQ-05 name: Output & API score: 1 max: 1 passed: true - comment: Saves plot-{THEME}.png and plot-{THEME}.html; interactive HTML correctly - included + comment: Saves plot-{THEME}.png and plot-{THEME}.html correctly. library_mastery: score: 7 max: 10 @@ -232,17 +230,17 @@ review: score: 4 max: 5 passed: true - comment: pygal.XY used idiomatically for coordinate-based scatter; Style object - carries all theme tokens; per-series stroke/show_dots overrides are idiomatic - pygal + comment: pygal.XY for scatter-based dumbbell is correct. y_labels with dict + format (label/value) for categorical Y-axis is idiomatic. Per-series stroke/dots_size + overrides used correctly. - id: LM-02 name: Distinctive Features score: 3 max: 5 passed: true - comment: Uses y_labels dict with label/value for custom tick positioning; - truncate_label/legend=-1 to disable truncation; legend_at_bottom_columns=2; - HTML output exploits pygal interactive rendering + comment: Generates both PNG and interactive HTML (pygal's main differentiator). + Interactive tooltips via per-point label property. legend_at_bottom_columns + leverages pygal's layout API. verdict: APPROVED impl_tags: dependencies: []