Skip to content

feat(d3): implement span-basic - #9862

Merged
MarkusNeusinger merged 6 commits into
mainfrom
implementation/span-basic/d3
Jul 25, 2026
Merged

feat(d3): implement span-basic#9862
MarkusNeusinger merged 6 commits into
mainfrom
implementation/span-basic/d3

Conversation

@github-actions

Copy link
Copy Markdown
Contributor

Implementation: span-basic - javascript/d3

Implements the javascript/d3 version of span-basic.

File: plots/span-basic/implementations/javascript/d3.js

Parent Issue: #980


🤖 impl-generate workflow

@claude

claude Bot commented Jul 25, 2026

Copy link
Copy Markdown
Contributor

AI Review - Attempt 1/3

Image Description

Light render (plot-light.png): A quarterly market-index line chart (2006–2011) on the #FAF8F1 warm off-white surface. The brand-green (#009E73) line traces the index from ~102 up to a peak of ~117 (late 2007), down through a trough of ~96 (2009), and back up to ~113 (2011) before a final dip. Two matte-red (#AE3030) semi-transparent vertical bands mark "2007–09 recession" and "2011 slowdown", each with a centered in-band text label. Y-axis gridlines only (subtle, light gray), dark ink title/axis-title text, softer ink tick labels. Title "span-basic · javascript · d3 · anyplot.ai" is bold, centered, comfortably sized. All text — title, axis titles ("Year", "Market Index"), tick labels, and both span labels — is clearly legible against the light background. Legibility verdict: PASS.

Dark render (plot-dark.png): Same layout and data on the #1A1A17 warm near-black surface. The line stays the identical brand green, and the span fill is the identical matte-red hue but rendered as a darker translucent maroon against the dark background (correct — only chrome should flip, and it does: title/axis text switch to light ink, gridlines switch to a light, low-opacity color). All text is clearly readable — no dark-on-dark failures observed anywhere (title, axis titles, tick labels, and span labels all render in light ink against the dark surface). Data colors are confirmed identical to the light render. Legibility verdict: PASS.

Both renders pass the theme-readability checklist; no chrome or text legibility failures in either theme.

Score: 80/100

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

Visual Quality (27/30)

  • VQ-01: Text Legibility (7/8) — all sizes explicitly set (title 26px, axis titles 17px, ticks 15px, span labels 13px), fully readable in both themes, no overflow/clipping.
  • VQ-02: No Overlap (6/6) — no text/element collisions.
  • VQ-03: Element Visibility (6/6) — line weight (3px) and span alpha (0.22) are well-adapted; both clearly visible without obscuring each other.
  • VQ-04: Color Accessibility (2/2) — green line vs. red span differ by both hue and visual channel (line vs. filled region), not relying on hue alone.
  • VQ-05: Layout & Canvas (2/4) — see weakness Add Claude Code GitHub Workflow #2: the "2011 slowdown" span rectangle overflows the plot's inner width and bleeds through the entire right margin to the canvas edge, leaving that margin with zero whitespace versus the intact left/top/bottom margins.
  • VQ-06: Axis Labels & Title (2/2) — "Year" / "Market Index" are descriptive; "Market Index" is a self-describing dimensionless index label, no unit needed.
  • VQ-07: Palette Compliance (2/2) — first series is exactly #009E73; span uses palette[4] (#AE3030), the designated semantic anchor for bad/loss/error, an apt semantic match for recession/slowdown periods. Backgrounds and chrome are theme-correct in both renders.

Design Excellence (13/20)

  • DE-01: Aesthetic Sophistication (5/8) - Intentional semantic color choice (red for recession spans) and clean in-band labeling lift it slightly above a generic default, but overall polish is modest.
  • DE-02: Visual Refinement (4/6) - L-shaped spine retained per style guide, y-only gridlines, generally clean — held back by the margin-bleed issue below.
  • DE-03: Data Storytelling (4/6) - The highlighted recession bands create a clear visual focal point and narrative (index falls during red-shaded periods) without needing separate annotations.

Spec Compliance (12/15)

  • SC-01: Plot Type (5/5) - Correct span-over-line-chart pattern.
  • SC-02: Required Features (2/4) - Only the "vertical" span direction is demonstrated; the spec's direction field explicitly names both "vertical" and "horizontal" as valid values, and this spec's matplotlib/seaborn/plotly sibling implementations all include a horizontal span alongside the vertical one.
  • SC-03: Data Mapping (2/3) - X/Y correctly assigned overall, but the second span's end date (2011-12-01) falls outside the x-scale's domain (last data point 2011-10-01), so the highlighted region visually implies data past what the axis actually covers.
  • SC-04: Title & Legend (3/3) - Title format exactly matches span-basic · javascript · d3 · anyplot.ai; omitting a legend in favor of direct in-band labels is an appropriate choice for a single-series chart.

