Skip to content

feat(bokeh): implement slope-basic#5640

Merged
MarkusNeusinger merged 6 commits intomainfrom
implementation/slope-basic/bokeh
Apr 30, 2026
Merged

feat(bokeh): implement slope-basic#5640
MarkusNeusinger merged 6 commits intomainfrom
implementation/slope-basic/bokeh

Conversation

@github-actions
Copy link
Copy Markdown
Contributor

Implementation: slope-basic - python/bokeh

Implements the python/bokeh version of slope-basic.

File: plots/slope-basic/implementations/python/bokeh.py

Parent Issue: #981


🤖 impl-generate workflow

@claude
Copy link
Copy Markdown
Contributor

claude Bot commented Apr 30, 2026

AI Review - Attempt 1/3

Image Description

Light render (`plot-light.png`): The plot renders on a warm off-white background (~#FAF8F1). It shows a clean slope chart with 10 product lines connecting Q1 to Q4 sales values. The lines are color-coded by direction — teal/green (#009E73-like) for increasing products and orange (#D55E00-like) for decreasing ones. Labels appear at both endpoints showing product name and value. The Y-axis is labeled "Sales (thousands)". Q1 and Q4 are labeled at the bottom of the chart. All text (title, axis labels, product labels) is readable against the light background with dark text. The title reads "slope-basic · bokeh · anyplot.ai".
Legibility verdict: PASS (based on images)

Dark render (`plot-dark.png`): The plot renders on a near-black background (~#1A1A17). The same slope lines are shown with identical data colors (green for increases, orange for decreases — unchanged from light render). Title, axis labels, and Q1/Q4 labels appear in light/white text and are readable against the dark background. No dark-on-dark failures visible in the images. The product labels also appear in matching line colors (teal or orange) which remain readable on the dark surface.
Legibility verdict: PASS (based on images)

⚠️ Critical Code-Image Mismatch: The images appear to have been generated from a different version of the code. The current `bokeh.py` uses `#306998` (Python Blue) and `#FFD43B` (Python Yellow) — but the images show green + orange (Okabe-Ito). The code also saves to `plot.png` (not `plot-light.png`/`plot-dark.png`) and sets the title as `"pyplots.ai"` (not `"anyplot.ai"`). The code as written cannot produce the images shown. Both paragraphs describe the images as rendered; code analysis drives palette and CQ scoring.

Score: 73/100

Category Score Max
Visual Quality 21 30
Design Excellence 12 20
Spec Compliance 13 15
Data Quality 13 15
Code Quality 8 10
Library Mastery 6 10
Total 73 100

Visual Quality (21/30)

  • VQ-01: Text Legibility (6/8) — Font sizes explicitly set (title 32pt, labels 22pt, ticks 18pt, product labels 18pt). Images show readable text in both themes. Deduction: code provides no explicit dark-mode color settings, so a fresh dark-mode run would produce unreadable default dark-on-dark text.
  • VQ-02: No Overlap (3/6) — Several label pairs are very close: G(78)/B(72) left side only 6 units apart; G(95)/A(92)/C(88) right side only 3-4 units apart; I(67)/B(65) right side only 2 units apart. Likely overlap at the densest endpoints.
  • VQ-03: Element Visibility (5/6) — Lines at line_width=4 and scatter markers at size=18 are clearly visible and well-sized for the canvas.
  • VQ-04: Color Accessibility (2/2) — Images show green vs orange — distinguishable by luminance, CVD-safe, no red-green sole signal.
  • VQ-05: Layout & Canvas (3/4) — Reasonable canvas utilization, labels on both sides give good spacing. Minor wasted space at top (above 100 mark) and bottom (below Q1/Q4 labels).
  • VQ-06: Axis Labels & Title (2/2) — "Sales (thousands)" is descriptive with units; title format correct in images.
  • VQ-07: Palette Compliance (0/2) — Code uses `#306998` (Python Blue) for increases — explicitly listed as non-compliant ("legacy Python Blue") in VQ-07 criteria. Code also uses `#FFD43B` (Python Yellow) which is non-Okabe-Ito. No theme-adaptive chrome is set (no PAGE_BG, INK, INK_SOFT tokens). Images show compliant colors but were generated from different code.

Design Excellence (12/20)

  • DE-01: Aesthetic Sophistication (4/8) — Direction color-coding is a smart design choice. Chart is clean and functional. However, the design is relatively generic — a well-configured default look without distinctive typographic or spatial polish.
  • DE-02: Visual Refinement (4/6) — X-grid disabled, y-grid adjusted to dashed style (alpha=0.3 is slightly heavier than the recommended 10-15% opacity but still subdued), outline removed. Some visible refinement effort.
  • DE-03: Data Storytelling (4/6) — The direction color-coding immediately communicates which products gained vs lost. Viewer can read the narrative at a glance. Good use of the slope chart's natural storytelling strength.

Spec Compliance (13/15)

  • SC-01: Plot Type (5/5) — Correct slope chart (slopegraph) with lines connecting two time points. Spec requirements met.
  • SC-02: Required Features (3/4) — Labels at both endpoints ✓; color coding by direction ✓; vertical axes labeled with time point names ✓; 10 entities (within 5-15 range) ✓. Missing: no legend explaining what the direction colors represent.
  • SC-03: Data Mapping (3/3) — Q1 on left, Q4 on right, sales values on Y-axis. Correct.
  • SC-04: Title & Legend (2/3) — Title "slope-basic · bokeh · anyplot.ai" is correct in images. Code sets "pyplots.ai" — title is wrong in the actual source. No direction legend (increase/decrease color key).

Data Quality (13/15)

  • DQ-01: Feature Coverage (5/6) — Shows both increases (5 products) and decreases (5 products), demonstrates rank changes and crossing lines. Good variation. Slight deduction: no near-flat product to illustrate the "no change" case.
  • DQ-02: Realistic Context (4/5) — Q1 vs Q4 product sales is a plausible, neutral business scenario. Deduction: "Product A–J" labels are generic; real product names would score higher.
  • DQ-03: Appropriate Scale (4/4) — Sales values 40–95 thousand are realistic. Changes (up/down 5–26 units) are believable quarterly fluctuations.

Code Quality (8/10)

  • CQ-01: KISS Structure (3/3) — Clean linear structure: data → figure → style → draw → save. No functions or classes.
  • CQ-02: Reproducibility (2/2) — Data is hardcoded; fully deterministic, no random seed needed.
  • CQ-03: Clean Imports (2/2) — Only imports used: `export_png`, `save`, `Label`, `figure`, `CDN`.
  • CQ-04: Code Elegance (1/2) — Code is readable and Pythonic. Deduction: uses wrong palette colors and omits theme-adaptive chrome entirely — substantive correctness issue, not just style.
  • CQ-05: Output & API (0/1) — Saves to `plot.png` and `plot.html`. Required: `plot-{THEME}.png` and `plot-{THEME}.html`. No `ANYPLOT_THEME` reading at all. Cannot produce themed output.

Library Mastery (6/10)

  • LM-01: Idiomatic Usage (4/5) — Uses `figure`, `line`, `scatter`, `Label`, `export_png` appropriately. `ColumnDataSource` not used (direct lists passed instead), which is less idiomatic for Bokeh.
  • LM-02: Distinctive Features (2/5) — Uses Bokeh's `Label` model for custom annotations (distinctive). HTML export via `save` is used. Misses opportunity for `HoverTool` which is Bokeh's strongest distinctive feature for a chart like this.

Score Caps Applied

  • None — all caps checked; DE-01=4 and DE-02=4 both exceed the ≤2 threshold, so the 75-cap does not apply. VQ-02=3≠0, VQ-03=5≠0, SC-01=5≠0. No cap fires.

Strengths

  • Correct slope chart type with lines connecting two time periods — matches spec exactly
  • Direction color-coding is excellent data storytelling and spec-required feature
  • Labels at both endpoints with value + product name — clean and informative
  • KISS code structure with no over-engineering; all imports used
  • Reasonable font sizing explicitly set throughout

Weaknesses

  • CRITICAL: Code uses #306998 (Python Blue, explicitly non-compliant) and #FFD43B (Python Yellow, not Okabe-Ito) — replace with #009E73 for increase and #D55E00 for decrease
  • CRITICAL: No ANYPLOT_THEME reading, no theme-adaptive chrome — add PAGE_BG, INK, INK_SOFT tokens and set all background/text/grid colors accordingly (see prompts/library/bokeh.md)
  • CRITICAL: Output filenames are plot.png/plot.html — must be plot-{THEME}.png/plot-{THEME}.html
  • CRITICAL: Title hardcoded as "pyplots.ai" not "anyplot.ai"
  • Label overlap at dense endpoints (G/A/C on right at 95/92/88; I/B on right at 67/65) — consider small y-offset for near-equal values
  • No direction legend or subtitle explaining color coding (increase vs decrease)

Issues Found

  1. VQ-07 FAIL + CQ-05 FAIL: Non-compliant palette and missing theme support — both critical
    • Fix: Add ANYPLOT_THEME = os.getenv("ANYPLOT_THEME", "light"), set PAGE_BG/INK/INK_SOFT tokens, apply to all background/text elements, change colors to Okabe-Ito (#009E73/#D55E00), save to plot-{THEME}.png and plot-{THEME}.html
  2. SC-04 LOW: Title hardcoded to "pyplots.ai"
    • Fix: Change to "anyplot.ai"
  3. VQ-02 MODERATE: Label overlap at dense endpoint clusters
    • Fix: Add small y-jitter offset for labels within ±3 units of each other, or reduce label font size slightly

AI Feedback for Next Attempt

Fix the four critical issues: (1) Replace #306998/#FFD43B with Okabe-Ito #009E73 (increase) and #D55E00 (decrease); (2) Add full theme adaptation — read ANYPLOT_THEME = os.getenv("ANYPLOT_THEME", "light"), define PAGE_BG/INK/INK_SOFT tokens, apply to p.background_fill_color, p.border_fill_color, p.title.text_color, p.xaxis/yaxis colors, all Label text_color and the grid; (3) Change output to export_png(p, filename=f"plot-{THEME}.png") and save(p, filename=f"plot-{THEME}.html"); (4) Fix title to use "anyplot.ai". Additionally: reduce label crowding at dense endpoints by adding a small y-offset (~1-2 units) when two labels are within 3 units of each other, and add a small direction legend or subtitle explaining the green/orange coding.

Verdict: REJECTED

@github-actions github-actions Bot added quality:73 Quality score 73/100 ai-rejected Quality not OK, triggers update labels Apr 30, 2026
@github-actions github-actions Bot added ai-attempt-1 First repair attempt and removed ai-rejected Quality not OK, triggers update labels Apr 30, 2026
@github-actions
Copy link
Copy Markdown
Contributor Author

🔧 Repair Attempt 1/4

Applied fixes based on AI review feedback.

Status: Repair completed, re-triggering review...


🤖 impl-repair

@claude
Copy link
Copy Markdown
Contributor

claude Bot commented Apr 30, 2026

AI Review - Attempt 2/3

Image Description

Light render (plot-light.png): Warm off-white background (#FAF8F1). Title "slope-basic · bokeh · anyplot.ai" is bold, dark, centered at the top. Y-axis label "Sales (thousands)" and tick labels are dark ink on light surface. "Q1" and "Q4" text labels appear at the bottom. A direction legend ("— Increase" in brand green, "— Decrease" in orange-red) sits below the title. Ten slope lines connect endpoint dots (size=18) — #009E73 (Okabe-Ito brand green) for increases and #D55E00 (vermillion) for decreases. Left-side endpoint labels read "Product X: value" and right-side labels read "value: Product X", both in the matching line color; the spread_labels algorithm keeps them visually separated. All text is readable against the light background.

Dark render (plot-dark.png): Near-black background (#1A1A17). Title, Q1/Q4 labels, and axis chrome all render in light INK (#F0EFE8), clearly visible. Tick labels use INK_SOFT (#B8B7B0). Data colors (#009E73 and #D55E00) are identical to the light render — only background and chrome flip. Endpoint labels in their matching data colors are legible against the dark surface. No dark-on-dark text failure observed. Both renders pass the theme-readability check.

Both paragraphs are required. A review that only describes one render is invalid.

Score: 84/100

Category Score Max
Visual Quality 28 30
Design Excellence 13 20
Spec Compliance 15 15
Data Quality 13 15
Code Quality 8 10
Library Mastery 7 10
Total 84 100

Visual Quality (28/30)

  • VQ-01: Text Legibility (7/8) — Title 32pt, axis label 22pt, tick labels 18pt, endpoint labels 18pt, Q1/Q4 labels 28pt — all explicitly set. Minor deduction: endpoint label color relies on data color contrast (Okabe-Ito, so safe, but not INK).
  • VQ-02: No Overlap (6/6) — spread_labels algorithm effectively separates all endpoint labels on both sides.
  • VQ-03: Element Visibility (6/6) — Lines at line_width=4 and markers at size=18 clearly visible on 4800×2700 canvas.
  • VQ-04: Color Accessibility (2/2) — Okabe-Ito positions 1 and 2 (green/orange-red) are CVD-safe with strong luminance contrast.
  • VQ-05: Layout & Canvas (3/4) — Good canvas usage; top section (title + direction legend gap) creates notable whitespace above the data area.
  • VQ-06: Axis Labels & Title (2/2) — Y-axis "Sales (thousands)" with units; title format correct; Q1/Q4 column labels identify time points.
  • VQ-07: Palette Compliance (2/2) — INCREASE_COLOR=#009E73 (Okabe-Ito pos 1), DECREASE_COLOR=#D55E00 (pos 2). PAGE_BG #FAF8F1 light / #1A1A17 dark. All theme chrome tokens correctly set.

Design Excellence (13/20)

  • DE-01: Aesthetic Sophistication (5/8) — Purposeful design: direction color coding, hidden x-axis replaced by text labels, custom label-spread algorithm. Above configured defaults but lacks the typographic refinement and polish needed for 6+.
  • DE-02: Visual Refinement (4/6) — X-grid hidden, Y-grid alpha=0.10 (very subtle), toolbar removed, outline_line_color=None. Clean but the y-axis line frame is still prominent.
  • DE-03: Data Storytelling (4/6) — Direction color coding creates an immediate visual narrative (green rises, orange falls). Mixed increases/decreases with crossovers demonstrate the chart type's value clearly.

Spec Compliance (15/15)

  • SC-01: Plot Type (5/5) — Correct slopegraph connecting two time points with slope lines.
  • SC-02: Required Features (4/4) — Labels at both endpoints ✓, color coding by direction ✓, time point column labels ✓.
  • SC-03: Data Mapping (3/3) — X = Q1/Q4 time points, Y = sales values; all 10 products visible.
  • SC-04: Title & Legend (3/3) — Title "slope-basic · bokeh · anyplot.ai" correct. Direction legend with matching data colors.

Data Quality (13/15)

  • DQ-01: Feature Coverage (6/6) — Includes both increases and decreases, varied magnitudes, multiple rank inversions/crossovers; 10 products within the 5–15 recommended range.
  • DQ-02: Realistic Context (3/5) — Business scenario is plausible, but "Product A" through "Product J" are abstract generic labels rather than real named products.
  • DQ-03: Appropriate Scale (4/4) — Values 40–95 thousand for quarterly sales are plausible and internally consistent.

Code Quality (8/10)

  • CQ-01: KISS Structure (1/3) — spread_labels helper function defined at module level; breaks the KISS "no functions/classes" rule.
  • CQ-02: Reproducibility (2/2) — All data hardcoded; fully deterministic.
  • CQ-03: Clean Imports (2/2) — All imports used: os, export_png, save, ColumnDataSource, HoverTool, Label, figure, CDN.
  • CQ-04: Code Elegance (2/2) — Clean, Pythonic; strict=True in zip calls is modern style; no fake UI.
  • CQ-05: Output & API (1/1) — Saves plot-{THEME}.png and plot-{THEME}.html with CDN resources.

Library Mastery (7/10)

  • LM-01: Idiomatic Usage (4/5) — ColumnDataSource for scatter (enabling HoverTool), Label via add_layout, toolbar_location=None — correct Bokeh patterns. Lines drawn per-entity in loop is slightly non-idiomatic versus multi_line.
  • LM-02: Distinctive Features (3/5) — HoverTool showing product/period/value and HTML export with CDN are distinctively Bokeh features.

Score Caps Applied

  • None — all caps checked, none triggered.

Strengths

  • Direction-coded slope lines (green=increase, orange=decrease) using Okabe-Ito positions 1 and 2
  • Custom spread_labels algorithm prevents endpoint label overlap on both sides
  • Full theme support with properly threaded INK/INK_SOFT tokens in both light and dark renders
  • HoverTool with product/period/value tooltips leverages Bokeh interactive capability
  • Correct title format, all required spec features present, full spec compliance

Weaknesses

  • CQ-01 violation: spread_labels helper function breaks KISS structure; consider inlining the spread logic or using a simple list comprehension
  • DQ-02 penalty: product labels are generic (Product A–J) rather than real named products
  • Top-canvas whitespace: the direction legend placement creates a gap between the title and data area
  • DE-01 ceiling: design is functional but lacks refined typography polish for a score above 5

Issues Found

  1. CQ-01 LOW: spread_labels function defined at module level violates KISS structure
    • Fix: Inline the label spread computation or rewrite as a compact list comprehension
  2. DQ-02 MEDIUM: Generic product names reduce realism score
    • Fix: Replace "Product A–J" with named real-world products (e.g., consumer electronics, beverage brands)

AI Feedback for Next Attempt

The core implementation is solid and fully spec-compliant. To push above 84: replace generic "Product A–J" labels with realistic named products to improve DQ-02; remove the spread_labels function and inline the logic to satisfy CQ-01; tighten the top-canvas whitespace by moving the direction legend closer to the data or inside the plot area; consider using multi_line for the slope lines instead of a per-entity loop for more idiomatic Bokeh.

Verdict: APPROVED

@github-actions github-actions Bot added quality:84 Quality score 84/100 ai-approved Quality OK, ready for merge labels Apr 30, 2026
@MarkusNeusinger MarkusNeusinger merged commit a1da3a6 into main Apr 30, 2026
@MarkusNeusinger MarkusNeusinger deleted the implementation/slope-basic/bokeh branch April 30, 2026 17:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ai-approved Quality OK, ready for merge ai-attempt-1 First repair attempt quality:73 Quality score 73/100 quality:84 Quality score 84/100

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant