Skip to content

feat(pygal): implement swarm-basic#9939

Merged
MarkusNeusinger merged 6 commits into
mainfrom
implementation/swarm-basic/pygal
Jul 26, 2026
Merged

feat(pygal): implement swarm-basic#9939
MarkusNeusinger merged 6 commits into
mainfrom
implementation/swarm-basic/pygal

Conversation

@github-actions

Copy link
Copy Markdown
Contributor

Implementation: swarm-basic - python/pygal

Implements the python/pygal version of swarm-basic.

File: plots/swarm-basic/implementations/python/pygal.py

Parent Issue: #974


🤖 impl-generate workflow

github-actions Bot added 2 commits July 26, 2026 07:10
Regen from quality 80. Addressed:
- Canvas size: 4800x2700 (historical, off-contract) -> 3200x1800 (canonical landscape)
- Missing language token in title -> "swarm-basic · python · pygal · anyplot.ai"
- Font sizes rescaled to the canonical 3200x1800 pygal table (title=66, label=56, major_label=44, legend=44)
- Added subtle Group Mean markers per category (spec explicitly recommends this; previous attempt had removed them) using the theme-adaptive neutral anchor color
- Tightened right-side margin to reduce wasted whitespace

Kept: custom beeswarm overlap-avoidance algorithm, Imprint palette in canonical order, dual PNG/HTML output, employee-performance-by-department scenario.
@claude

claude Bot commented Jul 26, 2026

Copy link
Copy Markdown
Contributor

AI Review - Attempt 1/3

Image Description

Light render (plot-light.png): Warm off-white (#FAF8F1) background. Title "swarm-basic · python · pygal · anyplot.ai", axis titles "Department"/"Performance Score", y-axis ticks (40-110), x-axis category labels, and the bottom legend (4 categories + Group Mean) are all dark and clearly legible. Subtle dashed horizontal gridlines. Engineering=green(#009E73), Marketing=purple, Sales=blue, Operations=brown, with a large black "Group Mean" dot per category. However, within several categories (most visibly Sales, and mid-range Marketing/Operations) points stack in a dense, mostly single-column vertical line rather than fanning out into a swarm shape. All text is readable against the light background.

Dark render (plot-dark.png): Warm near-black (#1A1A17) background. Same title/axis/legend text, now in light ink, fully legible against the dark surface — no dark-on-dark issues found. Data colors are identical to the light render (green/purple/blue/brown), confirming only chrome (background, text, gridlines, and the Group Mean dot's ink tone) flips between themes. The same point-clumping pattern from the light render persists here since it's a data-layout issue, not a theme issue. All text is readable against the dark background.

Both renders confirmed via the Read tool.

Score: 75/100

Category Score Max
Visual Quality 24 30
Design Excellence 11 20
Spec Compliance 13 15
Data Quality 12 15
Code Quality 9 10
Library Mastery 6 10
Total 75 100

Visual Quality (24/30)

  • VQ-01: Text Legibility (7/8)
  • VQ-02: No Overlap (3/6) - Large stretches of points stack directly on each other rather than spreading
  • VQ-03: Element Visibility (4/6) - Overlapping clusters reduce individual-point distinguishability
  • VQ-04: Color Accessibility (2/2)
  • VQ-05: Layout & Canvas (4/4)
  • VQ-06: Axis Labels & Title (2/2)
  • VQ-07: Palette Compliance (2/2)

Design Excellence (11/20)

  • DE-01: Aesthetic Sophistication (5/8) - Solid custom styling, undercut by clumped points
  • DE-02: Visual Refinement (3/6) - Subtle grid/margins, but dense clustering looks unrefined
  • DE-03: Data Storytelling (3/6) - Mean markers help, but muted spread undersells the distribution-shape story

Spec Compliance (13/15)

  • SC-01: Plot Type (4/5) - Right approach (manual swarm on XY) but partially fails to deliver a true swarm shape
  • SC-02: Required Features (3/4) - Category axis, color-by-category, mean markers present; horizontal spread only partially achieved
  • SC-03: Data Mapping (3/3)
  • SC-04: Title & Legend (3/3)

Data Quality (12/15)

  • DQ-01: Feature Coverage (4/6) - Distribution shape obscured where the swarm collapses into a column
  • DQ-02: Realistic Context (5/5)
  • DQ-03: Appropriate Scale (3/4) - A few points exceed 100, odd for a "Performance Score"

Code Quality (9/10)

  • CQ-01: KISS Structure (3/3)
  • CQ-02: Reproducibility (2/2)
  • CQ-03: Clean Imports (2/2)
  • CQ-04: Code Elegance (1/2) - Beeswarm collision loop has a units mismatch that prevents it from working as intended
  • CQ-05: Output & API (1/1)

Library Mastery (6/10)

  • LM-01: Idiomatic Usage (4/5)
  • LM-02: Distinctive Features (2/5) - Standard Style/XY usage plus HTML export; nothing beyond that

Score Caps Applied

  • None

Strengths

  • Imprint palette applied correctly: Engineering=#009E73 (first series, brand green) through to Operations=#BD8233 in canonical order, identical across both themes.
  • Theme tokens threaded through consistently — PAGE_BG/INK/INK_MUTED flip correctly with no dark-on-dark or light-on-light text.
  • Group Mean markers per department are a thoughtful addition that directly satisfies the spec's "consider adding a subtle mean/median marker" note.
  • Canvas is exactly 3200x1800 with no clipped text at any edge.
  • Deterministic data generation via np.random.seed(42); clean imports; correct plot-{theme}.png/.html output contract.

Weaknesses

  • Beeswarm collision detection is scaled wrong. point_radius=0.1 and spacing=0.05 are compared directly against raw y-values, but the value axis spans ~75 units (range=(40,115)) while a rendered dot (dots_size=10) is roughly 1-1.5 data-units tall on screen. Because the overlap threshold (2*point_radius+spacing = 0.25) is far smaller than the dot's actual visual footprint, most visually-touching points are never flagged as overlapping and stay at center_x, producing a dense solid-looking vertical strip (e.g. the Sales column) instead of a fanned beeswarm. Fix by deriving point_radius/spacing from the actual y-range and dot size (e.g. normalize y into [0, 1] using the chart's range before running the collision loop, or scale point_radius proportional to (range span) * (dots_size in px / plot height in px)).
  • Because of that bug, the plot under-delivers on the spec's core promise ("points spread horizontally to avoid overlap" / "reveals the full distribution shape") — large portions of each category render as a single dense column rather than a true swarm shape.
  • Some synthetic performance scores exceed 100 (up to ~115 in Sales), which reads oddly for a "Performance Score" metric typically bounded 0-100 — tighten the normal-distribution parameters or clamp values.

Issues Found

  1. VQ-02/DQ-01 HIGH: Beeswarm collision-detection units mismatch causes points to stack instead of spreading
    • Fix: Scale point_radius/spacing to the y-axis data range (or normalize coordinates to [0,1] before the collision check) so the threshold matches the dot's actual rendered size.
  2. DQ-03 LOW: A handful of data points exceed 100 for a "Performance Score" metric
    • Fix: Tighten np.random.normal parameters (e.g. lower std devs or clip) so values stay within a plausible 0-100ish band.
  3. DE-03 LOW: Distribution-shape storytelling is muted by the overlap bug
    • Fix: Resolves automatically once the swarm spacing bug above is fixed.

AI Feedback for Next Attempt

The core blocker is the beeswarm collision-detection scale mismatch: point_radius=0.1/spacing=0.05 are far too small relative to the y-axis's actual data range (~75 units across range=(40,115)), so the algorithm rarely detects overlap and most points stay stacked at center_x — producing dense vertical strips instead of a proper fanned swarm. Fix by normalizing y-values into [0,1] (or an equivalent pixel-aware scale) before running the collision loop, so point_radius corresponds to the dot's actual rendered footprint. Also tighten the synthetic performance-score distributions so values stay within a more plausible ~0-100 range.

Verdict: REJECTED

@github-actions github-actions Bot added quality:75 Quality score 75/100 ai-rejected Quality not OK, triggers update labels Jul 26, 2026
@github-actions github-actions Bot added ai-attempt-1 First repair attempt and removed ai-rejected Quality not OK, triggers update labels Jul 26, 2026
Attempt 1/4 - fixes based on AI review
@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

claude Bot commented Jul 26, 2026

Copy link
Copy Markdown
Contributor

AI Review - Attempt 2/3

⚠️ Pipeline note (read before the score below): the plot_images/plot-light.png and plot-dark.png supplied to this review step are stale and do not reflect commit 8939f709e. They show data points above 100, which is mathematically impossible given this code's np.clip(np.random.normal(...), 0, 100) bound, and their y-axis extends past the script's own computed range=(50,100). This proves those PNGs were rendered from a pre-fix version of the script. I independently re-rendered plots/swarm-basic/implementations/python/pygal.py in a clean environment with the exact pinned pygal==3.1.3 and scored those verified renders instead. Recommend re-rendering plot-light.png/plot-dark.png from the current commit (and double-checking impl-merge.yml does the same before GCS promotion) so stale pre-fix imagery is never published as the production preview.

Image Description

Light render (re-rendered plot-light.png): Warm off-white (#FAF8F1) background. Title "swarm-basic · python · pygal · anyplot.ai" and axis titles ("Department" / "Performance Score") are dark and fully legible; y-axis ticks now run 50-100 (values correctly clamped); bottom legend (4 categories + Group Mean) is clean and legible. Data uses the canonical Imprint order (Engineering #009E73 → Marketing #C475FD → Sales #4467A3 → Operations #BD8233) with large black Group Mean markers per category. Points now form a genuine fanned beeswarm shape — wide in high-density bands, narrowing toward the tails — with no unresolved dense overlapping column like the previous attempt. All text readable, nothing clipped.

Dark render (re-rendered plot-dark.png): Same layout on a warm near-black (#1A1A17) background. Title, axis titles, tick labels, and legend all render in light ink and are clearly legible — no dark-on-dark failures. Data colors are identical to the light render (only chrome flips), and the same well-fanned swarm shape confirms the fix is theme-independent.

Both renders pass legibility; the previous "dense vertical column" defect is resolved in both themes.

Score: 88/100

Category Score Max
Visual Quality 28 30
Design Excellence 14 20
Spec Compliance 15 15
Data Quality 15 15
Code Quality 10 10
Library Mastery 6 10
Total 88 100

Visual Quality (28/30)

  • VQ-01: Text Legibility (7/8)
  • VQ-02: No Overlap (6/6) — beeswarm collision-scale bug fixed
  • VQ-03: Element Visibility (5/6)
  • VQ-04: Color Accessibility (2/2)
  • VQ-05: Layout & Canvas (4/4)
  • VQ-06: Axis Labels & Title (2/2)
  • VQ-07: Palette Compliance (2/2)

Design Excellence (14/20)

  • DE-01: Aesthetic Sophistication (6/8) - Custom palette + now-correct swarm shape read as polished
  • DE-02: Visual Refinement (4/6) - Subtle grid, generous margins, clean chrome
  • DE-03: Data Storytelling (4/6) - Group Mean + genuine fan shape now tell the distribution story

Spec Compliance (15/15)

  • SC-01: Plot Type (5/5)
  • SC-02: Required Features (4/4)
  • SC-03: Data Mapping (3/3)
  • SC-04: Title & Legend (3/3)

Data Quality (15/15)

  • DQ-01: Feature Coverage (6/6)
  • DQ-02: Realistic Context (5/5)
  • DQ-03: Appropriate Scale (4/4) - values now clamped to a sensible 0-100 band

Code Quality (10/10)

  • CQ-01: KISS Structure (3/3)
  • CQ-02: Reproducibility (2/2)
  • CQ-03: Clean Imports (2/2)
  • CQ-04: Code Elegance (2/2) - per-axis pixel-to-data-unit scaling now correctly derived
  • CQ-05: Output & API (1/1)

Library Mastery (6/10)

  • LM-01: Idiomatic Usage (4/5)
  • LM-02: Distinctive Features (2/5) - Generic usage beyond Style/XY + HTML export

Score Caps Applied

  • None

Strengths

  • Beeswarm collision algorithm now correctly derives per-axis pixel-to-data-unit scale (x_unit_per_px / y_unit_per_px) from the actual plot pixel dimensions and dot radius, fixing the exact units-mismatch bug flagged in the previous review — independently re-rendered and confirmed to produce a genuine fanned swarm shape with no dense overlapping columns.
  • Performance-score data is now clamped to a plausible 0-100 range via np.clip, resolving the previous "values exceed 100" realism issue.
  • Imprint palette applied correctly and identically across both themes; Group Mean markers give a clear comparative focal point per the spec's suggestion.
  • Canvas exactly 3200x1800 with no clipped text; theme tokens threaded through consistently with no dark-on-dark/light-on-light failures.
  • Deterministic data generation via np.random.seed(42); clean imports; correct plot-{theme}.png/.html output contract.

Weaknesses

  • [Pipeline, not code] See callout above — the supplied plot_images/ were stale/pre-fix; recommend re-rendering before/at merge.
  • LM-02: still fairly generic pygal usage beyond Style/XY basics and HTML export — no distinctive pygal-only feature (e.g. custom tooltip/value formatting) is showcased.
  • DE-01/DE-02: solid and clean, but no extra embellishment (e.g. varied dot sizing, easing on the swarm silhouette) pushes it into the top design tier.

Issues Found

  1. [Process] Stale review artifacts: plot_images/plot-light.png/plot-dark.png did not match the submitted code (data >100 impossible under current np.clip bound).
    • Fix: Re-render from the current commit before GCS promotion; not an implementation defect.
  2. LM-02 LOW: No pygal-distinctive feature beyond Style/XY + HTML export.
    • Fix: Consider custom tooltip value formatting or print_values to showcase pygal-specific capability.

AI Feedback for Next Attempt

Implementation quality is strong and the previous blocking beeswarm-overlap bug is fixed (verified via independent re-render). Remaining headroom is only in Library Mastery (showcase a pygal-distinctive feature) and Design Excellence polish — neither is blocking.

Verdict: APPROVED

@github-actions github-actions Bot added quality:88 Quality score: 88/100 ai-approved Quality OK, ready for merge and removed quality:75 Quality score 75/100 labels Jul 26, 2026
@MarkusNeusinger
MarkusNeusinger merged commit b4dc4ea into main Jul 26, 2026
3 checks passed
@MarkusNeusinger
MarkusNeusinger deleted the implementation/swarm-basic/pygal branch July 26, 2026 07:28
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:88 Quality score: 88/100

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant