One commit, no migration. CI green on 3f26aa9 (run 3507). Fixes what you reported after the last deploy — see #2541.
The bug
The board fetched limit=100. Project 2 has 166 tasks, so 66 never arrived, and the route's total was fetched and discarded so nothing said so. Sorted updated_at desc, the dropped ones were the least-recently-touched — mostly done tasks in completed milestones.
That's why the three symptoms looked unrelated: the progress bar is counted server-side over all tasks while the kanban rendered the truncated set. 12/12 expanded to two cards, and the 100%-done auto-collapse rule read as arbitrary because the number driving it disagreed with what you saw.
Introduced in 012eb1d (2026-03-02), the commit that wrote the view. Not a regression and no trade-off behind it — it was correct at twenty tasks and outgrown since.
Changes
Page until complete, guarding against a page that returns nothing while total still claims more.
Stop swallowing the load error — catch {} left an empty board indistinguishable from a project with no tasks. Styled unlike the empty state on purpose.
Clamp plan bodies to ~6.5rem with Show more. max-height, not line-clamp, since the content is rendered markdown with block children.
Auto-collapse decides once per milestone. It re-ran on every reload and loadMilestones fires after a status change — so expanding a finished milestone and ticking anything snapped it shut again.
Still outstanding
loadMilestones keeps a silent catch {}. If it fails, every milestone disappears and all 166 tasks fall into the unassigned group — the same failure, larger. Left out to keep this reviewable; noted on #2541.
One commit, no migration. CI green on `3f26aa9` (run 3507). Fixes what you reported after the last deploy — see #2541.
## The bug
The board fetched `limit=100`. Project 2 has **166 tasks**, so 66 never arrived, and the route's `total` was fetched and discarded so nothing said so. Sorted `updated_at desc`, the dropped ones were the least-recently-touched — mostly done tasks in completed milestones.
That's why the three symptoms looked unrelated: the progress bar is counted server-side over *all* tasks while the kanban rendered the truncated set. `12/12` expanded to two cards, and the 100%-done auto-collapse rule read as arbitrary because the number driving it disagreed with what you saw.
Introduced in `012eb1d` (2026-03-02), the commit that wrote the view. Not a regression and no trade-off behind it — it was correct at twenty tasks and outgrown since.
## Changes
- **Page until complete**, guarding against a page that returns nothing while `total` still claims more.
- **Stop swallowing the load error** — `catch {}` left an empty board indistinguishable from a project with no tasks. Styled unlike the empty state on purpose.
- **Clamp plan bodies** to ~6.5rem with Show more. `max-height`, not `line-clamp`, since the content is rendered markdown with block children.
- **Auto-collapse decides once per milestone.** It re-ran on every reload and `loadMilestones` fires after a status change — so expanding a finished milestone and ticking anything snapped it shut again.
## Still outstanding
`loadMilestones` keeps a silent `catch {}`. If it fails, every milestone disappears and all 166 tasks fall into the unassigned group — the same failure, larger. Left out to keep this reviewable; noted on #2541.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
https://claude.ai/code/session_01UaYUaouG9jjhATyuxCKrQs
The milestone progress bars and the cards beneath them came from different
places. The bar is counted SERVER-SIDE over every task; the kanban rendered
whatever a single `limit=100` returned. Project 2 has 166 tasks, so 66 never
arrived — and because the route sorts `updated_at desc`, the ones dropped were
the least recently touched, which is mostly done tasks in completed milestones.
So "v1.0 — 12/12" expanded to two cards, and the auto-collapse rule (100% done
starts collapsed) read as arbitrary because the number driving it disagreed
with what you saw when you opened it.
No benefit was being chased. The limit shipped the day the view was written
(012eb1d, March 2), when the project had a couple of dozen tasks. It became
wrong as the corpus grew, and nothing was watching: the route returns `total`
and the view discarded it. Correct when written, wrong later, silent in between
— the same shape as half the coherence survey.
Four changes:
- **Page until complete.** The board groups by milestone and shows per-milestone
progress, so it cannot be right on a partial set. Guards against a page that
returns nothing while `total` still claims more, rather than looping forever.
- **Stop swallowing the error.** `catch {}` left an empty board, which is
indistinguishable from a project with no tasks — the same hidden-with-no-
indicator failure one layer up. Styled apart from the empty state deliberately;
"no tasks" and "the tasks did not load" must not look alike.
- **Clamp long plan bodies** to ~6.5rem with a Show more. A milestone IS the
plan, so its body carries the whole design — several hundred words now — and
rendered in full one plan pushes every other milestone off screen. max-height
rather than line-clamp: the content is rendered markdown with block children,
which line-clamp handles unpredictably. Length judged on the source string; a
per-milestone scrollHeight measurement is a lot of machinery to decide whether
to show one button, and the proxy is only wrong near the threshold.
- **Auto-collapse decides ONCE per milestone.** It re-ran on every reload, and
`loadMilestones` runs after a task's status changes — so expanding a finished
milestone and ticking anything snapped it shut again with no visible cause.
That is the other half of why the collapse state looked mixed: it wasn't only
deciding at start, it was overriding the reader continuously.
Reported by the operator after the fd7097c deploy. Not caused by it — but
restoring `.milestone-header` in #2444 is what made the progress track render
again, so the mismatch had been invisible rather than absent.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
One commit, no migration. CI green on
3f26aa9(run 3507). Fixes what you reported after the last deploy — see #2541.The bug
The board fetched
limit=100. Project 2 has 166 tasks, so 66 never arrived, and the route'stotalwas fetched and discarded so nothing said so. Sortedupdated_at desc, the dropped ones were the least-recently-touched — mostly done tasks in completed milestones.That's why the three symptoms looked unrelated: the progress bar is counted server-side over all tasks while the kanban rendered the truncated set.
12/12expanded to two cards, and the 100%-done auto-collapse rule read as arbitrary because the number driving it disagreed with what you saw.Introduced in
012eb1d(2026-03-02), the commit that wrote the view. Not a regression and no trade-off behind it — it was correct at twenty tasks and outgrown since.Changes
totalstill claims more.catch {}left an empty board indistinguishable from a project with no tasks. Styled unlike the empty state on purpose.max-height, notline-clamp, since the content is rendered markdown with block children.loadMilestonesfires after a status change — so expanding a finished milestone and ticking anything snapped it shut again.Still outstanding
loadMilestoneskeeps a silentcatch {}. If it fails, every milestone disappears and all 166 tasks fall into the unassigned group — the same failure, larger. Left out to keep this reviewable; noted on #2541.🤖 Generated with Claude Code
https://claude.ai/code/session_01UaYUaouG9jjhATyuxCKrQs