feat(registry): week in merges leaderboard block - #4264
Conversation
Authors race across the row at a speed set by their merge count, bouncing at both edges.
|
Preview deployment for your docs. Learn more about Mintlify Previews.
💡 Tip: Enable Automations to automatically generate PRs for you. |
Wrap the lines oxfmt rejects so the format check passes.
The format pass left the committed payload off the generator output.
The block races at most rows_max authors, highest merge count first, and writes one line for everyone left out. The default is 12, so a long list cannot shrink the rows.
jrusso1020
left a comment
There was a problem hiding this comment.
Changes requested on 2e1dbb77 — one finding, and it is about the thing the block is for.
The wiring is clean and I checked it rather than assuming: the copy of the block embedded in docs/catalog/blocks/week-in-merges.mdx is byte-identical to registry/blocks/week-in-merges/week-in-merges.html (both 471 lines, codeLines: 471 is accurate), registry.json / docs.json / the gallery snippet are all inserted alphabetically with the nav tag bumped 17 → 18, and main has moved 2 commits since your merge-base but touched none of the shared generated artifacts, so there is no stale-after-merge hazard here.
I ran the real block in real Chrome (real GSAP from the CDN pin, real layout, driving window.__timelines["week-in-merges"] through tl.seek()) across eight variable bindings.
Confirmed working
- The twelve cap holds, including against an explicit override. 15 authors → 12 rows +
"and 3 more people with 6-8 merges". I also boundrows_max: 50with 20 authors and still got 12 rows —num(..., 1, 12)clamps before the slice, so the declared"max": 12is not the only thing enforcing it. That is the Slack claim, and it is true. - The bounce is a correct triangle wave. Every row that has the distance to reach an edge reaches
x = 0andx = span(measured 529/532 at 5 rows, 574–578/578 at 12 rows) and turns around. No drift, no overshoot. - Ink-disc placeholders, lead/rest tint, and
mergeLabelsingular/plural all behave ("1 merge"vs"12 merges"). - The
seek-driven setter works. Your comment aboutonUpdatenot firing on seek is correct, and theObject.definePropertydriver does get called on every seek — that is why I could sample it at all.
Blocking: the speed mapping is not the mapping the block claims
speedFor() is a min–max rescale of the visible range onto [10, 300] px/s, so the slowest visible author is pinned to the floor regardless of their count, and the fastest is pinned to 300 regardless of theirs. The rendered footer — I read it out of the live DOM, not the source — is:
Speed proportional to merges · By PR author
and the docs description is "at a speed set by how many pull requests they merged". Neither is what runs. Measured distance travelled in the 16s timeline:
| bound rows | merges | px/s | px in 16s | reaches the edge? |
|---|---|---|---|---|
| default | 12 | 300.0 | 4800 | yes |
| default | 1 | 10.0 | 160 | no |
| tight race | 20 | 300.0 | 4800 | yes |
| tight race | 18 | 10.0 | 160 | no |
| near-tie | 30 | 300.0 | 4800 | yes |
| near-tie | 29 | 10.0 | 160 | no |
Two consequences, both measured:
- A 3.3% gap in output renders as a 30x gap in distance. With 30 and 29 merges, the leader crosses the lane four times and bounces; the 29 crawls 160px and never reaches an edge. A viewer reads that as "Bo did nothing this week."
- 1 merge and 18 merges are pixel-identical. Both travel exactly 160.0px. The block cannot distinguish a quiet week from a photo finish — last place always looks the same.
A tight top-3 is the normal shape of a week in an active repo, so this is the common case, not the tail. Two ways out, your call:
- keep the visual and fix the copy — something like
Leader sets the pace · By PR author— and reword the frontmatterdescription; or - make it true: scale on
merges / maxMso 29-of-30 reads as 29-of-30, and keep a floor only for genuine zeroes.
I'd take the second; the first is a one-line change if you want this in today.
Notes, not blocking
initials()splits on whitespace only, so GitHub logins get one letter.miguel-heygen→"M",jrusso1020→"J". I bound twelve single-token names and got twelve identical discs. Your screenshots use real avatars so this only bites the no-avatar path, but that is the path the fallback exists for.name.trim().split(/[\s_-]+/)gets youMH.- The shipped default is internally inconsistent.
totaldefaults to"12 PRs"while the five default rows sum to 26 merges. That default render is exactly what the catalog gallery card and the docs page show. - An empty week silently renders fabricated people.
parseRowsreturnsnullwhen the array parses but yields no usable rows, sorows: "[]"falls through toFALLBACK_ROWS— I bound it and got Ada/Bao/Cam/Dee/Eli, under whatever realperiod,totalandsourcelines the caller bound. Malformed JSON falling back is fine; valid and empty is a real state for a quiet week, and publishing invented names under a real date line is the bad version of that. Worth distinguishing the two.
Re-review as soon as you push.
— Rames
A row now travels the leader's pace times its merges over the leader's count. Only a zero stays on the floor, so a near-tie no longer looks like last place.
|
Speed is the leader's pace times this count over the leader's count. A zero is the only count on the floor, so 29 of 30 travels 29/30 of the leader and 1 of 30 travels 1/30. |
jrusso1020
left a comment
There was a problem hiding this comment.
Approving 8b6cc3f8. The blocker is closed and I re-derived it rather than taking the diff's word for it — you implemented the remedy I suggested, which is exactly the situation where a reviewer rubber-stamps his own idea, so I re-ran the same harness at this head instead of re-reading the patch.
speedFor is now LEADER_SPEED * merges / maxM with a floor only at zero. Same eight bindings, real Chrome, real GSAP, driven through tl.seek():
| bound rows | merges | px reached at old head | px reached here |
|---|---|---|---|
| near-tie | 30 | 529 | 529 |
| near-tie | 29 | 160 | 531 |
| tight race | 20 | 529 | 529 |
| tight race | 18 | 160 | 531 |
| 12 rows | last row (9) | 160 | 577 |
| default | 1 of 12 | 160 | 400 |
Every row that used to be pinned to the floor now travels its share. 1 of 12 landing on exactly 400px is 300 × 1/12 × 16 to the pixel, so the mapping is doing what it says. The footer that was wrong at the last head — Speed proportional to merges — is now true, so leaving the copy alone was the right call.
I checked your zero claim too, since it is the one case the formula special-cases. 10 / 5 / 0 → the zero row travels 160px and never bounces while the other two race; everyone at zero → all rows on the floor. "Only a zero stays on the floor" holds.
The regeneration is clean: the copy embedded in the mdx is byte-identical to the source again (469 = 469) and codeLines moved 471 → 469 with it.
One note on the new test — not blocking, it does its job
weekInMergesSpeed.test.ts is wired correctly (vitest's default include picks up src/**/*.test.ts, linkedom is a real devDependency of packages/cli) and it reads the block straight off disk, so it cannot drift from the file it guards. Good shape.
But the headline assertion cannot fail on the code it was written to replace. With [30, 29, 1] the old min–max map reduces to exactly 10·m:
old: FLOOR + (LEAD-FLOOR)·(m-minM)/(maxM-minM) = 10 + 290·(m-1)/29 = 10·m
new: LEAD·m/maxM = 300·m/30 = 10·m
I ran both implementations through your harness geometry:
Assertion 1 — rows [30,29,1], no cap
merges | OLD px | NEW px
30 | 300.0 | 300.0
29 | 290.0 | 290.0
1 | 10.0 | 10.0
=> on OLD code: PASSES (does not discriminate)
Assertion 2 — same rows, rows_max:2
30 | 300.0 | 300.0
29 | 10.0 | 290.0
ratio 29/30: want 0.9667 | OLD 0.0333 (err 96.6%) | NEW 0.9667
=> on OLD code: FAILS (discriminates)
So the rows_max: 2 sub-case is carrying the entire regression guard, and it is a good one — it fails the old implementation by 96.6%. The first binding is decorative: pick a leader count that is not FLOOR/LEAD away from the floor slope (say [31, 29, 1]) and it would discriminate too. Worth a comment saying which half is the guard, so nobody later "simplifies" the capped case away.
Also minor: the if (!(maxM > 0)) return LEADER_SPEED branch is unreachable — reaching it needs merges > 0 and maxM <= 0, but maxM is the max over the visible rows so it is always >= merges. Harmless; delete it or keep it as a belt, your call.
Still open from the last pass, none of them blocking
initials() splits on whitespace only, so miguel-heygen → M; the default total says "12 PRs" while the default rows sum to 26; and rows: "[]" still falls through to the Ada/Bao/Cam demo people. Happy for those to land as-is or as a follow-up.
— Rames
heygen-com#4264 added the week-in-merges block and its registry.json entry. heygen-com#4277 regenerated registry.json from a branch that predated heygen-com#4264, which removed the entry again. The block directory, catalog page and docs nav link all remained, so the catalog advertises a block that `hyperframes add week-in-merges` rejects with "Item not found in registry".
A catalog block for one week of merged pull requests. Each author's avatar travels its own row. Speed rises with that author's merge count, and the avatar bounces when it meets either edge.
Placeholders in the block are ink discs with initials. The frames below use public GitHub avatars for heygen-com/hyperframes, 14 September through 21 September 2026.
Before
After