Planning bug: a design entry cited an existing component as a surface's pending stand-in without measuring it — 9 tracks against 4, 40px rows against 48
Type: bug (planning) · Home: MOTIR-1465 · Found by: motir run MOTIR-3440 while building MOTIR-3444, 2026-08-26 · Defect authored by: MOTIR-3442, merged ~1 h earlier as motir-core#2288 · Correction: applied in MOTIR-3444's branch
What the asset said
design/work-items/design-notes.md § The streaming allocation at ARRIVAL — /items/archived and /items/[key]/edit gave /items/archived the verdict "NONE — reuse", on this reasoning:
"The late region is a table of work-item rows, and
app/(authed)/items/_components/IssueTreeSkeleton.tsxis the drawn pending state for exactly that, already composed by/itemsbehind its own<Suspense>./items/archivedis the same table one route over."
The last sentence is false, and it was never measured.
What the code says
IssueTreeSkeleton | ArchivedWorkItemsList | |
|---|---|---|
| tracks | 9, derived from buildIssueColumns | 4 or 5 — minmax(0,1fr) 130px 175px 140px [150px], the fifth only when canDelete |
| columns | Title · Type · Priority · Assignee · Reporter · Estimate · Points · Status · Actions | Title · Status · Archived by · Archived (· actions) |
| row height | 40 | 48 |
| right padding | pr-7 | pr-5 |
Composing it as the fallback lays out four fewer tracks and 8 px less per row across eight rows.
Why it matters more than an ordinary wrong citation
It reproduces the exact defect the cited component's own header comment documents. IssueTreeSkeleton carries a 20-line comment about MOTIR-3452: its grid template was two local constants "kept in sync by a comment saying they were, and they were not", so for eighty days the fallback laid out 272 px less fixed track than its table and the Title column took the difference back on settle — a visible horizontal jump on every load, sort, filter change and view switch. The fix was to DERIVE the template from the registry.
So the design entry proposed re-introducing that defect on a neighbouring route, by citing the very component whose lesson is that a stand-in must be derived from the table it stands in for.
And a wrong citation is worse than no citation: it compiles, it renders, and the next agent has no reason to check it. The design-asset address guard (tests/design-asset-addresses.test.ts) passes on it — the path resolves; it is the fit that does not.
Root cause
The entry's verdict was reached by reading the ROUTE (a list of work items, one segment below /items) rather than by reading the COMPONENT it names. Two tables can render the same entity and share no layout at all. A design asset that names an existing component as a stand-in is making a measurable claim about that component's box — tracks, heights, padding — and this one was asserted from the entity rather than measured from the markup.
Evidence
app/(authed)/items/_components/IssueTreeSkeleton.tsx:140 gridTemplate = [minmax(ISSUE_TITLE_MIN_TRACK,1fr), ...columns.slice(1)]
app/(authed)/items/_components/IssueTreeSkeleton.tsx:157 height: 40 (header)
app/(authed)/items/_components/IssueTreeSkeleton.tsx:177 height: 40 (rows)
app/(authed)/items/archived/_components/ArchivedWorkItemsList.tsx:159 gridTemplate = 'minmax(0,1fr) 130px 175px 140px 150px' | 'minmax(0,1fr) 130px 175px 140px'
app/(authed)/items/archived/_components/ArchivedWorkItemsList.tsx:172 height: 40 (header)
app/(authed)/items/archived/_components/ArchivedWorkItemsList.tsx:208 height: 48 (rows)
Measured on origin/main 052965b3.
The correction, already applied
MOTIR-3444's branch amends the design entry with the table above and states that the archived boundary is not this sweep's to add, naming the two open questions: which variant the frame draws (showActions is canDelete, which the frame cannot know before the read), and whether the generic frame — PageSkeleton, absent, see MOTIR-3520 — is the right ladder rung. The verdict, the tiers and the settle count are untouched: the falsified clause was the stand-in, not the allocation.
Acceptance criteria
- The amended entry is reviewed with MOTIR-3444's pull request, and the archived boundary is either given an owner or written off with a reason on the record.
- The general rule is recorded where a future design pass will meet it: an asset that names an existing component as a stand-in states the measurement that makes it fit — track count, row height, padding — or names no component. Citing by entity ("it is the same table") is what failed here.
- Whether the design-asset guard can be widened from the path resolves to the stand-in fits is answered — even a weak form (an asset naming component X as a fallback for surface Y must name a measurement) would have caught this.
Resolution
Open. The correction is in MOTIR-3444's branch; this card records the mistake and asks for the rule.