You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
C1 [critical] — org.ts in-flight overlay bucket was missing the new required
prs / avgLinesPerPr fields. Weeks with only in-flight commits would have
rendered NaN bars / undefined tooltips. Zero-defaulted both in the bucket
initializer.
I1 [important] — PR-level P95 threshold used `floor(N * 0.95)` which at
N ≤ 20 indexes the max element, making the "outliers excluded" filter a
no-op on typical dev pages. Switched to `ceil(N * 0.95) - 1` so the
filter actually kicks in at N ≥ 20. Added regression tests at N=20
(boundary) and N=10 (degrades to no-filter, by design).
I2 [important] — avgLinesPerPr cross-week semantic was undocumented.
Added an in-code comment explaining: a PR's TOTAL across all weeks decides
P95 inclusion (stable filter), but only the per-week slice of lines goes
into the numerator and the denominator counts PRs active in that week.
Added a cross-week test that locks down the semantic.
I3 [important] — spec + plan docs claimed only one chart shipping. Both
updated to reflect what landed: two charts (PRs/Week + Avg Lines/PR with
P95 filter), the SQL pr_number fix, the in-flight-only week edge case,
and the cyan/pink color choices.
I4 [important] — PRs/Week was #A78BFA (purple-400), colliding with AI%
on the same chart grid (#A855F7, purple-500). Swapped to #06B6D4 (cyan).
S1 — Avg Lines/PR now has suffix=" lines" on the tooltip.
S3 — Label appended with " (outliers excluded)" to match the precedent
set by LinesChangedChart.
Skipped: S4 (PR distinctness across repos — pre-existing, separate
ticket); S2/S5/S6 (covered by I1/I3 fixes).
Co-Authored-By: Claude <noreply@anthropic.com>
Copy file name to clipboardExpand all lines: docs/superpowers/plans/2026-05-26-glook-10-prs-first-class.md
+7Lines changed: 7 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -2,6 +2,13 @@
2
2
3
3
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
4
4
5
+
> **Scope expansion (post-implementation):** Tasks 1–4 below cover the original PRs / Week chart. During the smoke step the user requested:
6
+
> - A companion **Avg Lines Changed / PR** chart (added alongside PRs / Week on both pages).
7
+
> - A **P95 outlier filter** on that chart, mirroring the existing Lines Changed smoothing.
8
+
> - A **fix** for the `pr_number` column missing from the org/dev timeline `SELECT` (made the new chart render zeros until corrected).
9
+
>
10
+
> All four shipped together. The spec at `docs/superpowers/specs/2026-05-26-glook-10-prs-first-class-design.md` has been updated to reflect what landed (algorithm, colors, semantics, edge cases). The task list below is preserved as the original plan; treat it as historical.
11
+
5
12
**Goal:** Add a `PRs / Week` time-series chart on the org and engineer pages, mirroring the existing `Commits / Week` chart.
6
13
7
14
**Architecture:** Single data-aggregator change (extend `WeeklyBucket.prs`) cascades to both pages, which each get one new `<TimelineChart>` invocation. No new endpoint, no schema change.
Copy file name to clipboardExpand all lines: docs/superpowers/specs/2026-05-26-glook-10-prs-first-class-design.md
+32-27Lines changed: 32 additions & 27 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1,8 +1,10 @@
1
1
# GLOOK-10 — Surface PR count as a first-class metric in graphs
2
2
3
+
> **Scope note (post-implementation):** Initial design called for a single `PRs / Week` chart. During implementation the user requested a companion `Avg Lines Changed / PR` chart (sized to give the "throughput vs size" story), with a P95 outlier filter mirroring the existing Lines Changed chart's smoothing. Both ship together. This doc has been updated below to reflect what landed.
4
+
3
5
## Goal
4
6
5
-
PR count is the most heavily weighted contributor to the IC impact score (`min(PRs/10, 1) × 2.7`), but it's currently invisible in every time-series chart on the org and engineer pages. Add a `PRs / Week` chart on each page, mirroring the existing `Commits / Week`chart, so the metric that drives impact is also visible in the time-series story.
7
+
PR count is the most heavily weighted contributor to the IC impact score (`min(PRs/10, 1) × 2.7`), but it's currently invisible in every time-series chart on the org and engineer pages. Add a `PRs / Week` chart **and a companion `Avg Lines Changed / PR (outliers excluded)` chart**on each page, mirroring the existing `Commits / Week`and `Lines Changed / Week` charts respectively, so the metric that drives impact is also visible in the time-series story — both as throughput (count) and as size (avg).
6
8
7
9
## Non-goals
8
10
@@ -44,20 +46,19 @@ Extend the `WeeklyBucket` interface and the `aggregateWeekly()` implementation:
44
46
exportinterfaceWeeklyBucket {
45
47
week:string;
46
48
commits:number;
47
-
prs:number; // NEW: distinct pr_number values that week
49
+
prs:number; // NEW: distinct pr_number values that week
50
+
avgLinesPerPr:number; // NEW: avg lines per PR active in week (outliers excluded)
48
51
linesAdded:number;
49
52
linesRemoved:number;
50
53
// ... (rest unchanged)
51
54
}
52
55
```
53
56
54
-
Implementation: in the per-week accumulator, add a `prNumbers: Set<string>` alongside the existing `activeDevs: Set<string>`. For each commit row:
57
+
**`prs`** — in the per-week accumulator, add `prNumbers: Set<string>` alongside the existing `activeDevs: Set<string>`. For each commit row:`if (c.pr_number != null) w.prNumbers.add(String(c.pr_number))`. Emit `prs: w.prNumbers.size`.
55
58
56
-
```ts
57
-
if (c.pr_number!=null) w.prNumbers.add(String(c.pr_number));
58
-
```
59
+
**`avgLinesPerPr`** — first-pass compute `prLineTotals: Map<pr_number, totalLines>` across all weeks. Derive a P95 threshold over distinct PRs using `sortedPrTotals[Math.ceil(N * 0.95) - 1]` (NOT `floor` — `floor` returns the max at N≤20 and the filter degenerates to a no-op). In the per-week accumulator, track `prNumbersP95: Set<string>` and `prLinesP95: number`; only add a commit's lines to these if its PR's total ≤ threshold. Emit `avgLinesPerPr = prNumbersP95.size > 0 ? round(prLinesP95 / prNumbersP95.size) : 0`.
59
60
60
-
Emit `prs: w.prNumbers.size`from the final `.map(...)`.
61
+
**Semantic of `avgLinesPerPr`** — per-week slice of activity. A PR's *total* across all weeks decides whether it's an outlier (stable filter across the chart), but only the lines from this week's commits go into this week's numerator, and the denominator is the count of PRs active in this week. A 400-line PR split 200/200 across two weeks shows avg=200 in each; a 400-line PR landing in one week shows avg=400 there. This is "average per-PR activity in week W," not "size of the average PR overall."
61
62
62
63
### Definition
63
64
@@ -73,28 +74,27 @@ The `commit_analyses` rows already carry `pr_number` and they're already passed
73
74
74
75
### Both pages: `org/page.tsx` and `dev/[login]/page.tsx`
75
76
76
-
1. Add `prs: number` to the local `WeeklyData` interface (mirrors `WeeklyBucket`).
77
-
2. Add **one new `<TimelineChart>`invocation** immediately after the existing `Commits / Week` chart:
77
+
1. Add `prs: number`and `avgLinesPerPr: number`to the local `WeeklyData` interface (mirrors `WeeklyBucket`).
78
+
2. Add **two new `<TimelineChart>`invocations** immediately after the existing `Commits / Week` chart:
3. No `computeValue` or `inFlightValue` props — `prs` is a direct numeric field.
89
-
4. Tooltip / scale / height all inherit from the existing`TimelineChart` defaults.
91
+
3. No `computeValue` or `inFlightValue` props — both are direct numeric fields.
92
+
4. Tooltip / scale / height inherit from `TimelineChart` defaults.
90
93
91
94
### Color choice
92
95
93
-
`#A78BFA` (Tailwind purple-400). Reasoning:
94
-
- Greens are already taken by commits / lines-added.
95
-
- Ambers / reds are lines-removed.
96
-
- Blues are sometimes used for AI%.
97
-
- Purple sits cleanly in the unused part of the existing palette and won't clash on either page.
96
+
-`#06B6D4` (Tailwind cyan-500) for **PRs / Week** — distinct from `#A855F7` (purple-500) used by AI Assisted % on the same grid; earlier purple-400 (`#A78BFA`) was too close to the AI hue.
97
+
-`#EC4899` (Tailwind pink-500) for **Avg Lines Changed / PR** — reads as "size, not count," and doesn't collide with amber (used by Avg Complexity on the dev page).
98
98
99
99
### Placement
100
100
@@ -104,21 +104,26 @@ The new chart goes **immediately after** Commits/Week on both pages. Rationale:
104
104
105
105
| Layer | What | Where |
106
106
|---|---|---|
107
-
| Unit — aggregator |`aggregateWeekly()` emits `prs` = distinct `pr_number` count per week. Cases: rows with no `pr_number` → 0; rows with duplicate `pr_number` → counted once; rows with multiple distinct PRs → all counted; PR spanning two weeks → counted in each. | New file `src/lib/__tests__/unit/timeline.test.ts` (no existing tests on `timeline.ts`; verified via `ls`). |
108
-
| Visual / interactive | None. Repo has no RTL/Playwright harness; the chart is a copy of an existing chart with a different field. Manual smoke. | n/a |
107
+
| Unit — `prs` aggregation | Cases: rows with no `pr_number` → 0; duplicates → counted once; multiple distinct PRs; PR spanning two weeks → counted in each; mixed PR + direct-push rows. |`src/lib/__tests__/unit/timeline.test.ts`|
108
+
| Unit — `avgLinesPerPr` aggregation | Cases: zero PRs → 0; single-PR-multi-commit sum; avg across distinct PRs; direct-push lines excluded from numerator; integer rounding; **P95 outlier exclusion at N=20 boundary**; **degrades to no-filter at N<20**; **cross-week semantic lockdown** (per-week slice / per-week distinct count). | same file |
109
+
| Visual / interactive | None. Repo has no RTL/Playwright harness. Manual smoke. | n/a |
109
110
110
111
## Edge cases
111
112
112
113
| Case | Behavior |
113
114
|---|---|
114
115
| Week with 0 commits and 0 PRs | Renders as empty bar (same as Commits/Week handles the no-commits case today). |
115
-
| Commit row has `pr_number = null` (direct push) | Contributes to commits count, contributes 0 to PRs count. Correctly reflects: "this work landed without a PR." |
116
-
| Many small PRs in one week | Bar is tall — same visual treatment as a high commit count. |
117
-
| PR with 50 commits across one week | Counted as 1 PR — distinct on pr_number. The volume is visible in the Commits/Week chart; this chart specifically tells the story of PR throughput, not commit volume per PR. |
116
+
| Commit row has `pr_number = null` (direct push) | Contributes to commits count, contributes 0 to PRs count, contributes 0 to `avgLinesPerPr` numerator. Correctly reflects: "this work landed without a PR." |
117
+
| Many small PRs in one week | PRs/Week bar is tall; Avg Lines/PR stays low. |
118
+
| PR with 50 commits across one week | Counted as 1 PR. Total of its lines / 1 = the avg. |
119
+
| Org-wide week has only in-flight commits (no shipped) | In-flight overlay creates a bucket with `prs: 0, avgLinesPerPr: 0` — both new charts render as zero, no NaN/undefined. |
120
+
| < 20 PRs in the lookback window |`avgLinesPerPr` P95 filter degenerates to no-filter (you can't meaningfully exclude top 5% of a tiny population). Chart shows raw average. |
118
121
119
122
## Files touched
120
123
121
-
-**Modify**`src/lib/report/timeline.ts` — `prs` field on `WeeklyBucket`, `prNumbers` set in the accumulator, `prs: w.prNumbers.size` in the final map.
122
-
-**Modify**`src/app/report/[id]/org/page.tsx` — `WeeklyData` interface gains `prs`; one new `<TimelineChart>` invocation after Commits/Week.
-**Modify**`src/lib/report/org.ts` — add `pr_number` to the `commit_analyses` SELECT; zero-default `prs`/`avgLinesPerPr` in the in-flight overlay bucket initializer.
126
+
-**Modify**`src/lib/report/dev.ts` — add `pr_number` to the `commit_analyses` SELECT.
127
+
-**Modify**`src/app/report/[id]/org/page.tsx` — `WeeklyData` interface gains both fields; two new `<TimelineChart>` invocations after Commits/Week.
123
128
-**Modify**`src/app/report/[id]/dev/[login]/page.tsx` — same two changes.
124
-
-**Modify or Create**`src/lib/__tests__/unit/timeline.test.ts` — unit tests for the new `prs` aggregation.
129
+
-**Create**`src/lib/__tests__/unit/timeline.test.ts` — unit tests for both aggregations.
0 commit comments