(motir-core) Design — the roadmap ROOT level's non-epic rows: the grouped defects node, the level it drills into, and a cap that is visible rather than silent
Type · design · Repo motir-core · One PR.
Parent · MOTIR-3490 — the defect this unblocks. Why this card exists: motir run MOTIR-3490 reached run.md guard #3 and stopped. MOTIR-3490's acceptance criteria require two pieces of roadmap-canvas UI that design/roadmap/ does not depict — a grouped node on the ROOT level (its ACs 1, 2, 5) and a visible truncated state for the level cap (its AC 3) — and a run may not improvise UI.
What was checked before concluding the design is absent (the design-reference rule's own precondition): design/roadmap/ was listed — 19 .mock.html sheets, each with a .png, plus a 1 286-line design-notes.md. The notes were read and grepped; every .mock.html under design/roadmap/, design/backlog/ and design/triage/ was grepped for defect / truncat / parentless / unparented / +N more. Findings: the notes describe the root level as "the full root level (every epic)" (design-notes.md:507); the one + N more epics tile in the corpus (design-notes.md:200, grid-init.mock.html) belongs to the ONBOARDING init screen's plan-preview cluster, a different surface; triage.mock.html's "Unparented" is the triage inbox's promote-into-backlog popover. No sheet depicts a grouped root node, and none depicts a truncated level.
What to produce
A THREE-file design asset under design/roadmap/ — a new *.mock.html sheet built from the real design system, its same-basename .png export, and the design-notes.md section that carries the decisions. A NEW surface gets a NEW sheet; do not amend an existing one.
Design against SHIPPED REALITY — render it first. The roadmap canvas is implemented and running: screenshot the real /roadmap root level (or render the real ProjectRoadmapCanvas / WorkItemNode headlessly from their own source with the real globals.css) BEFORE drawing, and compose the sheet from the real shipped components rather than a stylised stand-in. The project's live tree already contains a parentless bug at the root, so the defect is reproducible on the running app.
The seven decisions the sheet must settle
Each is a choice the code card would otherwise make silently. Every one gets an explicit disposition in design-notes.md, in the numbered-decision style planning-origin-drill uses.
- WHICH rows group. MOTIR-3490 contradicts itself: its AC 1 says the root draws no
bugnode beside the epics, while its fix direction says collapse non-epicrows.story,taskandbugare all legal roots (prisma/sql/work_item_triggers.sql:182— onlysubtaskis refused). Decide whether the group is bugs-only or every non-epic root, and the node's NAME follows: a parentlesstaskinside a node labelled "Defects" is wrong. State the disposition for each of the four kinds. - The node's CARD FACE. The canvas already ships four distinct treatments —
WorkItemNode(container face, kind tile, meter, drill chevron),GhostAnchor,StationCard, and the wide plan-preview cluster. Pick one and say why; name the count copy and its format, and say which token carries its tile, since there is no--el-type-*hue for a node no kind backs. decorative, or a branch.ProjectRoadmapCanvascountsnodes.filter((n) => n.decorative !== true)to ask "does this level offer a CHOICE?" forautoDescendSingleParent(MOTIR-1807 / MOTIR-1824). The planning-origin card is decorative because it is provenance beside the road; a group node holding real work arguably is not. Decide it, and say what a one-epic project's root level does with the group node present.- The DRILLED level (its AC 2). The grouped defects are ALREADY in the root read, so the level can be served synthetically from the same fetched data the way
loadLevelinterceptsORIGIN_ID— or by a real fetch. Draw the level: its breadcrumb crumb label, whether each defect keeps the status chip / ready highlight / off-level-blocker treatment it has today, and what the level says when the group is empty. - The TRUNCATION affordance (its AC 3).
TREE_LEVEL_MAX_TAKE = 200withDEFAULT_SORTkey-ascending discards the HIGHEST keys — the newest epics — with no cursor and no affordance. Draw what the reader sees when a level is truncated: a+ N moretile on the canvas, a header count, a paginate control, or a raised cap.countProjectTreeLevelalready exists inworkItemRepository, so a total is available to draw against. Draw the affordance at the LEVEL, not only at the root, if it is to be general. - SPRINT scope (its AC 5). The sprint root level is re-rooted at the topmost in-sprint members (
findProjectTreeLevel'stopInSprintMembersSql), so a committed parentless defect IS a root there. Say whether the same group node appears in sprint scope, and what it shows when the group is the only root. - The ACCESS PATH. The group node is itself the door to the defects — so the sheet must DRAW the root canvas with the node in place AND the level behind it, not describe the route in prose.
Acceptance criteria
design/roadmap/<name>.mock.htmlexists and is built from the real design system —components/ui/*markup and--el-*element tokens only, no Tier-0--color-*and no rawrounded-md/p-2/h-9.- A same-basename
.pngexport sits beside it (Playwright chromium, light,deviceScaleFactor: 2, ~1200px — the conventiondesign-notes.md's asset table records for this area). design/roadmap/design-notes.mdgains a section for the new sheet: its row in the asset table, and one numbered disposition per decision 1–7 above, each stating what was decided and why. A decision left as "to be resolved by the code card" does not satisfy this.- The sheet draws BOTH states of the drill — the root level with the group node among the epics, and the level the group opens onto — so a reader sees the door and the room.
- The sheet draws the truncated state decided in 5, with the copy it carries.
- Every element the sheet composes from an ALREADY-SHIPPED component reproduces that component's real markup and classes (or embeds the shipped screen), rather than a redrawn stand-in — checked against a render of the running canvas, and the render is cited in the notes.
prettier --checkis clean over the changed files, and the diff touchesdesign/roadmap/**only.
Context refs
design/roadmap/design-notes.md— the asset table, the node vocabulary, and the numbered-decision style to follow;:507is the "full root level (every epic)" line this card revises.design/roadmap/planning-origin-drill.mock.html+ its notes section — the closest precedent: a SYNTHETIC root node that is a door, with an explicit decision per station and an explicitdecorativeruling.design/roadmap/roadmap.mock.html,auto-drill.mock.html,scope-toggle.mock.html— the shipped root level, the auto-descend cases, and the sprint-scope root.components/planning/WorkItemNode.tsx,ProjectRoadmapCanvas.tsx(:478the decorative count),workItemLevel.tsx(ORIGIN_ID,buildWorkItemLevel),WorkItemRoadmap.tsx(loadLevel'sORIGIN_IDintercept) — the shipped components the sheet composes from.lib/services/workItemsService.ts:828(TREE_LEVEL_MAX_TAKE) ·:3374(getProjectRoadmap) ·lib/issues/issueListView.ts:70(DEFAULT_SORT) — what the cap does and which rows it drops.lib/repositories/workItemRepository.ts—findProjectTreeLevel(no kind predicate at the root) andcountProjectTreeLevel(the total a truncation affordance can draw against).- MOTIR-3490 — the defect this unblocks; its ACs 1, 2, 3 and 5 are what this sheet must make buildable.