4.3.5 Roll-up displays — sprint committed-points (fills the Story-4.2 sprint-header seam) + epic/parent subtree roll-up badge (issue detail + list/tree)
Estimate: 26m · Depends on: 4.3.1, 4.3.3, 4.2.3
Render the two BOUNDED roll-ups 4.3.3 computes: the per-sprint committed-points figure that fills the Story-4.2 sprint-container header seam, and the epic/parent subtree roll-up badge on the issue detail + list/tree. Drawn per design/estimation/estimation.mock.html; binds to 4.3.3 rollupForSprint / rollupForParent. Display-only — the aggregation is 4.3.3.
Sprint committed-points (fills the 4.2 seam). The Story-4.2 backlog sprint container reserved a committed-points slot (design/backlog/design-notes.md, "filled by Story 4.3"). Bind it to rollupForSprint(sprintId): render the committed points (and the labelled seam for completed / remaining per the design) in the sprint header, in the reserved slot (no relayout). An unestimated sprint shows —, never NaN (the DTO returns 0s; the UI owns the "—"). The figure comes from the bounded aggregate, NOT a sum over the loaded backlog page (finding #57). NOTE: the SCRUM board header (Story 4.5) draws its own fuller points summary from the same rollupForSprint via 4.5.2 — this subtask fills the BACKLOG sprint container's slot; it does not touch the scrum board.
Epic / parent roll-up badge. On an epic (and any parent with children), show the rolled-up subtree point total from rollupForParent(parentId) — e.g. Story Points · 34 on the issue-detail header/rail and a roll-up figure on the list/tree parent row, DISTINCT from the parent's OWN estimate (a roll-up of descendants, the way Jira rolls child points into an epic). Unestimated subtree → —. The read is the one bounded recursive-CTE aggregate (4.3.3), never a load-the-whole-subtree-and-sum.
Tokens + a11y. Figures read as TEXT (number + label — finding #35); colour via --el-*, shape via element shape tokens (CLAUDE.md); the roll-up regions carry aria-labels naming the committed/completed/remaining or the rolled-up total; new copy gets estimation.* i18n keys in every shipped locale.
Out of scope here: the per-issue estimate badge/picker (4.3.4); the scrum board sprint header + columnPoints (Story 4.5); the velocity / burndown charts (Story 4.6 — this ships numeric remaining only, leaving the chart seam); the Estimation settings panel (4.3.6).
Acceptance criteria
- The backlog sprint container header renders the committed-points figure (and the labelled completed/remaining seam per the design) from 4.3.3
rollupForSprint, in the Story-4.2 reserved slot with no relayout; an unestimated sprint shows—(noNaN); the figure is the bounded aggregate, not a sum over the loaded page. - An epic (and any parent) shows a rolled-up subtree point total from 4.3.3
rollupForParenton the issue detail + list/tree parent row, distinct from its own estimate; an unestimated subtree shows—; the read is one bounded recursive aggregate. - Both displays reuse the configured statistic; colour via
--el-*, shape via element tokens, AA-safe; figures read as text witharia-labels (finding #35); new copy hasestimation.*i18n keys in every shipped locale. - Component tests assert the sprint committed-points render (estimated + unestimated
—) and the epic subtree roll-up render; they assert the figures come from the roll-up DTO, not a client sum of loaded rows.
Context refs
design/estimation/estimation.mock.html+design-notes.md(4.3.1) — the roll-up display spec;design/backlog/design-notes.md(the committed-points slot this fills)- Story 4.3.3 (
rollupForSprint/rollupForParent) — the bounded aggregates this renders; Story 4.5.2 (the scrum header reading the samerollupForSprint) — keep the backlog + scrum figures consistent - The backlog sprint container (Story 4.2.3) + the issue-detail header/rail (Story 2.4) + the list/tree (Story 2.5) — the surfaces this decorates
- finding #57 (bounded, not load-all-and-sum), #35 (read as text); the
prodect-i18n-threading-pattern;motir-core/CLAUDE.md