Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
180 changes: 10 additions & 170 deletions apps/ui/src/components/AnalysisResults.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,12 @@ import {
StemSummaryResult,
} from '../types';
import {
Activity,
AudioWaveform,
Check,
ChevronDown,
ChevronRight,
Clock,
Disc,
FileJson,
FileText,
Music,
Settings2,
Sliders,
} from 'lucide-react';
Expand All @@ -38,8 +34,7 @@ import { TranscriptionPianorollBlock } from './TranscriptionPianorollBlock';
import { Mt3TranscriptionPanel } from './Mt3TranscriptionPanel';
import { StemListeningNotesPanel } from './StemListeningNotesPanel';
import { hasStemListeningNotesContent } from '../services/sessionMusician';
import { Button, DeviceRack, MetricBar, MetricTile, Pill, SectionHeader, TokenBadgeList } from './ui';
import { PhaseSourceBadge } from './PhaseSourceBadge';
import { Button, DeviceRack, Pill, SectionHeader } from './ui';
import { StickyNav, type StickyNavSection } from './StickyNav';
import { CitationBlock, CitationHeadline } from './CitationBlock';
import { ConfidenceBandBadge } from './sessionMusician/ConfidenceBandBadge';
Expand All @@ -66,7 +61,8 @@ import {
getTextRoleClassName,
type TextRole,
} from '../utils/displayText';
import { MetaBadgeList, ResultsSectionHeader, textRoleClassName, type StyleProfileSectionState } from './analysisResults/shared';
import { lowConfidenceIndicator, MetaBadgeList, ResultsSectionHeader, textRoleClassName, type StyleProfileSectionState } from './analysisResults/shared';
import { MeasurementSummarySection } from './analysisResults/MeasurementSummarySection';
import { AudioObservationsSection } from './analysisResults/AudioObservationsSection';
import { ProjectSetupSection } from './analysisResults/ProjectSetupSection';
import { TrackLayoutSection } from './analysisResults/TrackLayoutSection';
Expand Down Expand Up @@ -349,21 +345,6 @@ function SourcesToggle({ sources, showSources, onToggle }: { sources?: string[];
// three-level Confidence Notes chips. Retired — chips now route through
// `ConfidenceBandBadge` with the canonical four-band ladder.

function shortenCharacteristicName(name: string): string {
return name.trim().split(/\s+/).slice(0, 2).join(' ');
}

function characteristicPillClass(confidence: string): string {
const normalized = String(confidence).trim().toUpperCase();
if (normalized === 'HIGH') {
return 'bg-success/20 text-success border-success/30';
}
if (normalized === 'MED' || normalized === 'MODERATE') {
return 'bg-warning/20 text-warning border-warning/30';
}
return 'bg-error/20 text-error border-error/30';
}

function groupIcon(groupName: string): React.ReactNode {
if (groupName.includes('DRUM PROCESSING')) return '🥁';
// Audit #13: 🫧 (bubbles) is not a bass signifier in any audio
Expand Down Expand Up @@ -391,21 +372,6 @@ function withAlpha(hexColor: string, alphaHex: string): string {
return `${hexColor}${alphaHex}`;
}

const LOW_CONFIDENCE_TITLE = "Low confidence — treat this as approximate.";

function lowConfidenceIndicator(show: boolean) {
if (!show) return null;
return (
<span
className="text-meta font-mono text-warning"
title={LOW_CONFIDENCE_TITLE}
aria-label="Low confidence"
>
</span>
);
}

interface InterpretationWarningMapping {
originalValue?: string;
coercedValue?: string;
Expand Down Expand Up @@ -609,14 +575,6 @@ function getChordStrength(phase1: Phase1Result): number | null {
return toFiniteNumber((chordDetail as Record<string, unknown>).chordStrength);
}

function isAssumedMeter(phase1: Phase1Result): boolean {
return phase1.timeSignatureSource === 'assumed_four_four' || (phase1.timeSignatureConfidence ?? 1) <= 0;
}

function meterStatusLabel(phase1: Phase1Result): string {
return isAssumedMeter(phase1) ? 'ASSUMED' : 'DETECTED';
}

// Audit Finding #4: `formatBpmScore` retired — the BPM card now renders
// the canonical band pill via ConfidenceBandBadge, same vocabulary as
// every other confidence surface.
Expand Down Expand Up @@ -911,131 +869,13 @@ export function AnalysisResults({

<StickyNav sections={navSections} />

<DeviceRack name="Measurement Summary" density="dense" status="success">
<div className="grid grid-cols-2 md:grid-cols-4 gap-3">
{/* TEMPO */}
<MetricTile
size="lg"
accent="accent"
icon={<Activity className="w-3.5 h-3.5 text-accent/60" />}
label="TEMPO"
value={finalBpm}
unit="BPM"
headerRight={<PhaseSourceBadge source="measured" />}
footer={
<div className="space-y-2">
{/* Audit Finding #4: `SCORE 0.86` badge retired in favor of the
canonical band pill — same vocabulary as Key, Character, and
every other confidence surface. */}
<ConfidenceBandBadge variant="compact" confidence={phase1.bpmConfidence} />
{phase1.bpmSource && (
<span className="block text-nano font-mono uppercase tracking-wide text-text-secondary/50">
{phase1.bpmSource.replace(/_/g, ' ')}
</span>
)}
</div>
}
/>

{/* KEY SIG */}
<MetricTile
size="lg"
accent="accent"
icon={<Music className="w-3.5 h-3.5 text-accent/60" />}
label="KEY SIG"
value={<span className="truncate block">{finalKey}</span>}
headerRight={
<div className="flex items-center gap-1">
<PhaseSourceBadge source="measured" />
{lowConfidenceIndicator(keyIsApproximate)}
</div>
}
footer={
<div className="space-y-1.5">
<MetricBar
value={phase1.keyConfidence}
color="var(--color-accent)"
glow
/>
{/* Audit Finding #4: `CONF 62%` text replaced with the canonical
band pill so every confidence reads in the same vocabulary. */}
<ConfidenceBandBadge variant="compact" confidence={phase1.keyConfidence} />
</div>
}
/>

{/* METER */}
<MetricTile
size="lg"
accent="accent"
icon={<Clock className="w-3.5 h-3.5 text-accent/60" />}
label="METER"
value={phase1.timeSignature}
footer={<Pill tone="neutral" size="xs">{meterStatusLabel(phase1)}</Pill>}
/>

{/* CHARACTER — genre primary, characteristic pills secondary */}
{phase1.genreDetail ? (
<MetricTile
size="lg"
accent="accent"
icon={<Disc className="w-3.5 h-3.5 text-accent/60" />}
label="CHARACTER"
value={<span className="truncate block capitalize">{phase1.genreDetail.genre}</span>}
headerRight={<PhaseSourceBadge source="measured" />}
footer={
<div className="space-y-2">
<TokenBadgeList
items={[
{ label: phase1.genreDetail.genreFamily, tone: 'accent' },
...(phase1.genreDetail.secondaryGenre
? [{ label: phase1.genreDetail.secondaryGenre, tone: 'neutral' as const }]
: []),
]}
/>
<MetricBar
value={phase1.genreDetail.confidence}
color="var(--color-accent)"
glow
/>
{/* Audit Finding #4: `CONF X%` replaced with the canonical
band pill — same vocabulary across every confidence. */}
<ConfidenceBandBadge
variant="compact"
confidence={phase1.genreDetail.confidence}
/>
</div>
}
/>
) : (
<MetricTile
size="lg"
accent="accent"
icon={<Disc className="w-3.5 h-3.5 text-accent/60" />}
label="CHARACTER"
value={
<span className="text-base font-mono uppercase tracking-wide text-text-secondary/60">
SCANNING...
</span>
}
footer={
characteristicPills.length > 0 ? (
<div className="w-full flex flex-wrap gap-1">
{characteristicPills.map((item, idx) => (
<span
key={`${item.name}-${idx}`}
className={`inline-flex items-center px-2 py-1 rounded-sm border text-micro font-mono uppercase tracking-wide ${characteristicPillClass(item.confidence)}`}
>
{shortenCharacteristicName(item.name)}
</span>
))}
</div>
) : undefined
}
/>
)}
</div>
</DeviceRack>
<MeasurementSummarySection
phase1={phase1}
finalBpm={finalBpm}
finalKey={finalKey}
keyIsApproximate={keyIsApproximate}
characteristicPills={characteristicPills}
/>

{/* Audit Finding #1: MeasurementDashboard was here at the top of the
results scroll, ahead of Style / Sonic Elements / Mix Chain / Patches.
Expand Down
Loading
Loading