From c95afdc3afc5db02ad5da4687b11f568afe92e94 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 1 Jul 2026 05:59:23 +0000 Subject: [PATCH 1/5] feat(bokeh): implement lollipop-basic MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Regen from quality 85. Addressed: - Canvas: corrected width/height from 4800×2700 to canonical 3200×1800 - Export: replaced broken export_png with Selenium screenshot + PIL crop - Font sizes: updated to 50pt/42pt/34pt per bokeh.md (was 28/22/18pt) - Title: set text_font_style=bold (was normal) - min_border_*: added canonical reservations for label room - Data storytelling (DE-03 ❌→✅): added value labels above markers + avg reference line - Change request: replaced product categories (same as matplotlib sibling) with cloud infrastructure spend (Compute→Monitoring, descending $94K–$6K) - sys.path fix: prevent bokeh.py from shadowing the installed bokeh package --- .../implementations/python/bokeh.py | 149 +++++++++++++----- 1 file changed, 111 insertions(+), 38 deletions(-) diff --git a/plots/lollipop-basic/implementations/python/bokeh.py b/plots/lollipop-basic/implementations/python/bokeh.py index b0da1d8704..f67776b73e 100644 --- a/plots/lollipop-basic/implementations/python/bokeh.py +++ b/plots/lollipop-basic/implementations/python/bokeh.py @@ -1,91 +1,164 @@ -""" anyplot.ai +"""anyplot.ai lollipop-basic: Basic Lollipop Chart Library: bokeh 3.9.0 | Python 3.14.4 -Quality: 85/100 | Updated: 2026-04-26 """ +import sys + + +# This file is named bokeh.py; without this fix Python would import itself +# instead of the installed bokeh package when run directly. +if sys.path and sys.path[0] not in ("", None): + sys.path.append(sys.path.pop(0)) + +import io import os +import time +from pathlib import Path -from bokeh.io import export_png, output_file, save -from bokeh.models import ColumnDataSource, NumeralTickFormatter +from bokeh.io import output_file, save +from bokeh.models import ColumnDataSource, NumeralTickFormatter, Range1d, Span from bokeh.plotting import figure +from PIL import Image +from selenium import webdriver +from selenium.webdriver.chrome.options import Options -# Theme tokens +# Imprint palette + theme tokens THEME = os.getenv("ANYPLOT_THEME", "light") PAGE_BG = "#FAF8F1" if THEME == "light" else "#1A1A17" -ELEVATED_BG = "#FFFDF6" if THEME == "light" else "#242420" INK = "#1A1A17" if THEME == "light" else "#F0EFE8" INK_SOFT = "#4A4A44" if THEME == "light" else "#B8B7B0" -BRAND = "#009E73" +INK_MUTED = "#6B6A63" if THEME == "light" else "#A8A79F" +BRAND = "#009E73" # Imprint palette position 1 — always first series -# Data — product sales by category (pre-sorted descending) +# Data — monthly cloud infrastructure spend by service category (sorted descending) categories = [ - "Electronics", - "Clothing", - "Home & Garden", - "Sports", - "Books", - "Toys", - "Food", - "Beauty", - "Automotive", - "Office", + "Compute", + "Storage", + "Networking", + "Database", + "Security", + "Analytics", + "AI / ML", + "IoT", + "DevOps", + "Monitoring", ] -values = [85000, 72000, 61000, 53000, 47000, 39000, 33000, 28000, 22000, 15000] - -source = ColumnDataSource(data={"categories": categories, "values": values, "zeros": [0] * len(values)}) +values = [94200, 67500, 48300, 38800, 28400, 22100, 18700, 12900, 9600, 6800] +avg_spend = sum(values) / len(values) + +labels = [f"${v // 1000}K" for v in values] + +source = ColumnDataSource( + data={ + "categories": categories, + "values": values, + "zeros": [0] * len(values), + "labels": labels, + "label_y": [v + 2800 for v in values], + } +) -# Plot +# Figure p = figure( - width=4800, - height=2700, + width=3200, + height=1800, x_range=categories, + y_range=Range1d(0, 108000), title="lollipop-basic · bokeh · anyplot.ai", - x_axis_label="Product Category", - y_axis_label="Sales (USD)", + x_axis_label="Cloud Service", + y_axis_label="Monthly Spend (USD)", toolbar_location=None, + min_border_bottom=160, + min_border_left=180, + min_border_top=110, + min_border_right=80, ) +# Average reference line +p.add_layout(Span(location=avg_spend, dimension="width", line_color=INK_MUTED, line_width=3, line_dash="dashed")) + +# Stems p.segment(x0="categories", y0="zeros", x1="categories", y1="values", source=source, line_width=4, color=BRAND) +# Markers p.scatter(x="categories", y="values", source=source, size=42, color=BRAND, line_color=PAGE_BG, line_width=3) -# Style -p.title.text_font_size = "28pt" +# Value labels above each marker +p.text( + x="categories", + y="label_y", + text="labels", + source=source, + text_font_size="24pt", + text_align="center", + text_baseline="bottom", + text_color=INK_SOFT, +) + +# Title +p.title.text_font_size = "50pt" p.title.text_color = INK -p.title.text_font_style = "normal" +p.title.text_font_style = "bold" -p.xaxis.axis_label_text_font_size = "22pt" -p.yaxis.axis_label_text_font_size = "22pt" -p.xaxis.major_label_text_font_size = "18pt" -p.yaxis.major_label_text_font_size = "18pt" +# Axis label sizes +p.xaxis.axis_label_text_font_size = "42pt" +p.yaxis.axis_label_text_font_size = "42pt" +p.xaxis.major_label_text_font_size = "34pt" +p.yaxis.major_label_text_font_size = "34pt" +# Axis label colors p.xaxis.axis_label_text_color = INK p.yaxis.axis_label_text_color = INK p.xaxis.major_label_text_color = INK_SOFT p.yaxis.major_label_text_color = INK_SOFT +# Axis line and tick colors p.xaxis.axis_line_color = INK_SOFT p.yaxis.axis_line_color = INK_SOFT p.xaxis.major_tick_line_color = INK_SOFT p.yaxis.major_tick_line_color = INK_SOFT p.xaxis.minor_tick_line_color = None p.yaxis.minor_tick_line_color = None +p.xaxis.major_label_orientation = 0.5 -p.xaxis.major_label_orientation = 0.6 - +# Grid — y-axis only, subtle p.xgrid.grid_line_color = None p.ygrid.grid_line_color = INK p.ygrid.grid_line_alpha = 0.10 +# Background and chrome p.background_fill_color = PAGE_BG p.border_fill_color = PAGE_BG -p.outline_line_color = None +p.outline_line_color = INK_SOFT +# Y-axis tick format p.yaxis.formatter = NumeralTickFormatter(format="$0,0") -# Save -export_png(p, filename=f"plot-{THEME}.png") +# Save HTML (interactive catalog artifact) output_file(f"plot-{THEME}.html") save(p) + +# Screenshot with headless Chrome — Selenium 4 / Selenium Manager resolves the driver. +# Chrome's headless viewport is ~143px shorter than --window-size due to internal +# overhead; use an oversized window then crop to the exact canvas target. +W, H = 3200, 1800 +CHROME_H = H + 200 +opts = Options() +for arg in ( + "--headless=new", + "--no-sandbox", + "--disable-dev-shm-usage", + "--disable-gpu", + f"--window-size={W},{CHROME_H}", + "--hide-scrollbars", +): + opts.add_argument(arg) +driver = webdriver.Chrome(options=opts) +driver.set_window_size(W, CHROME_H) +driver.get(f"file://{Path(f'plot-{THEME}.html').resolve()}") +time.sleep(3) +# The bokeh figure starts at (0, 0); crop screenshot to exact canvas dimensions +Image.open(io.BytesIO(driver.get_screenshot_as_png())).crop((0, 0, W, H)).save(f"plot-{THEME}.png") +driver.quit() From 211f32e771f3927ca1ddbfeb7d23933fbc14a787 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 1 Jul 2026 05:59:34 +0000 Subject: [PATCH 2/5] chore(bokeh): add metadata for lollipop-basic --- .../lollipop-basic/metadata/python/bokeh.yaml | 224 +----------------- 1 file changed, 11 insertions(+), 213 deletions(-) diff --git a/plots/lollipop-basic/metadata/python/bokeh.yaml b/plots/lollipop-basic/metadata/python/bokeh.yaml index addd40cc5a..494f0356e9 100644 --- a/plots/lollipop-basic/metadata/python/bokeh.yaml +++ b/plots/lollipop-basic/metadata/python/bokeh.yaml @@ -1,223 +1,21 @@ +# Per-library metadata for bokeh implementation of lollipop-basic +# Auto-generated by impl-generate.yml + library: bokeh language: python specification_id: lollipop-basic created: '2025-12-23T15:14:01Z' -updated: '2026-04-26T12:54:40Z' -generated_by: claude-opus -workflow_run: 24956899574 +updated: '2026-07-01T05:59:34Z' +generated_by: claude-sonnet +workflow_run: 28496532200 issue: 934 -python_version: 3.14.4 -library_version: 3.9.0 +language_version: 3.13.14 +library_version: 3.9.1 preview_url_light: https://storage.googleapis.com/anyplot-images/plots/lollipop-basic/python/bokeh/plot-light.png preview_url_dark: https://storage.googleapis.com/anyplot-images/plots/lollipop-basic/python/bokeh/plot-dark.png preview_html_light: https://storage.googleapis.com/anyplot-images/plots/lollipop-basic/python/bokeh/plot-light.html preview_html_dark: https://storage.googleapis.com/anyplot-images/plots/lollipop-basic/python/bokeh/plot-dark.html -quality_score: 85 +quality_score: null review: - strengths: - - 'Perfect spec compliance: stems + markers + sorted data + correct title format' - - 'Excellent theme adaptation: all chrome tokens applied correctly, both renders - pass legibility check' - - Clean minimal code with proper KISS structure - - White-ring detail on markers (PAGE_BG as line_color) adds visual separation - - NumeralTickFormatter adds professional dollar formatting - weaknesses: - - 'No data storytelling: sorted data is good but no emphasis on top performer, no - focal points, no value labels, no visual hierarchy to guide the viewer' - - 'Title not bold: style guide specifies bold/medium-weight for titles, text_font_style=normal - weakens typographic hierarchy' - - 'Design sophistication stays at well-configured default level: white ring on markers - is the only distinctive aesthetic choice' - image_description: |- - Light render (plot-light.png): - Background: Warm off-white #FAF8F1 — correct, not pure white - Chrome: Title "lollipop-basic · bokeh · anyplot.ai" top-left in dark INK color, readable; axis labels "Sales (USD)" and "Product Category" in dark INK, readable; y-axis tick labels in INK_SOFT ($0, $20,000, $40,000, etc.), readable; x-axis category labels rotated and readable - Data: 10 lollipops in brand green #009E73 — thin stems (line_width=4) rising from y=0 baseline to large circular markers (size=42) with white PAGE_BG ring; values sorted descending Electronics ($85K) to Office ($15K) - Legibility verdict: PASS — all text readable, no light-on-light failures - - Dark render (plot-dark.png): - Background: Near-black #1A1A17 — correct, not pure black - Chrome: Title in light F0EFE8 text, readable; axis labels in INK color (light), readable; tick labels in INK_SOFT (B8B7B0), readable; no dark-on-dark failures detected - Data: Brand green #009E73 lollipops identical to light render — stems, markers, and white ring all unchanged; only background and text colors flip - Legibility verdict: PASS — all text readable against dark background, data colors identical to light render - criteria_checklist: - visual_quality: - score: 28 - max: 30 - items: - - id: VQ-01 - name: Text Legibility - score: 7 - max: 8 - passed: true - comment: Sizes explicitly set (28pt/22pt/18pt), readable in both themes; title - not bold - - id: VQ-02 - name: No Overlap - score: 6 - max: 6 - passed: true - comment: Rotated x-axis labels well-spaced, no collisions - - id: VQ-03 - name: Element Visibility - score: 6 - max: 6 - passed: true - comment: Stems line_width=4 and markers size=42 clearly visible - - id: VQ-04 - name: Color Accessibility - score: 2 - max: 2 - passed: true - comment: Single brand green series, good contrast, CVD-safe - - id: VQ-05 - name: Layout & Canvas - score: 3 - max: 4 - passed: true - comment: Decent canvas utilization, minor empty space in upper plot area - - id: VQ-06 - name: Axis Labels & Title - score: 2 - max: 2 - passed: true - comment: Sales (USD) and Product Category with units - - id: VQ-07 - name: Palette Compliance - score: 2 - max: 2 - passed: true - comment: 'First series #009E73, light #FAF8F1, dark #1A1A17, chrome correct' - design_excellence: - score: 10 - max: 20 - items: - - id: DE-01 - name: Aesthetic Sophistication - score: 4 - max: 8 - passed: false - comment: Well-configured default with white ring on markers; not exceptional - design - - id: DE-02 - name: Visual Refinement - score: 4 - max: 6 - passed: true - comment: No x-grid, subtle y-grid, no outline, minor ticks removed, no toolbar - - id: DE-03 - name: Data Storytelling - score: 2 - max: 6 - passed: false - comment: Sorted data but no visual hierarchy, focal points, or emphasis - spec_compliance: - score: 15 - max: 15 - items: - - id: SC-01 - name: Plot Type - score: 5 - max: 5 - passed: true - comment: 'Correct lollipop: segment stems + scatter markers, vertical orientation' - - id: SC-02 - name: Required Features - score: 4 - max: 4 - passed: true - comment: Stems, markers, vertical, 10 categories, sorted descending - - id: SC-03 - name: Data Mapping - score: 3 - max: 3 - passed: true - comment: Categories on x with x_range, values on y, all data visible - - id: SC-04 - name: Title & Legend - score: 3 - max: 3 - passed: true - comment: Title lollipop-basic · bokeh · anyplot.ai correct; no legend for - single series - data_quality: - score: 15 - max: 15 - items: - - id: DQ-01 - name: Feature Coverage - score: 6 - max: 6 - passed: true - comment: 'All lollipop aspects shown: varying heights, sorted order, 10 categories' - - id: DQ-02 - name: Realistic Context - score: 5 - max: 5 - passed: true - comment: Product sales by category - natural neutral business scenario - - id: DQ-03 - name: Appropriate Scale - score: 4 - max: 4 - passed: true - comment: $15K-$85K realistic for product category sales, good spread - code_quality: - score: 10 - max: 10 - items: - - id: CQ-01 - name: KISS Structure - score: 3 - max: 3 - passed: true - comment: 'Linear: imports -> tokens -> data -> figure -> styling -> save' - - id: CQ-02 - name: Reproducibility - score: 2 - max: 2 - passed: true - comment: Deterministic hardcoded data - - id: CQ-03 - name: Clean Imports - score: 2 - max: 2 - passed: true - comment: All 4 imports used - - id: CQ-04 - name: Code Elegance - score: 2 - max: 2 - passed: true - comment: Clean Pythonic code, no fake UI - - id: CQ-05 - name: Output & API - score: 1 - max: 1 - passed: true - comment: plot-{THEME}.png and plot-{THEME}.html both generated - library_mastery: - score: 7 - max: 10 - items: - - id: LM-01 - name: Idiomatic Usage - score: 4 - max: 5 - passed: true - comment: ColumnDataSource, x_range for categorical, segment+scatter pattern - - id: LM-02 - name: Distinctive Features - score: 3 - max: 5 - passed: true - comment: NumeralTickFormatter and HTML export via output_file/save - verdict: REJECTED -impl_tags: - dependencies: [] - techniques: - - html-export - patterns: - - columndatasource - dataprep: [] - styling: [] + strengths: [] + weaknesses: [] From b7eeb3e82dc504bf21e26a7e457aad859931f283 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 1 Jul 2026 06:06:30 +0000 Subject: [PATCH 3/5] chore(bokeh): update quality score 88 and review feedback for lollipop-basic --- .../implementations/python/bokeh.py | 5 +- .../lollipop-basic/metadata/python/bokeh.yaml | 266 +++++++++++++++++- 2 files changed, 262 insertions(+), 9 deletions(-) diff --git a/plots/lollipop-basic/implementations/python/bokeh.py b/plots/lollipop-basic/implementations/python/bokeh.py index f67776b73e..8a1b9eeaef 100644 --- a/plots/lollipop-basic/implementations/python/bokeh.py +++ b/plots/lollipop-basic/implementations/python/bokeh.py @@ -1,6 +1,7 @@ -"""anyplot.ai +""" anyplot.ai lollipop-basic: Basic Lollipop Chart -Library: bokeh 3.9.0 | Python 3.14.4 +Library: bokeh 3.9.1 | Python 3.13.14 +Quality: 88/100 | Updated: 2026-07-01 """ import sys diff --git a/plots/lollipop-basic/metadata/python/bokeh.yaml b/plots/lollipop-basic/metadata/python/bokeh.yaml index 494f0356e9..9831ca6ed5 100644 --- a/plots/lollipop-basic/metadata/python/bokeh.yaml +++ b/plots/lollipop-basic/metadata/python/bokeh.yaml @@ -1,11 +1,8 @@ -# Per-library metadata for bokeh implementation of lollipop-basic -# Auto-generated by impl-generate.yml - library: bokeh language: python specification_id: lollipop-basic created: '2025-12-23T15:14:01Z' -updated: '2026-07-01T05:59:34Z' +updated: '2026-07-01T06:06:30Z' generated_by: claude-sonnet workflow_run: 28496532200 issue: 934 @@ -15,7 +12,262 @@ preview_url_light: https://storage.googleapis.com/anyplot-images/plots/lollipop- preview_url_dark: https://storage.googleapis.com/anyplot-images/plots/lollipop-basic/python/bokeh/plot-dark.png preview_html_light: https://storage.googleapis.com/anyplot-images/plots/lollipop-basic/python/bokeh/plot-light.html preview_html_dark: https://storage.googleapis.com/anyplot-images/plots/lollipop-basic/python/bokeh/plot-dark.html -quality_score: null +quality_score: 88 review: - strengths: [] - weaknesses: [] + strengths: + - 'Perfect visual quality: all font sizes explicitly set (50pt title, 42pt axis + labels, 34pt tick labels, 24pt value annotations), well-proportioned layout, readable + in both themes' + - 'Excellent data storytelling: dashed average reference line (Span) provides immediate + context for above/below-budget services; data sorted descending creates clear + visual ranking' + - Value labels above every lollipop head ($94K, $67K, …) eliminate the need to read + the y-axis for each bar, reducing cognitive load + - 'Idiomatic Bokeh usage: ColumnDataSource with named columns, Range1d for axis + bounds, NumeralTickFormatter for dollar ticks, Span for the reference line, proper + HTML + Selenium screenshot pipeline' + - Realistic, neutral cloud-spend dataset with plausible values ($6K–$94K/month), + deterministic data, and clean KISS code structure + - 'Correct Imprint palette compliance: brand green #009E73 for single series, #FAF8F1/#1A1A17 + backgrounds, full theme-adaptive chrome (INK/INK_SOFT tokens on all labels and + axes)' + weaknesses: + - 'SC-04: Title is missing the ''python'' language component. Required format: ''lollipop-basic + · python · bokeh · anyplot.ai''. Current title: ''lollipop-basic · bokeh · anyplot.ai''. + Fix: add '' · python'' between spec-id and library name in the title string.' + - 'DE-02: Full rectangular outline border (outline_line_color=INK_SOFT) creates + an all-four-sides box. Style guide prefers L-spine (remove top and right). Fix: + set p.outline_line_color=None and rely on p.xaxis.axis_line_color + p.yaxis.axis_line_color + for the bottom/left spines only.' + - 'DE-01: Design is above the generic default but not at ''strong design'' level + — could use one more differentiating touch, e.g. coloring lollipop heads above-average + vs below-average (brand green vs muted), or adding a subtle ''Average: $34.7K'' + text annotation to the reference line.' + image_description: |- + Light render (plot-light.png): + Background: Warm off-white consistent with #FAF8F1 — not pure white, not neutral grey. Correct theme surface. + Chrome: Title "lollipop-basic · bokeh · anyplot.ai" in bold dark text, clearly readable. X-axis label "Cloud Service" and Y-axis label "Monthly Spend (USD)" in Bokeh's default italic style, both readable in dark ink. Tick labels on x-axis (10 rotated category names) and y-axis ($0–$100,000 in dollar format) are readable in INK_SOFT. A subtle dashed horizontal reference line sits at approximately $35K (average spend). Rectangular outline border visible around the data area (all four sides in INK_SOFT). + Data: Brand green (#009E73) stems (vertical lines) and large filled circular markers for all 10 categories. Value annotations above each lollipop head ($94K, $67K, $48K, $38K, $28K, $22K, $18K, $12K, $9K, $6K) in INK_SOFT at 24pt. Data sorted descending from Compute to Monitoring. Y-axis grid lines only, subtle alpha ≈ 0.10. + Legibility verdict: PASS — all text clearly readable against the warm off-white background. No "light on light" failures. + + Dark render (plot-dark.png): + Background: Warm near-black consistent with #1A1A17 — not pure black. Correct theme surface. + Chrome: Title, axis labels, and tick labels rendered in light text (F0EFE8 / B8B7B0 range), clearly readable against the dark background. Reference line visible as a subtle dashed light-grey stroke. Same rectangular outline border visible in a lighter tone. + Data: Brand green (#009E73) stems and circular markers are identical in color to the light render — only chrome elements flipped. Value annotation labels visible in lighter text above each marker. Grid lines subtle and visible. + Legibility verdict: PASS — all text clearly readable against the warm near-black background. No dark-on-dark failures. Title, axis labels, tick labels, and value annotations all have adequate contrast. + 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: 50pt title, 42pt axis labels, 34pt + tick labels, 24pt value annotations. Balanced X/Y sizing. Readable in both + themes.' + - id: VQ-02 + name: No Overlap + score: 6 + max: 6 + passed: true + comment: No overlapping elements. Value labels clear of markers. Category + labels rotated to avoid collision. + - id: VQ-03 + name: Element Visibility + score: 6 + max: 6 + passed: true + comment: '10 data points (sparse): size=42 markers and line_width=4 stems + are appropriately prominent. Green pops against both backgrounds.' + - id: VQ-04 + name: Color Accessibility + score: 2 + max: 2 + passed: true + comment: 'Single series in brand green #009E73. High contrast on both surface + colors. CVD-safe.' + - id: VQ-05 + name: Layout & Canvas + score: 4 + max: 4 + passed: true + comment: Canvas 3200×1800 correct. min_border settings (160/180/110/80) provide + generous margins. Plot fills canvas well with no wasted space. + - id: VQ-06 + name: Axis Labels & Title + score: 2 + max: 2 + passed: true + comment: '''Cloud Service'' and ''Monthly Spend (USD)'' — descriptive with + units.' + - id: VQ-07 + name: Palette Compliance + score: 2 + max: 2 + passed: true + comment: 'Single series uses #009E73 (Imprint position 1). Backgrounds #FAF8F1 + (light) / #1A1A17 (dark). INK/INK_SOFT tokens used for all chrome. 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 a well-configured default: reference line, value annotations, + custom sizing, and coherent brand color. Not at ''strong design'' level + yet.' + - id: DE-02 + name: Visual Refinement + score: 3 + max: 6 + passed: true + comment: 'Y-axis-only grid, minor ticks removed, appropriate whitespace. Downside: + full rectangular outline border (outline_line_color=INK_SOFT) instead of + L-spine removes the minimalist top/right spine effect.' + - id: DE-03 + name: Data Storytelling + score: 4 + max: 6 + passed: true + comment: Average reference line immediately frames which services are above/below + budget. Sorted descending makes ranking obvious. Value labels reduce chart-reading + friction. + spec_compliance: + score: 13 + max: 15 + items: + - id: SC-01 + name: Plot Type + score: 5 + max: 5 + passed: true + comment: 'Correct lollipop chart: segment() for stems, scatter() for circular + markers at data values.' + - id: SC-02 + name: Required Features + score: 4 + max: 4 + passed: true + comment: Thin stems from baseline, circular markers, vertical orientation + (categories on x-axis), data sorted by value descending. All spec requirements + met. + - id: SC-03 + name: Data Mapping + score: 3 + max: 3 + passed: true + comment: 'X-axis: Cloud Service categories. Y-axis: Monthly Spend (USD). All + 10 data points visible.' + - id: SC-04 + name: Title & Legend + score: 1 + max: 3 + passed: false + comment: 'Title ''lollipop-basic · bokeh · anyplot.ai'' is missing the ''python'' + language component. Required: ''lollipop-basic · python · bokeh · anyplot.ai''. + No legend needed for single series (N/A).' + data_quality: + score: 15 + max: 15 + items: + - id: DQ-01 + name: Feature Coverage + score: 6 + max: 6 + passed: true + comment: '10 categories showing full range of lollipop chart features: variable + stem lengths, visible markers at different heights, value annotations.' + - id: DQ-02 + name: Realistic Context + score: 5 + max: 5 + passed: true + comment: Monthly cloud infrastructure spend by service category — real, neutral, + business context. + - id: DQ-03 + name: Appropriate Scale + score: 4 + max: 4 + passed: true + comment: $6K–$94K monthly spend per service is realistic for a mid-sized tech + company. Proportions between categories are plausible. + code_quality: + score: 10 + max: 10 + items: + - id: CQ-01 + name: KISS Structure + score: 3 + max: 3 + passed: true + comment: 'No functions or classes. Clean top-to-bottom: imports → tokens → + data → figure → styling → save.' + - id: CQ-02 + name: Reproducibility + score: 2 + max: 2 + passed: true + comment: Deterministic hardcoded dataset. No randomness. + - id: CQ-03 + name: Clean Imports + score: 2 + max: 2 + passed: true + comment: 'All imports used: io, os, time, pathlib, bokeh (figure, ColumnDataSource, + NumeralTickFormatter, Range1d, Span, output_file, save), PIL.Image, selenium.webdriver.' + - id: CQ-04 + name: Code Elegance + score: 2 + max: 2 + passed: true + comment: Clean and Pythonic. PIL crop trick for exact canvas dimensions is + an elegant workaround for Bokeh/Chrome headless sizing issue. + - id: CQ-05 + name: Output & API + score: 1 + max: 1 + passed: true + comment: Saves plot-{THEME}.png and plot-{THEME}.html. Uses current Bokeh + 3.9.0 API. + library_mastery: + score: 8 + max: 10 + items: + - id: LM-01 + name: Idiomatic Usage + score: 5 + max: 5 + passed: true + comment: 'Expertly uses Bokeh patterns: ColumnDataSource with named columns, + figure(x_range=categories) for categorical axis, segment()/scatter()/text() + glyph methods, Span layout model, Range1d, NumeralTickFormatter, full Selenium + screenshot pipeline.' + - id: LM-02 + name: Distinctive Features + score: 3 + max: 5 + passed: true + comment: Span layout model for reference line is distinctly Bokeh. NumeralTickFormatter + for dollar formatting. HTML export as a first-class artifact alongside the + PNG. Could leverage HoverTool for additional distinctiveness. + verdict: REJECTED +impl_tags: + dependencies: + - selenium + - pillow + techniques: + - annotations + - html-export + patterns: + - data-generation + - columndatasource + dataprep: [] + styling: + - grid-styling From d849477dc040a9e5b74998c7aa4c54535fbcb2ed Mon Sep 17 00:00:00 2001 From: "claude[bot]" <41898282+claude[bot]@users.noreply.github.com> Date: Wed, 1 Jul 2026 06:11:43 +0000 Subject: [PATCH 4/5] fix(bokeh): address review feedback for lollipop-basic MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Attempt 1/3 - fixes based on AI review - SC-04: add '· python ·' to title (was missing language component) - DE-02: remove full rectangular outline border; rely on axis_line_color for L-spine - DE-01: add 'Avg: $34.7K' text label to the average reference line --- .../implementations/python/bokeh.py | 23 +++++++++++++++---- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/plots/lollipop-basic/implementations/python/bokeh.py b/plots/lollipop-basic/implementations/python/bokeh.py index 8a1b9eeaef..cacaf1a1d6 100644 --- a/plots/lollipop-basic/implementations/python/bokeh.py +++ b/plots/lollipop-basic/implementations/python/bokeh.py @@ -1,4 +1,4 @@ -""" anyplot.ai +"""anyplot.ai lollipop-basic: Basic Lollipop Chart Library: bokeh 3.9.1 | Python 3.13.14 Quality: 88/100 | Updated: 2026-07-01 @@ -18,7 +18,7 @@ from pathlib import Path from bokeh.io import output_file, save -from bokeh.models import ColumnDataSource, NumeralTickFormatter, Range1d, Span +from bokeh.models import ColumnDataSource, Label, NumeralTickFormatter, Range1d, Span from bokeh.plotting import figure from PIL import Image from selenium import webdriver @@ -67,7 +67,7 @@ height=1800, x_range=categories, y_range=Range1d(0, 108000), - title="lollipop-basic · bokeh · anyplot.ai", + title="lollipop-basic · python · bokeh · anyplot.ai", x_axis_label="Cloud Service", y_axis_label="Monthly Spend (USD)", toolbar_location=None, @@ -77,8 +77,21 @@ min_border_right=80, ) -# Average reference line +# Average reference line + label p.add_layout(Span(location=avg_spend, dimension="width", line_color=INK_MUTED, line_width=3, line_dash="dashed")) +p.add_layout( + Label( + x=2880, + y=avg_spend, # screen x from plot-frame left; plot area = 3200-180-80=2940px wide + x_units="screen", + text=f"Avg: ${avg_spend / 1000:.1f}K", + text_font_size="22pt", + text_color=INK_MUTED, + text_align="right", + text_baseline="bottom", + y_offset=8, + ) +) # Stems p.segment(x0="categories", y0="zeros", x1="categories", y1="values", source=source, line_width=4, color=BRAND) @@ -132,7 +145,7 @@ # Background and chrome p.background_fill_color = PAGE_BG p.border_fill_color = PAGE_BG -p.outline_line_color = INK_SOFT +p.outline_line_color = None # L-spine only: x/y axis_line_color handle bottom+left # Y-axis tick format p.yaxis.formatter = NumeralTickFormatter(format="$0,0") From 1e86d5f28217b3e66bd644c7edae10f2bebe5327 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 1 Jul 2026 06:20:05 +0000 Subject: [PATCH 5/5] chore(bokeh): update quality score 91 and review feedback for lollipop-basic --- .../implementations/python/bokeh.py | 4 +- .../lollipop-basic/metadata/python/bokeh.yaml | 202 +++++++++--------- 2 files changed, 104 insertions(+), 102 deletions(-) diff --git a/plots/lollipop-basic/implementations/python/bokeh.py b/plots/lollipop-basic/implementations/python/bokeh.py index cacaf1a1d6..bc2a8a8fdc 100644 --- a/plots/lollipop-basic/implementations/python/bokeh.py +++ b/plots/lollipop-basic/implementations/python/bokeh.py @@ -1,7 +1,7 @@ -"""anyplot.ai +""" anyplot.ai lollipop-basic: Basic Lollipop Chart Library: bokeh 3.9.1 | Python 3.13.14 -Quality: 88/100 | Updated: 2026-07-01 +Quality: 91/100 | Updated: 2026-07-01 """ import sys diff --git a/plots/lollipop-basic/metadata/python/bokeh.yaml b/plots/lollipop-basic/metadata/python/bokeh.yaml index 9831ca6ed5..e32824c8d8 100644 --- a/plots/lollipop-basic/metadata/python/bokeh.yaml +++ b/plots/lollipop-basic/metadata/python/bokeh.yaml @@ -2,7 +2,7 @@ library: bokeh language: python specification_id: lollipop-basic created: '2025-12-23T15:14:01Z' -updated: '2026-07-01T06:06:30Z' +updated: '2026-07-01T06:20:05Z' generated_by: claude-sonnet workflow_run: 28496532200 issue: 934 @@ -12,49 +12,47 @@ preview_url_light: https://storage.googleapis.com/anyplot-images/plots/lollipop- preview_url_dark: https://storage.googleapis.com/anyplot-images/plots/lollipop-basic/python/bokeh/plot-dark.png preview_html_light: https://storage.googleapis.com/anyplot-images/plots/lollipop-basic/python/bokeh/plot-light.html preview_html_dark: https://storage.googleapis.com/anyplot-images/plots/lollipop-basic/python/bokeh/plot-dark.html -quality_score: 88 +quality_score: 91 review: strengths: - - 'Perfect visual quality: all font sizes explicitly set (50pt title, 42pt axis - labels, 34pt tick labels, 24pt value annotations), well-proportioned layout, readable - in both themes' - - 'Excellent data storytelling: dashed average reference line (Span) provides immediate - context for above/below-budget services; data sorted descending creates clear - visual ranking' - - Value labels above every lollipop head ($94K, $67K, …) eliminate the need to read - the y-axis for each bar, reducing cognitive load - - 'Idiomatic Bokeh usage: ColumnDataSource with named columns, Range1d for axis - bounds, NumeralTickFormatter for dollar ticks, Span for the reference line, proper - HTML + Selenium screenshot pipeline' - - Realistic, neutral cloud-spend dataset with plausible values ($6K–$94K/month), - deterministic data, and clean KISS code structure - - 'Correct Imprint palette compliance: brand green #009E73 for single series, #FAF8F1/#1A1A17 - backgrounds, full theme-adaptive chrome (INK/INK_SOFT tokens on all labels and - axes)' + - Brand green (#009E73) used consistently for stems and circular markers + - White outline ring on scatter markers (line_color=PAGE_BG) adds professional definition + - Average reference line with dashed style and annotation contextualizes the data + - Value labels above each marker make values immediately readable without requiring + axis lookup + - Data sorted descending creates natural visual hierarchy guiding viewer from highest + to lowest + - Theme-adaptive chrome thoroughly applied — all ink tokens set for both light and + dark renders + - 'Excellent Bokeh idioms: ColumnDataSource, Span, NumeralTickFormatter, Label models' + - NumeralTickFormatter for y-axis dollar formatting is a polished library-specific + touch weaknesses: - - 'SC-04: Title is missing the ''python'' language component. Required format: ''lollipop-basic - · python · bokeh · anyplot.ai''. Current title: ''lollipop-basic · bokeh · anyplot.ai''. - Fix: add '' · python'' between spec-id and library name in the title string.' - - 'DE-02: Full rectangular outline border (outline_line_color=INK_SOFT) creates - an all-four-sides box. Style guide prefers L-spine (remove top and right). Fix: - set p.outline_line_color=None and rely on p.xaxis.axis_line_color + p.yaxis.axis_line_color - for the bottom/left spines only.' - - 'DE-01: Design is above the generic default but not at ''strong design'' level - — could use one more differentiating touch, e.g. coloring lollipop heads above-average - vs below-average (brand green vs muted), or adding a subtle ''Average: $34.7K'' - text annotation to the reference line.' + - Average reference line label uses INK_MUTED for the reference line annotation + text which is good, but the label text at 22pt is noticeably smaller than the + 34pt tick labels — consider bumping to 26-28pt for better readability at mobile + scale + - Single brand-green color for all lollipops misses an opportunity to emphasize + outliers (e.g. Compute at $94K could be highlighted via a slightly larger marker + or bolder stem) — color or size variation would elevate the storytelling + - X-axis tick labels are rotated at 0.5 radians which creates a slightly awkward + angled look — consider 0.7-0.8 radians for a steeper slant or π/4 for 45° diagonal + which reads more cleanly + - 'DE-02: Minor tick lines are explicitly set to None (good) but major tick lines + are still the default size — styling major_tick_line_width smaller would further + refine the chrome' image_description: |- Light render (plot-light.png): - Background: Warm off-white consistent with #FAF8F1 — not pure white, not neutral grey. Correct theme surface. - Chrome: Title "lollipop-basic · bokeh · anyplot.ai" in bold dark text, clearly readable. X-axis label "Cloud Service" and Y-axis label "Monthly Spend (USD)" in Bokeh's default italic style, both readable in dark ink. Tick labels on x-axis (10 rotated category names) and y-axis ($0–$100,000 in dollar format) are readable in INK_SOFT. A subtle dashed horizontal reference line sits at approximately $35K (average spend). Rectangular outline border visible around the data area (all four sides in INK_SOFT). - Data: Brand green (#009E73) stems (vertical lines) and large filled circular markers for all 10 categories. Value annotations above each lollipop head ($94K, $67K, $48K, $38K, $28K, $22K, $18K, $12K, $9K, $6K) in INK_SOFT at 24pt. Data sorted descending from Compute to Monitoring. Y-axis grid lines only, subtle alpha ≈ 0.10. - Legibility verdict: PASS — all text clearly readable against the warm off-white background. No "light on light" failures. + Background: Warm off-white #FAF8F1 — correct, clearly not pure white. + Chrome: Title "lollipop-basic · python · bokeh · anyplot.ai" in bold dark ink, ~60-65% of canvas width, well-proportioned. X-axis label "Cloud Service" and Y-axis label "Monthly Spend (USD)" in dark INK at 42pt — balanced and readable. Tick labels in INK_SOFT at 34pt — legible. X-axis categories rotated ~28° to avoid overlap. Y-axis formatted as "$0"–"$100,000" in dollar notation. + Data: 10 lollipops all in brand green #009E73 with white outline rings, sorted descending (Compute $94K → Monitoring $6K). Stems as thin vertical lines from baseline. Circular markers prominently visible. Value labels ("$94K", "$67K", etc.) in INK_SOFT above each marker. Dashed average reference line with "Avg: $34.7K" annotation in INK_MUTED. Y-only subtle grid at 10% alpha. + Legibility verdict: PASS — all text clearly readable against the warm off-white background. No light-on-light issues. Dark render (plot-dark.png): - Background: Warm near-black consistent with #1A1A17 — not pure black. Correct theme surface. - Chrome: Title, axis labels, and tick labels rendered in light text (F0EFE8 / B8B7B0 range), clearly readable against the dark background. Reference line visible as a subtle dashed light-grey stroke. Same rectangular outline border visible in a lighter tone. - Data: Brand green (#009E73) stems and circular markers are identical in color to the light render — only chrome elements flipped. Value annotation labels visible in lighter text above each marker. Grid lines subtle and visible. - Legibility verdict: PASS — all text clearly readable against the warm near-black background. No dark-on-dark failures. Title, axis labels, tick labels, and value annotations all have adequate contrast. + Background: Warm near-black #1A1A17 — correct, clearly not pure black. + Chrome: Title in light #F0EFE8 ink — readable. Axis labels and tick labels in INK_SOFT (#B8B7B0) — clearly legible against the dark surface. No dark-on-dark failures observed. + Data: Identical brand green #009E73 lollipops with white-ring markers — data colors unchanged from light render as required. Value labels in INK_SOFT (#B8B7B0) remain visible. Average reference line and annotation adapt correctly to dark chrome. + Legibility verdict: PASS — all text readable against the near-black background. Chrome correctly flips while data colors remain identical to the light render. criteria_checklist: visual_quality: score: 30 @@ -65,54 +63,55 @@ review: score: 8 max: 8 passed: true - comment: 'All font sizes explicitly set: 50pt title, 42pt axis labels, 34pt - tick labels, 24pt value annotations. Balanced X/Y sizing. Readable in both - themes.' + comment: 'All font sizes explicitly set: title 50pt, axis labels 42pt, tick + labels 34pt, value labels 24pt, avg annotation 22pt. Well-proportioned in + both renders. No overflow. Readable in both themes.' - id: VQ-02 name: No Overlap score: 6 max: 6 passed: true - comment: No overlapping elements. Value labels clear of markers. Category - labels rotated to avoid collision. + comment: No overlapping elements. Value labels well-spaced above markers. + X-axis tick labels rotated to avoid collision. No text-on-data overlap. - id: VQ-03 name: Element Visibility score: 6 max: 6 passed: true - comment: '10 data points (sparse): size=42 markers and line_width=4 stems - are appropriately prominent. Green pops against both backgrounds.' + comment: Markers at size=42 are prominently visible for 10 sparse data points. + Stems at line_width=4 clearly visible. Appropriate sizing for the data density. - id: VQ-04 name: Color Accessibility score: 2 max: 2 passed: true - comment: 'Single series in brand green #009E73. High contrast on both surface - colors. CVD-safe.' + comment: Single-color brand green (#009E73) with good contrast on both backgrounds. + White outline ring on markers adds definition. CVD-safe — no red-green conflict. - id: VQ-05 name: Layout & Canvas score: 4 max: 4 passed: true - comment: Canvas 3200×1800 correct. min_border settings (160/180/110/80) provide - generous margins. Plot fills canvas well with no wasted space. + comment: 'Well-balanced layout. Plot fills good portion of 3200x1800 canvas. + Appropriate margins (min_border: left 180, bottom 160, top 110, right 80). + Canvas gate passed — no dimension drift.' - id: VQ-06 name: Axis Labels & Title score: 2 max: 2 passed: true - comment: '''Cloud Service'' and ''Monthly Spend (USD)'' — descriptive with - units.' + comment: Y-axis 'Monthly Spend (USD)' has units. X-axis 'Cloud Service' is + descriptive. Title format correct. - id: VQ-07 name: Palette Compliance score: 2 max: 2 passed: true - comment: 'Single series uses #009E73 (Imprint position 1). Backgrounds #FAF8F1 - (light) / #1A1A17 (dark). INK/INK_SOFT tokens used for all chrome. Both - renders theme-correct.' + comment: 'Brand green #009E73 as sole data color. Backgrounds #FAF8F1 (light) + / #1A1A17 (dark) correct. All chrome tokens theme-adaptive (INK, INK_SOFT, + INK_MUTED). Both renders pass. Data colors identical across themes.' design_excellence: - score: 12 + score: 13 max: 20 items: - id: DE-01 @@ -120,27 +119,29 @@ review: score: 5 max: 8 passed: true - comment: 'Above a well-configured default: reference line, value annotations, - custom sizing, and coherent brand color. Not at ''strong design'' level - yet.' + comment: 'Above well-configured default. Intentional choices: white outline + ring on markers (line_color=PAGE_BG), average reference line with annotation, + sorted data, value labels. Not yet at FiveThirtyEight sophistication level + — no color hierarchy or dramatic emphasis.' - id: DE-02 name: Visual Refinement - score: 3 + score: 4 max: 6 passed: true - comment: 'Y-axis-only grid, minor ticks removed, appropriate whitespace. Downside: - full rectangular outline border (outline_line_color=INK_SOFT) instead of - L-spine removes the minimalist top/right spine effect.' + comment: Y-only subtle grid at 10% alpha. No outer frame (outline_line_color=None). + Minor ticks suppressed. Theme-adaptive chrome throughout. Good refinement + visible above defaults, not yet 'perfect'. - id: DE-03 name: Data Storytelling score: 4 max: 6 passed: true - comment: Average reference line immediately frames which services are above/below - budget. Sorted descending makes ranking obvious. Value labels reduce chart-reading - friction. + comment: 'Sorted descending order creates visual hierarchy. Average reference + line contextualizes which services are above/below average. Value labels + make data immediately readable. Viewer quickly identifies the story. Missing: + color/size emphasis on outliers.' spec_compliance: - score: 13 + score: 15 max: 15 items: - id: SC-01 @@ -148,31 +149,31 @@ review: score: 5 max: 5 passed: true - comment: 'Correct lollipop chart: segment() for stems, scatter() for circular - markers at data values.' + comment: 'Correct lollipop chart: segment() for stems from baseline, scatter() + for circular markers at data values. Vertical orientation with categories + on x-axis.' - id: SC-02 name: Required Features score: 4 max: 4 passed: true - comment: Thin stems from baseline, circular markers, vertical orientation - (categories on x-axis), data sorted by value descending. All spec requirements - met. + comment: 'All spec features present: thin stems, circular markers, vertical + orientation, categories on x-axis, values on y-axis, data sorted by value + descending.' - id: SC-03 name: Data Mapping score: 3 max: 3 passed: true - comment: 'X-axis: Cloud Service categories. Y-axis: Monthly Spend (USD). All - 10 data points visible.' + comment: Categories on x-axis (Cloud Service), values on y-axis (Monthly Spend). + All 10 categories visible. Range $0-$100K covers all data. - id: SC-04 name: Title & Legend - score: 1 + score: 3 max: 3 - passed: false - comment: 'Title ''lollipop-basic · bokeh · anyplot.ai'' is missing the ''python'' - language component. Required: ''lollipop-basic · python · bokeh · anyplot.ai''. - No legend needed for single series (N/A).' + passed: true + comment: Title 'lollipop-basic · python · bokeh · anyplot.ai' matches required + format. No legend needed for single-series — correctly omitted. data_quality: score: 15 max: 15 @@ -182,22 +183,24 @@ review: score: 6 max: 6 passed: true - comment: '10 categories showing full range of lollipop chart features: variable - stem lengths, visible markers at different heights, value annotations.' + comment: Shows all lollipop features with good value range ($6.8K to $94.2K). + Natural variation in heights demonstrates the chart type effectively. - id: DQ-02 name: Realistic Context score: 5 max: 5 passed: true comment: Monthly cloud infrastructure spend by service category — real, neutral, - business context. + business scenario. Realistic categories (Compute, Storage, Networking, Database, + Security, Analytics, AI/ML, IoT, DevOps, Monitoring). - id: DQ-03 name: Appropriate Scale score: 4 max: 4 passed: true - comment: $6K–$94K monthly spend per service is realistic for a mid-sized tech - company. Proportions between categories are plausible. + comment: Values plausible for a mid-size tech company (~$347K/month total + cloud spend). Proportions between services (Compute largest, Monitoring + smallest) are realistic. No factual issues. code_quality: score: 10 max: 10 @@ -207,35 +210,35 @@ review: score: 3 max: 3 passed: true - comment: 'No functions or classes. Clean top-to-bottom: imports → tokens → - data → figure → styling → save.' + comment: 'Linear flow: imports → theme constants → data → figure → glyphs + → styling → output. No functions or classes.' - id: CQ-02 name: Reproducibility score: 2 max: 2 passed: true - comment: Deterministic hardcoded dataset. No randomness. + comment: Fully deterministic — hardcoded data arrays, no random generation. - id: CQ-03 name: Clean Imports score: 2 max: 2 passed: true - comment: 'All imports used: io, os, time, pathlib, bokeh (figure, ColumnDataSource, - NumeralTickFormatter, Range1d, Span, output_file, save), PIL.Image, selenium.webdriver.' + comment: 'All imports used: sys, io, os, time, pathlib.Path, bokeh models, + PIL.Image, selenium.' - id: CQ-04 name: Code Elegance score: 2 max: 2 passed: true - comment: Clean and Pythonic. PIL crop trick for exact canvas dimensions is - an elegant workaround for Bokeh/Chrome headless sizing issue. + comment: Clean, idiomatic Python. Appropriate complexity. No over-engineering. + sys.path fix is necessary and documented. - id: CQ-05 name: Output & API score: 1 max: 1 passed: true - comment: Saves plot-{THEME}.png and plot-{THEME}.html. Uses current Bokeh - 3.9.0 API. + comment: Saves plot-{THEME}.html and plot-{THEME}.png correctly. Uses current + Bokeh 3.9 API. library_mastery: score: 8 max: 10 @@ -245,19 +248,18 @@ review: score: 5 max: 5 passed: true - comment: 'Expertly uses Bokeh patterns: ColumnDataSource with named columns, - figure(x_range=categories) for categorical axis, segment()/scatter()/text() - glyph methods, Span layout model, Range1d, NumeralTickFormatter, full Selenium - screenshot pipeline.' + comment: 'Expert Bokeh usage: ColumnDataSource for all data, Span for reference + line, Label with x_units=''screen'' for annotation, NumeralTickFormatter + for dollar formatting, proper Selenium screenshot pattern per library guide.' - id: LM-02 name: Distinctive Features score: 3 max: 5 passed: true - comment: Span layout model for reference line is distinctly Bokeh. NumeralTickFormatter - for dollar formatting. HTML export as a first-class artifact alongside the - PNG. Could leverage HoverTool for additional distinctiveness. - verdict: REJECTED + comment: Uses Bokeh-specific Span model, NumeralTickFormatter, Label with + mixed coordinate units. HTML interactive export via output_file+save. Core + segment+scatter technique is library-agnostic — partial credit. + verdict: APPROVED impl_tags: dependencies: - selenium @@ -266,8 +268,8 @@ impl_tags: - annotations - html-export patterns: - - data-generation - columndatasource dataprep: [] styling: + - edge-highlighting - grid-styling