agent-ecosystem/src/renderer/components/report/sections/FrictionSection.tsx
Paul Holstein d54e36f6fa feat(report): add session report tab and all section components
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 16:53:01 -05:00

86 lines
3.2 KiB
TypeScript

import { MessageSquareWarning } from 'lucide-react';
import { ReportSection } from '../ReportSection';
import type { ReportFrictionSignals, ReportThrashingSignals } from '@renderer/types/sessionReport';
const frictionColor = (rate: number): string => {
if (rate <= 0.1) return '#4ade80';
if (rate <= 0.25) return '#fbbf24';
return '#f87171';
};
interface FrictionSectionProps {
data: ReportFrictionSignals;
thrashing: ReportThrashingSignals;
}
export const FrictionSection = ({ data, thrashing }: FrictionSectionProps) => {
return (
<ReportSection title="Friction Signals" icon={MessageSquareWarning}>
<div className="mb-4 flex items-center gap-3">
<span
className="rounded px-2 py-0.5 text-xs font-medium"
style={{
backgroundColor: `${frictionColor(data.frictionRate)}20`,
color: frictionColor(data.frictionRate),
}}
>
Friction Rate: {(data.frictionRate * 100).toFixed(1)}%
</span>
<span className="text-xs text-text-muted">
{data.correctionCount} correction{data.correctionCount !== 1 ? 's' : ''}
</span>
</div>
{data.corrections.length > 0 && (
<div className="mb-4">
<div className="mb-2 text-xs font-medium text-text-muted">Corrections</div>
<div className="flex flex-col gap-1">
{data.corrections.map((corr, idx) => (
<div key={idx} className="flex items-start gap-2 rounded px-2 py-1 text-xs">
<span
className="shrink-0 rounded px-1.5 py-0.5 font-mono text-[10px]"
style={{ backgroundColor: 'rgba(251, 191, 36, 0.15)', color: '#fbbf24' }}
>
{corr.keyword}
</span>
<span className="truncate text-text-secondary">{corr.preview}</span>
</div>
))}
</div>
</div>
)}
{(thrashing.bashNearDuplicates.length > 0 || thrashing.editReworkFiles.length > 0) && (
<div>
<div className="mb-2 text-xs font-medium text-text-muted">Thrashing Signals</div>
{thrashing.bashNearDuplicates.length > 0 && (
<div className="mb-2">
<div className="mb-1 text-xs text-text-muted">Repeated Bash Commands</div>
{thrashing.bashNearDuplicates.map((dup, idx) => (
<div key={idx} className="flex items-center gap-2 px-2 py-0.5 text-xs">
<span className="text-text-muted">{dup.count}x</span>
<code className="truncate text-text-secondary">{dup.prefix}</code>
</div>
))}
</div>
)}
{thrashing.editReworkFiles.length > 0 && (
<div>
<div className="mb-1 text-xs text-text-muted">Reworked Files (3+ edits)</div>
{thrashing.editReworkFiles.map((file, idx) => (
<div key={idx} className="flex items-center gap-2 px-2 py-0.5 text-xs">
<span className="text-text-muted">{file.editIndices.length}x</span>
<span className="truncate text-text-secondary">{file.filePath}</span>
</div>
))}
</div>
)}
</div>
)}
</ReportSection>
);
};