2.4.2 Description / explanation render + read-only core-fields panel
Estimate: 14m · Depends on: 2.4.1
The page's content body. The description renders through MarkdownView (2.3.5) — the same single render module the editor preview uses, so the read view and the edit-time preview can never diverge. The explanation (explanationMd, the "why this matters" axis from Story 1.4) renders read-only beneath it with an "AI-drafted" badge when explanationSource == 'ai_draft' (the provenance enum 1.4 shipped); editing/regenerating the explanation is an Epic-7 concern and is NOT a control here. Empty description shows a muted "No description" placeholder rather than blank space.
Core-fields panel (the metadata sidebar): every read-only field on work_item — type, priority, assignee (avatar/name or "Unassigned"), reporter, due date, estimate (minutes → human duration), created / updated (the same deterministic en-US/UTC formatter the jobs dashboard adopted after the 1.6.5 hydration fix — issue timestamps are an audit surface, so render them deterministically). These are DISPLAY only; the two interactive fields (status, assignee) get their inline controls in 2.4.4. The "Edit" button (2.4.1) remains the path for every other field.
Acceptance criteria
- Description renders via
MarkdownView(GFM + sanitized + highlighted + underlined links); empty → muted placeholder. - Explanation renders read-only with an "AI-drafted" badge iff
explanationSource == 'ai_draft'; absent explanation hides the section entirely. - Core-fields panel shows type / priority / assignee / reporter / due date / estimate / created / updated, each with a stable label; timestamps use the deterministic
en-US/UTCformatter (no hydration mismatch). - Component test (happy-dom) over the fields panel: each field renders its value or the documented empty state; an
ai_draftexplanation shows the badge, auser_authoredone does not. - STRICT shell-a11y sweep on the detail route stays green with content populated.
Context refs
components/ui/MarkdownView.tsx+lib/markdown/render.tsx(2.3.5) — the ONE render pathlib/issues/issueTypes.ts(2.1.1) — type icon/label; the priority enum + labels from Story 1.4- The 1.6.5
formatDateTime(en-US/UTC, "UTC" suffix) — reuse, don't re-derive explanationSourceenum +explanationMdsemantics (Story 1.4 · AI-storage boundary note)