Data Quality (12/15)

  • DQ-01: Feature Coverage (3/6) - Demonstrates the vertical-span/recession use case well but doesn't cover the horizontal-span/threshold use case the spec also calls out.
  • DQ-02: Realistic Context (5/5) - Plausible, neutral business/finance scenario (market index with historical-style recession periods).
  • DQ-03: Appropriate Scale (4/4) - Index values and drift magnitudes are plausible and internally consistent.

Code Quality (10/10)

  • CQ-01: KISS Structure (3/3)
  • CQ-02: Reproducibility (2/2) - Seeded LCG.
  • CQ-03: Clean Imports (2/2) - Only the d3 global, per the library contract.
  • CQ-04: Code Elegance (2/2) - Clean, no fake functionality.
  • CQ-05: Output & API (1/1) - Correctly mounts into #container per the harness contract, no animations.

Library Mastery (6/10)

  • LM-01: Idiomatic Usage (4/5) - Idiomatic scaleTime/scaleLinear/axisBottom/axisLeft and .data().join() patterns throughout.
  • LM-02: Distinctive Features (2/5) - Basic data-join usage; nothing that leverages a d3-specific capability beyond what's expected as baseline.

Score Caps Applied

  • None

Strengths

  • Correct Imprint palette usage: brand green (#009E73) for the line and the semantically-fitting matte-red (#AE3030) anchor for the recession/slowdown spans, identical across both themes.
  • Span opacity (0.22) sits squarely in the spec's recommended 0.2–0.3 range — underlying line data stays fully visible through the shaded regions.
  • Direct in-span text labels avoid the need for a legend on this single-series chart — a clean, minimal design choice per the style guide.
  • Deterministic seeded data generation, explicit font sizing on every text element, and theme-correct chrome in both renders.

Weaknesses

  • Only a "vertical" span direction is shown. The spec's direction field defines both "vertical" and "horizontal" as valid categorical values, and the matplotlib/seaborn/plotly implementations of this same spec-id both include a horizontal span (e.g., a value-threshold "risk zone" band via axhspan/add_hrect). Add at least one horizontal span so the plot demonstrates both direction variants.
  • The second span ("2011 slowdown", 2011-07-01 to 2011-12-01) extends past the x-scale's domain max (the last data point is quarterly, dated 2011-10-01), so x(d.end) extrapolates beyond the inner chart width iw. Confirmed by pixel probe on plot-light.png: the chart's own axis/domain line ends at x≈3079px, but the pink span fill continues unbroken from x≈2955px all the way to x=3199px — bleeding straight through the entire right margin to the canvas edge. This leaves the right margin with zero whitespace while the other three margins remain intact, and visually implies the highlighted region continues past what the x-axis actually represents. Fix by extending the x-domain to cover the full span range (e.g. d3.extent([...series.map(d => d.date), ...spans.flatMap(s => [s.start, s.end])])), or by clamping the rect's right edge to iw (e.g. Math.min(x(d.end), iw) - x(d.start)).

Issues Found

  1. SC-02/DQ-01 MODERATE: Missing horizontal-span demonstration
    • Fix: Add a horizontal span (fixed y-range, full plot width) alongside the existing vertical spans — e.g. a "target range" or "risk zone" threshold band — so both direction values from the spec are represented.
  2. VQ-05/SC-03 MODERATE: Span rectangle overflows the plot's inner width into the right margin
    • Fix: Extend the x-domain to include the full span range, or clamp span-rect width to the inner chart width iw so no span extends past the plotted axis area.

AI Feedback for Next Attempt

Two concrete fixes: (1) add a horizontal span (e.g. a fixed-value "risk zone" or "target range" band spanning the full plot width) so the implementation demonstrates both span directions the spec defines, and (2) fix the x-domain/span-width math so the "2011 slowdown" span doesn't extrapolate past the axis's actual data range — either widen x's domain to cover all span start/end dates, or clamp each span rect's right edge to the inner chart width iw. Everything else — palette, theme chrome, typography, code cleanliness — is solid and should be kept as-is.

Verdict: REJECTED

@github-actions github-actions Bot added quality:80 Quality score 80/100 ai-rejected Quality not OK, triggers update labels Jul 25, 2026
@github-actions github-actions Bot added ai-attempt-1 First repair attempt and removed ai-rejected Quality not OK, triggers update labels Jul 25, 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 25, 2026

Copy link
Copy Markdown
Contributor

AI Review - Attempt 2/3

Image Description

Light render (plot-light.png): Warm off-white background (#FAF8F1, verified pixel value 250,248,241). Bold, centered dark-ink title span-basic · javascript · d3 · anyplot.ai. Axis titles "Year" / "Market Index" in dark ink, tick labels in softer ink, subtle y-axis-only gridlines. A brand-green (#009E73) line traces a quarterly market index from 2006–2011 (peak ~117, trough ~96). Two matte-red semi-transparent vertical bands mark "2007–09 recession" and "2011 slowdown", each with a centered in-band label. A new amber semi-transparent horizontal band spans the full plot width near the bottom, labeled "Correction zone (index < 97)". All text is clearly readable against the light background; a pixel probe at the right edge confirms the span fill and axis domain line both stop exactly at x=3080px, leaving a clean off-white margin to the canvas edge.

Dark render (plot-dark.png): Warm near-black background (#1A1A17). Title, axis titles, and tick labels switch to light ink; gridlines switch to a low-opacity light color. Data colors are identical to the light render — same brand-green line, same red/amber span hues (rendering as translucent maroon/olive against the dark surface, as expected since only chrome should flip). All text, including the "Correction zone" label sitting on the olive-toned amber band, remains clearly legible — no dark-on-dark failures found anywhere.

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

Score: 91/100

Category Score Max
Visual Quality 29 30
Design Excellence 15 20
Spec Compliance 15 15
Data Quality 15 15
Code Quality 10 10
Library Mastery 7 10
Total 91 100

Visual Quality (29/30)

  • VQ-01: Text Legibility (7/8)
  • VQ-02: No Overlap (6/6)
  • VQ-03: Element Visibility (6/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 (15/20)

  • DE-01: Aesthetic Sophistication (5/8) - Intentional semantic color choices, but overall polish beyond the span highlighting is still modest
  • DE-02: Visual Refinement (5/6) - L-shaped spine, subtle y-only grid, generous margins; no longer held back by the fixed margin-bleed bug
  • DE-03: Data Storytelling (5/6) - Both recession bands and the threshold band create a clear, labeled narrative

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)

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)
  • CQ-05: Output & API (1/1)

Library Mastery (7/10)

  • LM-01: Idiomatic Usage (4/5)
  • LM-02: Distinctive Features (3/5) - Union-domain-across-spans technique and in-place span labeling are distinctive; nothing beyond that

Score Caps Applied

  • None

Strengths

  • Both attempt-1 weaknesses are fully fixed: a horizontal "Correction zone (index < 97)" span now demonstrates the spec's second direction, and the x-domain now uses d3.extent() across both the series dates and every span's start/end so the "2011 slowdown" span no longer bleeds through the right margin — confirmed by pixel probe: the span fill and axis domain line both stop exactly at x=3080px (= 3200 canvas width − 120px right margin), with a clean off-white margin beyond that point.
  • Correct Imprint palette usage: brand green (#009E73) for the line, matte-red semantic anchor for the recession/slowdown spans, and amber semantic anchor for the value-threshold band — identical data colors across both themes, only chrome flips.
  • Direct in-span text labels avoid the need for a legend on this single-series chart, a clean minimal design choice, and unioning series + span dates into one scale domain is a thoughtful, non-obvious D3 pattern.
  • Deterministic seeded (LCG) data generation, explicit font sizing on every text element, and theme-correct chrome in both renders with no dark-on-dark or light-on-light legibility failures.

Weaknesses

  • Title occupies only ~30% of canvas width (measured via pixel scan) — well under the 50–70% comfortable range; a slightly larger title fontsize would strengthen the typographic hierarchy without risking overflow.
  • The 24-point quarterly line series has no per-point markers; per the data-density heuristic, sparse series (< 50 points) should get prominent markers in addition to the line to make individual quarters distinguishable.
  • Where the vertical recession span and the horizontal correction-zone span overlap (e.g. 2008–2009 inside the < 97 band), the two semi-transparent fills blend into an unlabeled third color — consider a slightly different compositing approach or a note so the blended region doesn't read as an unexplained third category.
  • Design polish is still fairly minimal beyond the span highlighting itself (no additional refinement like an end-point marker on the line, subtle separation for the span labels, etc.) — DE-01 stays mid-range.

Issues Found

  1. DE-01 LOW: Aesthetic sophistication is still mid-range despite the fixes
    • Fix: Consider an end-point marker/dot on the line's last value, a touch more refinement on the span-label chips (e.g. a subtle background pill), or a slightly larger title for hierarchy
  2. LM-02 LOW: Distinctive features beyond the domain-union trick are limited
    • Fix: Could lean further into D3-specific idioms (e.g. d3.bisector-driven end-of-series callout, custom tick formatting) to showcase more of the library

AI Feedback for Next Attempt

This attempt correctly fixed both prior weaknesses (missing horizontal span, right-margin bleed from domain extrapolation) — verified via pixel probing the right edge and the span geometry. If revisited, consider: a slightly larger title for stronger hierarchy (currently ~30% of canvas width), small end-point markers on the sparse 24-point line series per the data-density heuristic, and a touch more DE-01 polish (e.g. refined label chips) to push Design Excellence higher.

Verdict: APPROVED

@github-actions github-actions Bot added quality:91 Quality score 91/100 ai-approved Quality OK, ready for merge and removed quality:80 Quality score 80/100 labels Jul 25, 2026
@MarkusNeusinger
MarkusNeusinger merged commit 53a9622 into main Jul 25, 2026
3 checks passed
@MarkusNeusinger
MarkusNeusinger deleted the implementation/span-basic/d3 branch July 25, 2026 14:55
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:91 Quality score 91/100

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant