Skip to content

GLOOK-58: Recharts 3 chart migration, with "Not measured" weeks - #75

Merged
maescomua merged 53 commits into
mainfrom
feat/glook-58-recharts-migration
Sep 28, 2026
Merged

maescomua merged 53 commits into
mainfrom
feat/glook-58-recharts-migration

Conversation

@maescomua

@maescomua maescomua commented Sep 28, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Replaces the hand-rolled SVG charts with Recharts 3 and a ported shadcn/ui chart.tsx wrapper (the Tailwind v3 variant). Every chart now follows the light/dark theme, shows its values on hover, and reads its colours from one set of tokens.

  • Theme tokens: --chart-* CSS variables for both modes in globals.css, exposed through tailwind.config.ts. The palette was checked for colour-vision-deficiency separation and 3:1 mark contrast on the light and dark chart surfaces. Guard tests stop a literal colour from creeping back into a chart module.
  • Charts migrated:
    • one date-placed TimelineChart shared by the org and dev pages, with synced hover
    • stacked commit types, diverging lines added/removed, and a commit-type donut
    • Spend vs Impact as a scatter, with medians drawn in the dots' own scale
    • the vulnerability trend chart, with team colours that stay stable when the filter changes
    • the project progress ring, plus the volume and progress bars
  • In-flight work (unmerged commits) uses a hatch pattern, never colour alone, and keeps a 4px minimum height so a small segment stays visible.
  • Week keys are UTC. Before, a week's key depended on the viewer's time zone.

Behaviour change: "Not measured" weeks

Before this change, a week that no report covered drew as a real zero. The weekly charts now tell those two cases apart:

  • A week is measured when completed reports cover all 7 days of it. The window for each report is [completed_at − period_days, created_at], and the windows are unioned before counting.
  • A week with shipped work is always measured.
  • An unmeasured week has no bar, and its tooltip says "Not measured". The header totals skip it.
  • The charts end at the report's own week, not today.
  • Coverage is org-level on both the org and dev pages. A developer on vacation during a covered week reads 0 for that week, not "Not measured".
  • Test-mode runs count as normal coverage. They get no special handling for now.

New setting: Chart colors

After the first dev deploy, the accent-coloured weekly timelines read as too loud on dark themes, especially Amber Glow. Five of them sit on the org page and six on the dev page. Settings → Appearance → Chart colors lets each user pick one of three options:

Option Timeline colour
Vivid (default) the theme accent, unchanged
Soft the accent blended 70% with the chart card colour
Deep the theme's darker accent step on dark themes; the same as Vivid on light themes, where that step is louder
  • Only the single-metric timelines change, both their bars and their in-flight hatch. Multi-series charts and the rest of the UI keep their colours.
  • The choice is stored per browser in localStorage (glooker-chart-accent), like the theme. There is no DB or API change.
  • Vivid keeps the 3:1 contrast floor. Soft and Deep are opt-in and can fall below it on some themes; the control's help text says so.
  • The control uses native radios, so it works with arrow keys and has one tab stop, and it has a visible focus ring.

Dependencies

recharts@^3.10.1, react-is@^19 (a Recharts peer), clsx, tailwind-merge@^2.6 (the last version for Tailwind v3). npm audit reports no new vulnerabilities.

Rollout notes

  • MySQL session time zone. Coverage compares created_at and completed_at as UTC. db/mysql.ts does not pin the session time zone. Run it in UTC, or some weeks may be marked "Not measured" or measured wrongly.
  • Weeks now split in UTC. A Sunday-evening commit made west of UTC moves into the following week, so some weekly totals shift slightly compared with main.
  • No migration. No schema changes, so rolling back to the previous image is safe.

Other

  • The seed data is re-anchored to today and gains in-flight commits, so npm run dev:mock fills the 90-day chart window.
  • Jest gets a ResizeObserver stub, which Recharts needs under jsdom.
  • Design spec: docs/superpowers/specs/2026-09-25-glook-58-recharts-migration-design.md (the chart colors setting is Decision 16). Plan: docs/superpowers/plans/2026-09-25-glook-58-recharts-migration.md.

Test plan

  • npm test: 194 suites / 1898 tests, also under TZ=UTC and a UTC+9 zone for the coverage and week-key suites
  • npx tsc --noEmit, npm run build
  • Visual check on npm run dev:mock, including the "Not measured" hover
  • Visual check of the Chart colors control: Amber Glow with each option, Daylight Blue with Deep, keyboard focus, and the org timeline with Vivid and Soft
  • CI on Node 20 for the latest push (local runs used Node 24)

