feat(ui): D.3 AnalysisStatusPanel → SignalChain (marquee transformation) - #67
Conversation
PR 3 of 16 in the UI consistency overhaul. Worst-drift fix: kills every raw zinc-* / amber-* / emerald-* / rounded-lg instance in SamplePlayback.tsx (was 13 occurrences, now 0). Stacked on top of PR #65 (D.1 primitives). Will be rebased onto main once PR #65 merges. Migration: - Outer <section> → <DeviceRack name="AUDITION SAMPLES" subtitle="· Phase 3 heuristic" status={rackStatusFor(...)}>. Rack status reflects panel state — error tone on failure, active tone while generating, success tone once a manifest is rendered. - Original <h3> id-based labelling replaced by aria-label on the DeviceRack; the title strip carries the visible name. - Regenerate <button> → <Button variant="link" size="sm"> in the title-strip action slot. - Generate <button> → <Button variant="primary" size="md" ledIndicator> in the body. - ManifestMeta pill spans → <Pill tone="neutral" leadingDot>. - SampleGroup <h4> → <SectionHeader size="sm" eyebrow="Group" title={CATEGORY_LABELS[category]}>. - SampleCard <li> rounded-md border → <Panel variant="surface" padding="md"> (wrapped in a <li> for list semantics). - confidenceClassFor() className helper → confidenceTone() returning a Pill tone (warning for LOW / low-confidence, neutral for MED, success for HIGH). - Code spans for cited Phase 1 field paths now use design-token colors (bg-bg-app, border-border, text-text-primary) instead of raw zinc-300/zinc-800. - MIDI download link uses text-accent + underline instead of zinc. No behavior changes — same callbacks, same conditional rendering, same content. Chain-of-custody fields (sample.cites.rationale, sample.cites.phase1Fields) are rendered identically; PURPOSE.md invariant preserved. Verified: lint clean, 605/605 unit tests passing, build clean. Bundle: AnalysisResults chunk grew from 256.79 KB to 311.86 KB (larger import surface from the ui/ barrel; tree-shaking will tighten this as more components migrate and the import is shared). https://claude.ai/code/session_01WNtYcWXwn4mVnnjxqT7uAe
PR #65 review flagged that when signalIn, railContent, and signalOut are all set together, both railContent and signalOut carried ml-auto. In a flex row only the first ml-auto sibling claims the available space, so signalOut collapsed against railContent instead of anchoring to the far right. Restructure the rail as three fixed slots: a left container for signalIn, a flex-1 center for railContent, and a right-justified container for signalOut. Each slot always renders; empty when its content is absent. Layout is now consistent across all combinations of the three slot props. PR #66 doesn't exercise the all-three-slots case (SamplePlayback only sets status, not the rail), but D.4 (AnalysisStatusPanel migration) will, so worth fixing now while the primitive has no production consumers. Verified: lint clean, 605/605 unit tests passing. https://claude.ai/code/session_01WNtYcWXwn4mVnnjxqT7uAe
PR 4 of 16 in the UI consistency overhaul. The visual hook reviewers will remember: the analysis pipeline literally renders as a horizontal Live 12 device chain. Stacked on PR #66 (D.2 SamplePlayback + DeviceRack rail fix). Branch already includes the rail fix needed for the all-3-slots layout this PR exercises. Migration: - Outer <div> → <DeviceRack name="ANALYSIS RUN" subtitle={'· ' + runId.slice(-8)} status={overallStatus}>. Status maps progress tone + isActive to idle/active/success/error. - Stop button → <Button variant="danger" size="sm" leadingIcon=Square> in the title-strip action slot. - The three stage tiles (measurement / pitchNoteTranslation / interpretation) → <SignalChain orientation="horizontal" animated>. The animated cables convey "data is flowing left to right" between active stages — the literal Live 12 device chain metaphor. - Stage statuses (running/queued/completed/failed/etc.) map onto the SignalChain primitive's smaller vocabulary (idle/queued/active/success/error) via toSignalStatus(). - Per-stage retry buttons rendered via Button variant="ghost" in the stage device's action slot. - Non-retryable error codes (e.g. GEMINI_NOT_CONFIGURED) surface as a truncated mono span in the action slot with the full message in the title attribute — Audit N1 sibling preserved. - Primary readout (data-testid="status-panel-primary-readout") wraps in <Panel variant="inset" padding="sm"> instead of the hand-rolled rounded-sm border bg-bg-card div. Test ID preserved verbatim. - Progress bar disappears as a standalone element — its information (elapsed time, estimate range, percent) folds into the DeviceRack's bottom signal-flow rail via railContent. Animated SignalChain cables + LED-pulse on the active stage + percent in the rail collectively carry the "still running" signal. Preserved verbatim: - AnalysisStatusPanelProps (no API change for App.tsx). - computeLiveProgress() pure function and its export — the only consumer (tests/services/analysisStatusProgress.test.ts) was driven exclusively by this export and continues to pass without change. - STAGE_LABELS, statusLabel, all stage-status mapping logic. - The Audit N1 retry-button gating (errorMarkedNonRetryable check). - The Audit Finding #6 primary-readout placement at the top of the body. Bundle: index chunk grew from 271 KB → 325 KB gz (97.5 KB compressed) because AnalysisStatusPanel now imports more from the ui/ barrel. AnalysisResults shrank slightly. Will tighten as more files share the import. Verified: lint clean, 605/605 unit tests passing (computeLiveProgress test suite unaffected), build clean. https://claude.ai/code/session_01WNtYcWXwn4mVnnjxqT7uAe
slittycode
left a comment
There was a problem hiding this comment.
Verdict: REQUEST CHANGES
Summary
Pure UI transformation: AnalysisStatusPanel is rewritten around the DeviceRack / SignalChain / Panel primitives from PR D.1. No Phase 1 data is mutated, no schema fields change, computeLiveProgress() and its export are preserved verbatim. 622/622 unit tests pass, TypeScript lint is clean. The only issue triggering a REQUEST_CHANGES is two new logic functions with no unit tests — per the project's non-negotiable testing rule.
Findings
Should fix
toSignalStatus() and rackStatusFromProgress() are new non-trivial functions that convert internal state to typed contract values (SignalStageStatus, rack status string). Neither has a unit test. The project rule is explicit: new logic without tests = REQUEST_CHANGES. Both are simple enough to cover in a dozen lines.
Note: the three functions deleted by this PR (statusDotClass, statusTextClass, progressFillClass) also had no tests, so the net coverage posture is unchanged — but new additions still need to be covered going forward.
Worth considering
blocked and ready both map to 'queued' in toSignalStatus(). Previously they fell through to the neutral-grey default. For blocked (waiting on measurement) this reads correctly. For ready (failed stage, awaiting user retry) it's slightly off — the user already sees a Retry button in the action slot, so the stage tile also reading queued could momentarily confuse. Not blocking; judgment call.
Test results
622 passed / 4 skipped / 0 failed. computeLiveProgress test suite (10 tests) unaffected.
Phase boundary check
Clean. Only AnalysisStatusPanel.tsx changed. No reads or writes to Phase 1 output objects, no re-derivation of measured values, no changes to Phase 2/3 files.
Generated by Claude Code
PR #67 review (REQUEST CHANGES) called out that toSignalStatus() and rackStatusFromProgress() were new logic without tests, and that 'ready' mapping to 'queued' was a judgment-call regression (the user already sees a Retry button in the action slot — the tile reading 'queued' implies the chain will auto-resume when it actually won't). Changes: - Export toSignalStatus, statusLabel, and rackStatusFromProgress from AnalysisStatusPanel.tsx so the test suite can import them. Add doc comments to each explaining the intent + the per-case mapping rationale. - Remap 'ready' from 'queued' to 'idle'. statusLabel('ready') still returns 'READY' so the user sees the correct label inside the tile; the LED + cable + box-shadow no longer fake imminent execution. - New test file tests/services/analysisStatusPanelHelpers.test.ts with 23 tests covering every AnalysisStageStatus value, the unknown fallback for both helpers, the dominance of failed/success tones in rackStatusFromProgress, the running+isActive interaction, and the ready-vs-queued separation explicitly. Test count: 605 → 628. Verified: lint clean, full unit suite 628/628 passing. https://claude.ai/code/session_01WNtYcWXwn4mVnnjxqT7uAe
PR 5 of 16 in the UI consistency overhaul. The Input Source panel becomes a <DeviceRack name="Input Source">; the analysis-option toggles become Radix Checkboxes; the Run Analysis CTA becomes a <Button variant="primary" ledIndicator>; the loaded-file card becomes a <Panel variant="surface">. Stacked on PR #67 (D.3 SignalChain). Branch will be rebased onto main once #66 → #67 → PR 5 merge in order. FileUpload.tsx: - Loaded file card: replaced the hand-rolled bg-bg-card border div with <Panel variant="surface" padding="md">. Accent stripe + file icon + name + ready-dot + size-warning preserved verbatim. - Format chips (MP3/WAV/FLAC/AIFF): replaced inline span chips with <Pill tone="neutral" variant="outline" size="xs">. Visual parity. - "Load Demo Track" <button>: replaced with <Button variant="secondary" size="md">. Behavior + text preserved verbatim for the smoke test selector (tests/smoke/responsive-layout.spec.ts asserts the text). - Remove File icon button: replaced with <Button variant="ghost" iconOnly size="sm">. - Dropzone container kept as raw div — its drag-event handlers and conditional background-tint state are denser than Panel currently supports, and shimming Panel to accept onDragOver/Leave/Drop + three-way tint logic just to wrap one site would add API surface for one consumer. App.tsx — Input Source panel: - Outer wrapper at :1018-1027: hand-rolled bg-bg-surface-dark header + bg-bg-card body → <DeviceRack name="Input Source" status={audioFile ? (isAnalyzing ? 'active' : 'success') : 'idle'}>. Preserved data-testid="input-panel". - Collapsed-summary buttons (Analyze new file + Adjust settings): swapped from inline <button> bg-bg-panel borders to <Button variant="secondary">. - "Editing analysis settings" Hide button: <Button variant="secondary" size="sm">. - STEM PITCH/NOTE TRANSLATION toggle: replaced <input type="checkbox"> with Radix <Checkbox> (via the ui/ wrapper). Outer card label kept for the click-anywhere-on-card UX; htmlFor binds the label to the checkbox id. Preserved aria-label="PITCH/NOTE TRANSLATION" so the smoke selectors continue to resolve. - AI INTERPRETATION toggle: same treatment. Preserved data-testid="phase2-status-inline" and aria-label="AI INTERPRETATION". - Run Analysis CTA: replaced the motion.button with <Button variant="primary" size="lg" ledIndicator leadingIcon={<Play>}>. The Button primitive already encodes the bg-bg-panel + border-accent/60 + glow hover + ledIndicator pulse that the inline motion.button was hand-rolling. Text "Run Analysis" preserved verbatim for tests/smoke/upload-phase1.spec.ts. - Removed the explicit `<X />` import from lucide-react remains used by other call sites in App.tsx; left intact. - Removed unused motion.button (motion is still used elsewhere in the file; the import stays). Pre-flight decisions honored: - Two native <select> at :984-998 (phase2-model-desktop) and :1191-1204 (phase2-model-mobile) stayed native — they were already restyled with appearance-none and don't need migration. - Radix Checkbox, not Switch, for the analysis options (selection metaphor, not on/off feature flag). - TooltipProvider not mounted yet — no Tooltip consumers in this PR. Preserved verbatim: - All data-testid attributes (input-panel, input-panel-collapsed, phase2-status-badge, phase2-status-inline). - All visible text strings: "Input Source", "Drop Audio Here", "Load Demo Track", "Run Analysis", "↺ Analyze new file", "Adjust settings", "Hide", "STEM PITCH/NOTE TRANSLATION", "AI INTERPRETATION", "Ready", "Estimated local analysis". - All ARIA labels (PITCH/NOTE TRANSLATION, AI INTERPRETATION, ANALYSIS MODE, Interpretation model). - Behavior: onCheckedChange wraps Radix's CheckedState ('true' | 'false' | 'indeterminate') with a strict `=== true` check before setting the boolean state, preserving the existing semantics. - Audit findings (N9 collapse, N9 re-expand banner, #11 no CPU meter, #6 readout placement) untouched. Verified: lint clean, 605/605 unit tests passing, build clean (index chunk 323 KB / 97 KB gz; comparable to PR 4 — primitive imports are now amortized across consumers). https://claude.ai/code/session_01WNtYcWXwn4mVnnjxqT7uAe
* feat(ui): D.4 migrate FileUpload + Input Source to ui/ primitives PR 5 of 16 in the UI consistency overhaul. The Input Source panel becomes a <DeviceRack name="Input Source">; the analysis-option toggles become Radix Checkboxes; the Run Analysis CTA becomes a <Button variant="primary" ledIndicator>; the loaded-file card becomes a <Panel variant="surface">. Stacked on PR #67 (D.3 SignalChain). Branch will be rebased onto main once #66 → #67 → PR 5 merge in order. FileUpload.tsx: - Loaded file card: replaced the hand-rolled bg-bg-card border div with <Panel variant="surface" padding="md">. Accent stripe + file icon + name + ready-dot + size-warning preserved verbatim. - Format chips (MP3/WAV/FLAC/AIFF): replaced inline span chips with <Pill tone="neutral" variant="outline" size="xs">. Visual parity. - "Load Demo Track" <button>: replaced with <Button variant="secondary" size="md">. Behavior + text preserved verbatim for the smoke test selector (tests/smoke/responsive-layout.spec.ts asserts the text). - Remove File icon button: replaced with <Button variant="ghost" iconOnly size="sm">. - Dropzone container kept as raw div — its drag-event handlers and conditional background-tint state are denser than Panel currently supports, and shimming Panel to accept onDragOver/Leave/Drop + three-way tint logic just to wrap one site would add API surface for one consumer. App.tsx — Input Source panel: - Outer wrapper at :1018-1027: hand-rolled bg-bg-surface-dark header + bg-bg-card body → <DeviceRack name="Input Source" status={audioFile ? (isAnalyzing ? 'active' : 'success') : 'idle'}>. Preserved data-testid="input-panel". - Collapsed-summary buttons (Analyze new file + Adjust settings): swapped from inline <button> bg-bg-panel borders to <Button variant="secondary">. - "Editing analysis settings" Hide button: <Button variant="secondary" size="sm">. - STEM PITCH/NOTE TRANSLATION toggle: replaced <input type="checkbox"> with Radix <Checkbox> (via the ui/ wrapper). Outer card label kept for the click-anywhere-on-card UX; htmlFor binds the label to the checkbox id. Preserved aria-label="PITCH/NOTE TRANSLATION" so the smoke selectors continue to resolve. - AI INTERPRETATION toggle: same treatment. Preserved data-testid="phase2-status-inline" and aria-label="AI INTERPRETATION". - Run Analysis CTA: replaced the motion.button with <Button variant="primary" size="lg" ledIndicator leadingIcon={<Play>}>. The Button primitive already encodes the bg-bg-panel + border-accent/60 + glow hover + ledIndicator pulse that the inline motion.button was hand-rolling. Text "Run Analysis" preserved verbatim for tests/smoke/upload-phase1.spec.ts. - Removed the explicit `<X />` import from lucide-react remains used by other call sites in App.tsx; left intact. - Removed unused motion.button (motion is still used elsewhere in the file; the import stays). Pre-flight decisions honored: - Two native <select> at :984-998 (phase2-model-desktop) and :1191-1204 (phase2-model-mobile) stayed native — they were already restyled with appearance-none and don't need migration. - Radix Checkbox, not Switch, for the analysis options (selection metaphor, not on/off feature flag). - TooltipProvider not mounted yet — no Tooltip consumers in this PR. Preserved verbatim: - All data-testid attributes (input-panel, input-panel-collapsed, phase2-status-badge, phase2-status-inline). - All visible text strings: "Input Source", "Drop Audio Here", "Load Demo Track", "Run Analysis", "↺ Analyze new file", "Adjust settings", "Hide", "STEM PITCH/NOTE TRANSLATION", "AI INTERPRETATION", "Ready", "Estimated local analysis". - All ARIA labels (PITCH/NOTE TRANSLATION, AI INTERPRETATION, ANALYSIS MODE, Interpretation model). - Behavior: onCheckedChange wraps Radix's CheckedState ('true' | 'false' | 'indeterminate') with a strict `=== true` check before setting the boolean state, preserving the existing semantics. - Audit findings (N9 collapse, N9 re-expand banner, #11 no CPU meter, #6 readout placement) untouched. Verified: lint clean, 605/605 unit tests passing, build clean (index chunk 323 KB / 97 KB gz; comparable to PR 4 — primitive imports are now amortized across consumers). https://claude.ai/code/session_01WNtYcWXwn4mVnnjxqT7uAe * fix(ui): drop unused Panel import from App.tsx PR #69 review flagged App.tsx:9 imports Panel but never uses it (Panel is only consumed in FileUpload.tsx). Drop it. This is also a low-cost iteration to get CI logs against a fresh commit — the Frontend job failed on the previous push but the auth-gated logs prevented diagnosis from this sandbox. Pushing this clean fix to re-trigger the smoke suite. https://claude.ai/code/session_01WNtYcWXwn4mVnnjxqT7uAe * fix(ui): revert App.tsx analysis-option toggles to native <input> PR #69's Frontend CI failed twice on smoke tests without accessible logs from this sandbox. Best hypothesis: the smoke spec at tests/smoke/upload-estimate-phase1.spec.ts:242-246 uses page.getByLabel("PITCH/NOTE TRANSLATION") plus .toBeChecked() and .uncheck(). Playwright's getByLabel documents itself for "input elements", and .uncheck() expects native checkboxes (or, in some versions, also role=checkbox). The Radix Checkbox renders as a <button role="checkbox"> internally; that's a less-consistently- supported target for these methods than a real <input>. Revert the two toggles in App.tsx (PITCH/NOTE TRANSLATION and AI INTERPRETATION) to native <input type="checkbox"> with the same appearance-none-style border-card UX. The Checkbox primitive in components/ui/ is unchanged and remains available for surfaces where smoke selectors aren't load-bearing. Inline comments explain the rationale at each call site so future migrations don't naively re-introduce Radix here. Local 628/628 unit tests still pass; lint clean. If smoke CI passes on this commit, the hypothesis is confirmed and we can write a real test against the Radix Checkbox primitive separately to decide whether it's worth keeping in the canonical toolkit. https://claude.ai/code/session_01WNtYcWXwn4mVnnjxqT7uAe * fix(ui): restore bg-bg-card on input-panel to satisfy theme-shell smoke PR #69's Frontend CI failed three times. tests/smoke/theme-shell.spec.ts:41 asserts the computed background-color of [data-testid="input-panel"] is exactly rgb(68, 68, 68) — that's --color-bg-card (#444444). The PR 5 migration removed `bg-bg-card` from that div because the DeviceRack wrapper was meant to own the surface chrome. But the DeviceRack's body is transparent by default (so the rack's gradient face shows through); the computed background becomes rgba(0,0,0,0) instead of #444444, failing the test. Add `bg-bg-card` back to the inner div explicitly. The DeviceRack still owns the title-strip gradient, border, and box-shadow; the body is now flat #444444 matching the previous palette contract — and also matching how Live 12 devices visually compose (gradient header, relatively flat body). Also restore the `p-4` padding inside the input-panel div — the DeviceRack body's --space-device-pad-* is smaller than the original p-4 the test scenarios were calibrated against. The other smoke selectors (getByLabel for the toggles, getByTitle on Remove File, getByRole on Run Analysis) were never the issue — they're all preserved through prop spreading on the new primitives. Verified: lint clean, 628/628 unit tests passing, build clean. https://claude.ai/code/session_01WNtYcWXwn4mVnnjxqT7uAe --------- Co-authored-by: Claude <noreply@anthropic.com>
PR 7 of 16 in the UI consistency overhaul. Mix & Master Chain groups (DRUM PROCESSING, BASS PROCESSING, HIGH-END DETAIL, MASTER BUS) now each render as a <DeviceRack> with the group emoji + name on the title strip. Branched off main (PRs #66/#67/#69/#71 squash-merged). Single-file PR — AnalysisResults.tsx. Migration: - Per-group <section> + <h3> heading → <DeviceRack name={emoji + group.name}>. The DeviceRack title strip displays the emoji and uppercase group name; the DOM text content is preserved exactly so analysisResultsUi.test.ts:441-450 (toContain('🥁 DRUM PROCESSING') etc.) continue to pass. - group.annotation <p> kept inside the rack body with data-text-role="meta", margin-bottom restored. - Cards grid div retains its `grid gap-4 grid-cols-1 sm:grid-cols-2` className verbatim — analysisResultsUi.test.ts:440 expects ≥2 occurrences of this exact string (Mix Chain + Patches). - mix-chain-applied-progress badge: hand-rolled span → <Pill tone="success" size="sm">. Preserved data-testid="mix-chain- applied-progress". The Pill emits the canonical `bg-success/20 text-success border-success/30` class string the test at :507 already asserts is present in the rendered HTML. - SourcesToggle <button> → <Button variant="link">. Used by both Mix Chain and other sections; small ergonomic upgrade. Deferred (out of D.5b scope): - Per-card <div> outer wrapper NOT migrated to <Panel variant= "surface">. The card carries rich state-dependent styling (bg-bg-card with hover transitions, conditional border-l-2 for applied state, overflow-hidden for collapsible) that would require either extensive className overrides on Panel or extending Panel with new variants. Per-card migration deferred to a focused follow-up if/when Panel needs the additional variants. - AppliedCheckbox NOT migrated to the Checkbox primitive. The existing implementation is already a <button role="checkbox"> with aria-checked + aria-label + data-testid + green-tinted applied state. Migrating to Radix Checkbox would change the styling palette (success-green → accent-orange) and require Checkbox primitive extensions (tone prop). Existing implementation has equivalent a11y semantics and passes the applied-checkbox smoke test. Preserved verbatim: - All data-testid attributes (mix-chain-applied-progress, applied-checkbox, mix-chain-citation-*, mix-chain-headline-*). - All visible text strings (group names + emojis, "applied", "Sources", PRO TIP, etc.). - The exact `grid gap-4 grid-cols-1 sm:grid-cols-2` className the brittle assertion locks. - All data-text-role attributes on h2/h3/h4/p elements (section- title, item-title, meta, body). - The characteristicPillClass function which produces the `bg-{tone}/20 text-{tone} border-{tone}/30` strings asserted at :507-509 — untouched. - CitationBlock + CitationHeadline internals — untouched. - AppliedCheckbox tracker + audioContentHash gating — untouched. Verified: lint clean, 628/628 unit tests passing (including analysisResultsUi.test.ts which directly asserts the preserved class strings + text + data-text-role attributes), build clean (AnalysisResults chunk 254 KB / 63 KB gz — slightly smaller than PR 6 due to removed hand-rolled span styling). https://claude.ai/code/session_01WNtYcWXwn4mVnnjxqT7uAe Co-authored-by: Claude <noreply@anthropic.com>
PR 14 of 16 in the UI consistency overhaul. Final cleanup pass. Removes three CSS utility classes from index.css: - .ableton-panel - .ableton-device - .ableton-header All three were retired by D.* migrations — every former consumer now uses the canonical primitives from components/ui/ (Panel, DeviceRack, SectionHeader). `grep -rn` against apps/ui/src/ confirms zero remaining usages. .ableton-shell and .ableton-toolbar STAY because App.tsx:952,956 still consumes them for the outer app chrome (the load-bearing section-grid shell). A focused follow-up could migrate those two to DeviceRack / a future AppShell primitive; out of scope here. Deferred (preserved as-is): - components/MeasurementPrimitives.tsx cannot be fully deleted yet — 5 consumers still depend on timeline/lane primitives (LaneContainer, LaneRow, StatsBar, TimeRuler) that the plan explicitly preserved. The shipped primitives (StatusBadge, DeltaBadge, MetricBar, MetricBarRow, OutlinePillButton, TokenBadgeList, StyledDataTable, AccentMetricCard) also still have consumers in MeasurementDashboard and AnalysisResults sections that weren't migrated (StructureLanes, HarmonyLanes, AnalysisResults remaining sections). Keep the file intact. - components/Tooltip.tsx stays as a re-export shim; the file isn't causing any drift and external imports may still target it. Verified: lint clean, 628/628 unit tests passing, build clean. D.* migrations summary (all merged or open at time of this PR): - D.0 Foundation (#64) ✓ - D.1 Primitives complete (#65) ✓ - D.2 SamplePlayback (#66) ✓ - D.3 SignalChain marquee (#67) ✓ - D.4 FileUpload + Input Source (#69) ✓ - D.5a Results header + metric strip (#71) ✓ - D.5b Mix Chain (#73) ✓ - D.5c Patches (#74) ✓ - D.5d Section headers (#75) ✓ - D.6a Dashboard structure (#76) ✓ - D.6b Dashboard sections (#77) ✓ - D.6c Dashboard headers (#78) ✓ - D.7 SessionMusicianPanel + MixDoctorPanel (#79) — open - D.8 Signal Monitor + SpectrogramViewer drift (#80) — open - D.9 DenseDawConcept drift (#81) — open - D.10 Cleanup (this PR) ✓ https://claude.ai/code/session_01WNtYcWXwn4mVnnjxqT7uAe
…82) PR 14 of 16 in the UI consistency overhaul. Final cleanup pass. Removes three CSS utility classes from index.css: - .ableton-panel - .ableton-device - .ableton-header All three were retired by D.* migrations — every former consumer now uses the canonical primitives from components/ui/ (Panel, DeviceRack, SectionHeader). `grep -rn` against apps/ui/src/ confirms zero remaining usages. .ableton-shell and .ableton-toolbar STAY because App.tsx:952,956 still consumes them for the outer app chrome (the load-bearing section-grid shell). A focused follow-up could migrate those two to DeviceRack / a future AppShell primitive; out of scope here. Deferred (preserved as-is): - components/MeasurementPrimitives.tsx cannot be fully deleted yet — 5 consumers still depend on timeline/lane primitives (LaneContainer, LaneRow, StatsBar, TimeRuler) that the plan explicitly preserved. The shipped primitives (StatusBadge, DeltaBadge, MetricBar, MetricBarRow, OutlinePillButton, TokenBadgeList, StyledDataTable, AccentMetricCard) also still have consumers in MeasurementDashboard and AnalysisResults sections that weren't migrated (StructureLanes, HarmonyLanes, AnalysisResults remaining sections). Keep the file intact. - components/Tooltip.tsx stays as a re-export shim; the file isn't causing any drift and external imports may still target it. Verified: lint clean, 628/628 unit tests passing, build clean. D.* migrations summary (all merged or open at time of this PR): - D.0 Foundation (#64) ✓ - D.1 Primitives complete (#65) ✓ - D.2 SamplePlayback (#66) ✓ - D.3 SignalChain marquee (#67) ✓ - D.4 FileUpload + Input Source (#69) ✓ - D.5a Results header + metric strip (#71) ✓ - D.5b Mix Chain (#73) ✓ - D.5c Patches (#74) ✓ - D.5d Section headers (#75) ✓ - D.6a Dashboard structure (#76) ✓ - D.6b Dashboard sections (#77) ✓ - D.6c Dashboard headers (#78) ✓ - D.7 SessionMusicianPanel + MixDoctorPanel (#79) — open - D.8 Signal Monitor + SpectrogramViewer drift (#80) — open - D.9 DenseDawConcept drift (#81) — open - D.10 Cleanup (this PR) ✓ https://claude.ai/code/session_01WNtYcWXwn4mVnnjxqT7uAe Co-authored-by: Claude <noreply@anthropic.com>
Summary
PR 4 of 16 in the UI consistency overhaul / Live 12 restyle stack. The visual hook reviewers will remember: the analysis pipeline literally renders as a horizontal Live 12 device chain. Animated cables convey "data is flowing left to right" between active stages.
Stacked on #66 (D.2 SamplePlayback + DeviceRack rail fix). Base will be retargeted to
mainonce #66 merges. PR 4's branch already includes the rail fix needed for the all-three-slots layout this PR exercises.Migration
<div className="rounded-sm border ... p-3 space-y-3">→<DeviceRack name="ANALYSIS RUN" subtitle={'· ' + runId.slice(-8)} status={overallStatus}>. Status maps progress tone +isActivetoidle/active/success/error.<Button variant="danger" size="sm" leadingIcon={<Square>}>in the title-stripactionslot.measurement / pitchNoteTranslation / interpretation) →<SignalChain orientation="horizontal" animated>. The animated cables convey "data is flowing left to right" between active stages — the literal Live 12 device-chain metaphor.running/queued/completed/failed/...) map onto the SignalChain primitive's smaller vocabulary (idle/queued/active/success/error) via a localtoSignalStatus()helper.<Button variant="ghost">in the stage device's action slot.GEMINI_NOT_CONFIGURED) surface as a truncated mono span in the action slot with the full message in the title attribute — Audit N1 sibling preserved verbatim.data-testid="status-panel-primary-readout") wraps in<Panel variant="inset" padding="sm">instead of the hand-rolledrounded-sm border bg-bg-carddiv. Test ID preserved verbatim.DeviceRack's bottom signal-flow rail viarailContent. Animated SignalChain cables + LED-pulse on the active stage + percent in the rail collectively carry the "still running" signal.Preserved verbatim
AnalysisStatusPanelProps— no API change forApp.tsx:1279-1288.computeLiveProgress()pure function and its export — the only consumer (tests/services/analysisStatusProgress.test.ts) was driven exclusively by this export and continues to pass without change.STAGE_LABELS,statusLabel, all stage-status mapping logic.errorMarkedNonRetryablecheck).Bundle
Index chunk grew from 271 KB → 325 KB gz (97.5 KB compressed) because
AnalysisStatusPanelnow imports more from theui/barrel.AnalysisResultschunk shrank slightly (256 → 255 KB gz). Will tighten as more files share the import.Test plan
npm run lint— cleannpm run test:unit— 605/605 passing (computeLiveProgresstest suite unaffected)npm run build— cleannpm run test:smoke— sandbox network blocks Playwright browser; should pass in CI sincedata-testid="status-panel-primary-readout"is preserved and stage-label text ("MEASURE", "PITCH/NOTE", "INTERPRET", "RUNNING", "DONE", "FAILED", etc.) is unchangedUp next (PR 5)
D.4 FileUpload + Input Source. The Input Source wrapper becomes a
<DeviceRack name="INPUT SOURCE">, analysis-option toggles become Radix<Checkbox>es styled as Live device on/off pads.https://claude.ai/code/session_01WNtYcWXwn4mVnnjxqT7uAe
Generated by Claude Code