feat(analytics): burn-down chart per milestone (closes #41)#48
Merged
Conversation
Closes #41. Phase-7-deferred item — landed simpler than the issue proposed: no new schema, no new server endpoint, no ADR for a "Done"-column flag. The existing `last column = Done` heuristic (documented in analytics-view.tsx since Phase 7) is sufficient for v1, and all the data the chart needs is already on the client (cards via the board fetch, milestones via the #39 endpoint, activity events via the existing `/api/boards/[id]/activity` poll). ### What's in - `computeBurndown()` — pure helper that builds `BurnDownPoint[]` for a milestone. Scope held constant at the count of cards currently in the milestone (textbook burn-down assumption). Done = most recent `CARD_MOVED` event into a done column; cards currently in done with no recorded move fall back to their first activity timestamp or milestone start. - `BurnDownChart` — pure SVG line chart matching the rest of the analytics-view's style. Two lines (ideal dashed + actual solid), vertical "today" marker, scope/0 baseline labels. - Burn-Down section in `AnalyticsView`, placed after Throughput. Milestone selector top-right when ≥1 dated milestone exists. Empty states for "no milestones" and "no dated milestones". ### Wiring - `AnalyticsView` accepts `milestones: MilestoneView[]`. - `BoardClient` passes the `milestones` state through to the view. - `pickedMilestoneId` defaults to null and derives the effective selection during render (no `useEffect` setState — avoids the react-hooks/set-state-in-effect lint rule). ### Why not a server endpoint The issue suggested `GET /api/milestones/[id]/burndown`. We already ship enough data to the client for cycle / lead / CFD analytics; the burn-down is the same shape. Pushing the aggregation server-side would have meant either decrypting card content (impossible) or running an extra round-trip per milestone switch (slow). Same trade- off the rest of `analytics-view.tsx` makes — keep it in this view. ### Why no Done-column flag yet The existing convention (sort columns by position, last one wins) is good enough for v1 — boards seeded by us start with "Backlog / In progress / Done", and that's also how `doneColumnIds` in `computeStats` already works. A per-board "this column is Done" toggle remains a worthwhile follow-up but is independent of burn- down — every other analytics metric would benefit from it too. ### Test plan - [x] `pnpm typecheck` clean - [x] `pnpm lint` clean - [x] `pnpm test` — 107/107 - [ ] CI green - [ ] Manual: create milestone with start = today-3d, end = today+10d, assign 5 cards, mark 2 done. Open Analytics → see scope=5, actual line dips to 3 at today, ideal slopes from 5 to 0. Closes #41. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> Signed-off-by: Musiker15 <info@musiker15.de>
Musiker15
added a commit
that referenced
this pull request
May 29, 2026
Fills the missing *board* templates from §5.7 (only card templates existed). - src/lib/templates/board-templates.ts: a built-in set (Basic Kanban, Sprint, Bug tracker, OKR, Content pipeline, Hiring pipeline). Each is expressed as an ExportedBoardV1 (columns + optional labels, no cards) so it can be materialised through the existing importBoard() pipeline — E2EE under a fresh BoardKey, no new schema or server route. The "done" column gets isDone set for Analytics; the bug tracker ships severity labels. - workspace-client: a "From template" creator (template <select> + name + Create) next to the create/import forms; builds the template board and navigates to it. - Tests: tests/unit/board-templates.test.ts (every template builds a valid v1 export with exactly one done column; bug labels present). Docs: CLAUDE.md §5.7 + gap list flipped to ✅, CHANGELOG. Typecheck, ESLint and the suite (214 tests, +4) all pass. This completes Phase C. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Phase-7-deferred Burn-Down chart. Now that Milestones (#39 + #47) ship with start / end dates, we can plot scope-remaining vs. ideal pace per milestone.
Landed simpler than the issue proposed:
Column.isDoneflag was the issue's suggested ADR 0010. Not needed for v1: the existing "last column = Done" convention is already documented and used by every other metric inanalytics-view.tsx. Per-board Done flag remains a worthwhile follow-up that benefits all metrics, not just burn-down.GET /api/milestones/[id]/burndownwas suggested. Not needed: the client already has cards (withmilestoneId), the milestone list (with dates), and the activity log. Computing client-side keeps the path E2EE-clean and avoids an extra round-trip per milestone switch.What changed
computeBurndown()— pure helper, scope held constant at "cards currently in milestone" (textbook burn-down assumption). Done = lastCARD_MOVEDinto a done column; conservative fallback for cards currently in done with no move event.BurnDownChart— pure SVG line chart matching the existing analytics style. Ideal (dashed), actual (solid + accent color), today marker, scope/0 baseline labels.BoardClientpasses themilestonesstate through.Test plan
pnpm typecheckcleanpnpm lintcleanpnpm test— 107/107Follow-up (out of scope here)
Column.isDoneflag — flexibility for boards that have "Done → Archived" or "Released" columns past "Done". Benefits every analytics metric, not just burn-down.Closes #41.
🤖 Generated with Claude Code