🤖 Generated with Claude Code

maescomua and others added 30 commits September 25, 2026 10:00
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Filtered-series colour contract, count vs ratio week filling, hatch
mechanics with per-instance pattern ids, signed-stack diverging bars,
fixed ProgressRing angle domain, split palette validation, global
ResizeObserver stub, third type-colour map in team/dev-table.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Adds the Spend vs Impact scatter, UTC week keys at the source,
separate commit-type badge treatment, unknown-type folding, the
ProgressRing empty-state exception, react-is, the jsdom sizing
correction, and the full data-visual inventory. Drops the 3:1 rule
for decorative gridlines, which was an error.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…tch pattern

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…mmits

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…dev pages

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…d negative in-flight

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…page

Adds StackedTypesChart, LinesChangedChart and CommitTypeDonut (Recharts),
folds the org page's type breakdown through typeEntriesFrom, and deletes
the old TYPE_COLORS/TYPE_HEX maps and hand-rolled SVG chart functions.
The donut's slice-hover test (Step 7) passed in jsdom and was kept.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…ble shape, hover guard

Restores churn (added + removed as magnitudes) for the lines-changed tooltip's
total, matching the "Lines Changed / Week" card title and the old chart's
behavior; the brief's own step-4 formula and the previous net-change total
were both wrong, and the previous test's '50 total' baked in the bug.
Extracts a shared TypeSwatch into hatch.tsx to de-duplicate the
hatched-vs-solid swatch rendering across the three chart components. Hoists
StackedTypesChart's per-type bar shape to module scope so it's stable across
renders. Guards CommitTypeDonut's onMouseEnter against an unresolved type.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…ots' scale

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
The brief's verbatim tooltip code called p.impact.toFixed(1) directly. Every
value that reaches the tooltip via the chart is already toNum'd by
SpendImpactScatter's `clean` mapping, so this never threw in practice — but
the tooltip is exported on its own, and the spec says charts never throw on
a string DECIMAL value. A string impact reached this way would throw
TypeError: toFixed is not a function. Fixed and pinned with a test that
renders the exported tooltip directly with a string-valued payload.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…nd badges

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…wording

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…0 domain

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Full suite: 187 suites / 1798 tests green (baseline 186/1791 + this guard's 7 tests).
Build green. Screenshot pass (Amber Glow, Daylight Blue, Fresh Mint; org incl. spend
tab, dev, team, home, reports, vulnerabilities, projects) checked against the chart
list and the inline-bar/badge table. Light-mode fixes: none needed.

Concern (not fixed, per brief step 8 item 4's own fallback): the org Commits/Week
chart's in-flight segment for the seeded 1-in-flight/11-commit week renders as an
invisible 2px sliver, indistinguishable from the solid shipped bar below it, in all
three themes. Tried the brief's suggested minPointSize={4} on the in-flight Bar in
timeline-chart.tsx: it fixed the sliver but forces every zero-in-flight week onto a
visible hatch height too (3 timeline-chart tests failed), so reverted. Filed as a
finding for the report; no chart-module edit was kept.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Fix round 1 (Decision 9: in-flight is never shown by colour alone). The org
Commits/Week chart's in-flight Bar, StackedTypesChart's in_flight series, and
LinesChangedChart's inFlightAdded/inFlightRemoved series all get a function
minPointSize, floored to 4 only when the row's own in-flight value is non-zero.

Deviated from the literal `v => (toNum(v) !== 0 ? 4 : 0)` snippet: Recharts'
minPointSize callback receives `value[1]`, the cumulative top of this layer's
slice in the stack (e.g. shipped + inFlight), not inFlight's own delta (confirmed
by reading node_modules/recharts/es6/cartesian/Bar.js:601). On a shipped-only
week that cumulative top is still non-zero, so that snippet forced a 4px hatch
onto every week regardless of whether it actually had in-flight work — exactly
the 3 test failures the first attempt hit. Each callback instead reads the row's
own in-flight value by index from the chart's own `rows` array, which is correct
regardless of what Recharts' internal stack layer math passes in.

lines-changed-chart.tsx's removed-side segment renders with a negative `height`
attribute (it extends downward from the baseline); minPointSize's sign-preserving
math is already correct for it, so the added and removed callbacks are identical
in shape (`!== 0`, not `> 0`, per the fix-round instructions).

Tests: one behavioral test per chart (timeline-chart, stacked-types-chart,
lines-changed-chart), each rendering a large-total/tiny-in-flight week next to a
zero-in-flight week, asserting the hatch rect's height (or its absolute value, on
lines-changed-chart's removed side) is >= 4, and that the zero-in-flight week
draws no hatch rect at all. Verified RED against the un-fixed component for all
three before restoring the fix, and RED against the literal-snippet version
before switching to the row-indexed lookup, both by hand before committing.

Full suite: 187 suites / 1801 tests green (previous 1798 + these 3). Build green.
Re-screenshot of checklist item 4 (the short in-flight segment) in all three
themes, at default and ~390px width, confirms a legible multi-stripe hatch on
the Commits/Week, Lines Changed/Week, and Commit Types Over Time charts' Sep 21
column; items 3 (large in-flight segment) and 5 (diverging chart corners, zero
line) re-checked with no regression.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…t test; shared in-flight floor

1. Donut layout (commit-type-donut.tsx). The wrapper was `w-full max-w-[320px] shrink-0`, which
   can't shrink below its content and clipped at the card's left edge at ~390px (confirmed in the
   controller's own screenshot). Changed to `relative min-w-[160px] flex-1 max-w-[320px]`: a flex
   item's default min-width is its content size, which blocks shrinking; an explicit min-width
   (160px, not the literally-suggested `min-w-0`) replaces that default so it shrinks freely down
   to a still-legible floor and never to 0 (aspect-square + Recharts needs a measurable width).
   The legend column got `shrink-0`, and the row got `flex-wrap` so the legend drops below when
   both can't fit side by side, instead of overflowing.

2. Donut direction regression vs. main. Recharts' `<Pie>` default draws counter-clockwise from
   3 o'clock; main drew clockwise from 12. Added `startAngle={90} endAngle={-270}`, matching
   ProgressRing. Wedges now read in COMMIT_TYPE_ORDER starting at 12, same as the legend.

3. Real week-domain alignment test. chart-format.test.ts's old guard compared
   `recentWeekDomain(now)` with itself — a tautology that can't fail and never rendered a chart,
   so a chart that quietly built its own domain from its own `data` would still pass it. Replaced
   with `chart-domain-alignment.test.tsx`, which renders TimelineChart, StackedTypesChart and
   LinesChangedChart from one shared `weeks` array with real data only in the first and last week,
   and asserts each chart's first Bar renders exactly `weeks.length` category slots with the real
   values landing on slot 0 and the last slot.
   Deliberately does NOT read x-axis tick text/count, despite that being the more obvious
   approach: a first attempt did, and found only 1 of 5 ticks rendered in jsdom (Recharts'
   `interval="preserveEnd"` culls ticks using text-width math, and jsdom's
   getComputedTextLength/getBoundingClientRect always return 0) — exactly what this repo's own
   Testing conventions already warn about ("jsdom has no SVG text layout... never assert on tick
   counts, tick positions, or label placement"). Reading Bar rectangle DOM-node counts instead
   avoids that text-layout dependency entirely.
   Mutation-checked: temporarily changed stacked-types-chart.tsx to build its rows from `data`
   instead of the passed `weeks` prop; the new test failed (5 expected, 2 received). Reverted
   (byte-identical diff against a backup) and reran green before committing.
   chart-format.test.ts keeps only the one assertion that's actually specific to the pure
   function (recentWeekDomain's default 90-day window matches an equivalent buildWeekDomain
   call); the page-level "every chart gets the same domain" promise now has a test that can fail.

4. Shared in-flight floor. The index-based `minPointSize` callback
   (`(_, i) => toNum(rows[i]?.[key]) !== 0 ? 4 : 0`) was duplicated four times across
   timeline-chart.tsx, stacked-types-chart.tsx and lines-changed-chart.tsx. Extracted to
   `inFlightFloor(rows, key)` in hatch.tsx (natural home: it exists only to keep the in-flight
   hatch legible, the same reason hatch.tsx exists), with one shared comment, and used in all
   four places with identical behavior. Existing minPointSize tests pass unchanged.

Full suite: 188 suites / 1804 tests green (previous 1801 + 3 new in chart-domain-alignment).
Build: green. Screenshotted the org Impact tab in Daylight Blue at 375/768/1024px: the donut is
fully visible at every width (no clipping), the legend wraps below at 375/768 and sits beside it
at 1024 without overflowing, and the slices run clockwise from 12 (feature→bug→refactor→docs→
test→in_flight), matching the legend order and main's pre-migration behavior.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
maescomua and others added 23 commits September 25, 2026 17:04
1. chart-domain-alignment.test.tsx put its data at weeks[0]/weeks[4] — the shared domain's own
   edges. A realistic version of the bug this test exists to catch (a chart gap-filling its own
   domain from its own data's min/max week, e.g. buildWeekDomain(minWeek(data), maxWeek(data)),
   instead of the passed `weeks` prop) would, with boundary data, build a domain whose first/last
   week happen to equal weeks[0]/weeks[4] too — so the old version would have passed either way.
   Moved the data to interior weeks (index 1 and 3); the test now asserts weeks.length slots with
   values at slots 1 and 3, and slots 0/2/4 empty.

   Mutation-checked with that realistic bug: temporarily made stacked-types-chart.tsx build its
   domain via `buildWeekDomain` over its own data's min/max week instead of the `weeks` prop. The
   test failed (5 expected, 3 received: the 2-week-apart interior data produced a 3-week domain,
   not aligned to slots 1/3). Reverted, confirmed the restored file was byte-identical to a backup
   via `diff`, reran green. Also re-ran the existing naive mutation (rows built from `data` instead
   of `weeks`) against the new interior-week data to confirm it still fails (5 expected, 2
   received) — same revert-and-diff process.

2. Added a jsdom-safe geometric test to commit-type-donut.test.tsx proving the first sector
   (feature) starts at 12 o'clock and sweeps clockwise: the outer edge's opening "M x,y" point has
   x equal to the pie's own cx and y above cy (SVG y-axis points down), and the first arc command's
   sweep-flag (the 5th of its six numeric args) is 1 — the actual bit `startAngle`/`endAngle`
   changes, independent of any one slice's size, unlike reading the arc's far endpoint. Mutation-
   checked: removed `startAngle`/`endAngle` from commit-type-donut.tsx, confirmed the new test
   failed (the M point landed at x=308.8 for a cx of 160, nowhere near 12 o'clock), reverted,
   confirmed byte-identical via diff, reran green.

3. hatch.tsx's inFlightFloor JSDoc said "each of which called this identically three times before,"
   but there are four call sites (LinesChangedChart alone has two: inFlightAdded and
   inFlightRemoved). Fixed the count and reworded to name them.

Test-only changes plus one comment; no build needed. Focused tests (chart-domain-alignment,
commit-type-donut, timeline-chart, stacked-types-chart, lines-changed-chart, chart-format,
chart-no-literal-colors): 7 suites / 66 tests green. Full suite: 188 suites / 1805 tests green
(previous 1804 + 1 new donut test).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Count charts no longer draw unmeasured weeks as zero: the server
returns the weeks any report period covered, and the week window ends
at the report's own completion week instead of today.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Completed reports only, windowed on completed_at; per-login coverage on
the dev page; whole UTC days only; a server-computed anchorWeek; rows
keep numeric values plus a measured flag that all three tooltips read.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…d anchor

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…nses

Decision 15, server side. Only completed reports count, windowed on
completed_at, and a week is listed only when all 7 of its UTC days are
covered. The dev page counts only reports with a developer_stats row for
that login. Windows are merged into their union first, so reports that
meet mid-day leave no hole. anchorWeek is completed_at's week for a
completed report and created_at's otherwise; an unparseable source falls
back to the current UTC week. Both are read from the existing reports
query, so the call order is unchanged.

Full suite: 190 suites / 1836 tests green (expected about 190 / 1836).
Both coverage files also green under TZ=UTC.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…member was searched

Decision 15 review fix. report-runner.ts searches each member from
runStart - period_days with NO upper bound, at some moment at or after
runStart. A member searched early in a long run is not re-searched for
commits made later in that same run, so a window ending at completed_at
could over-claim the run's own tail. created_at <= runStart is the last
instant every member's search, even the earliest, is guaranteed to have
covered, so the window is now [completed_at - period_days, created_at].
A window whose edges land the wrong way round (a report resumed long
after it was created) contributes nothing, which the existing
start >= end guard already handles (confirmed by mutation).

Both org.ts and dev.ts now SELECT created_at alongside the other reports
columns in the existing widened query; call count and order are
unchanged. completedReportWindows and coveredWeeksFromWindows in
timeline.ts carry both edges explicitly (completedAt, createdAt) instead
of a single end + period.

Tests updated: pure tests now build windows from (completed_at,
created_at, period), with new cases proving the right edge is created_at
(not completed_at), a long run doesn't claim the week holding its own
tail, and a report resumed far later yields an empty window. DB fixtures
that put created_at exactly period_days before completed_at (rA, rOther,
rAdj1, rAdj2) became zero-length windows under the fix, so they're
changed to created_at == completed_at (a quick, non-resumed run), which
reproduces the pre-fix window exactly; rB (resumed far later) is
unchanged and now correctly contributes no coverage, updating three DB
expectations accordingly.

Full suite: 190 suites / 1839 tests green. Both coverage files also
green under TZ=UTC.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Minor finding from the Task 12 re-review: no DB-level test went through
the real getOrgReport SQL with a report whose created_at is a few hours
before completed_at (a genuine narrowing that still leaves a non-empty
window) - only the pure helper covered it.

Adds rNarrow in its own org (acme-narrow), created Sunday 2026-03-15T20:00Z,
completed Monday 2026-03-16T03:00Z, period 14 days. Sunday is deliberately
the LAST day of its ISO week: the other 6 days (Mon-Sat) are already
inside the window regardless of which right edge is used, so completing
Sunday is what completes the week. With the correct right edge
(created_at), coveredWeeks is []; mutation-tested by swapping the right
edge back to completed_at, which makes Sunday whole and wrongly claims
the week of Mar 9 - confirmed by running the test (7 failures total:
this one plus the 6 from the prior round), then reverted by Edit.

Note: a version of this fixture with the roles reversed (created Monday,
completed Tuesday, as in the original finding's example) would NOT
discriminate at the week level - Monday is the FIRST day of its week,
and the other 6 days are never reached by either right edge, so that
week can never be whole either way. Verified this by derivation and by
running the Monday/Tuesday design's would-be mutation check, both
independently of the advisor's arithmetic, before choosing Sunday/Monday
instead.

Full suite: 190 suites / 1840 tests green. Both coverage files also
green under TZ=UTC (35/35).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…ort's week

Decision 15, client side. Rows of the three page-grid charts carry a
measured flag (data, or a covered week), their tooltips say "Not measured"
for an unmeasured week, and both pages build one domain with
weekDomainEndingAt(anchorWeek) and pass coveredWeeks to every grid chart
(org: 7, dev: 6). Empty states read "in the 90 days before this report".

Full suite: 191 suites / 1861 tests green (expected about 191 / 1857). Build green.
chart-format and the wiring test also green under TZ=UTC.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Seven chart call sites from 9d1f53b had coveredWeeks={coveredWeeks} joined
to the next attribute with no space (org: 4, dev: 3). Whitespace only.
Wiring test and tsc green.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Also fixes stale helper and window wording flagged in the final review.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…dening

Decision 15 final-review fixes.

- The org page's in-flight overlay creates week buckets (unmerged_commits has
  no date filter), so "a row exists" proved nothing. A new shared helper,
  hasShippedData (commits - types.in_flight > 0), replaces it in all three
  row builders. An uncovered in-flight-only week is now unmeasured.
- NotMeasuredTooltip takes an optional in-flight line, so a hatched week
  reads "Shipped: Not measured / In flight: N" rather than contradicting its
  bar. The TimelineChart header takes latest and change from measured weeks
  only. The dev page has no overlay and is unchanged.
- anchorWeekFor: a completed report with a null or unparseable completed_at
  falls back to created_at, then to today.
- A new child-process test under TZ=Asia/Tokyo feeds zone-less SQLite
  timestamps through completedReportWindows, coveredWeeksFromWindows and
  anchorWeekFor, and fails if they are parsed as UTC.

Mutation-checked: reverting hasShippedData to "row exists" fails 9 tests
across all three charts and the header. UTC parsing fails the Tokyo test on
both the covered weeks and the anchor.

Full suite: 192 suites / 1877 tests green. The coverage and chart suites
are green on the host zone, under TZ=UTC and under TZ=Asia/Tokyo. tsc and
build green.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The org page's AI % chart gated isDefined on merged commits, which include
in-flight. A covered in-flight-only week then read a proven-looking 0%.
It now uses hasShippedData, so that week is a null gap.

The other ratio gates need no change:
- Org Avg Lines/PR keys on prs, which the overlay never adds to.
- Org Avg Impact is merged before the overlay creates buckets, so an
  overlay-only week has none.
- The dev page has no overlay.

The measured field comments now say "no SHIPPED data". The wiring test
checks the org AI % chart's isDefined and its gap.

Full suite: 192 suites / 1878 tests green. tsc green.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…exact guard-test steps

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…elines

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@maescomua
maescomua merged commit 5b01fb6 into main Sep 28, 2026
1 check passed
@maescomua
maescomua deleted the feat/glook-58-recharts-migration branch September 28, 2026 21:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant