Loading narrative...
;
+ if (error) return Not enough events to generate a narrative.
;
+ }
+
+ const currentPhase = detectPhase(narrative.segments);
+ const phaseProgress = getPhaseProgress(narrative.segments);
+
+ return (
+
+ {/* Phase badge + sentiment */}
+
+ {currentPhase && (
+
+ {currentPhase}
+
+ )}
+
+ {SENTIMENT_ICONS[narrative.sentiment]}
+
+
+ {formatDuration(narrative.durationMs)} · {narrative.stats.totalEvents} events
+
+
+
+ {/* Phase progress bar */}
+
+ {phaseProgress.map(({ phase, percent }) =>
+ percent > 0 ? (
+
+ ) : null,
+ )}
+
+
+ {/* Summary */}
+
{narrative.summary}
+
+ {/* Accomplishments & Challenges */}
+ {narrative.accomplishments.length > 0 && (
+
+
Accomplishments
+
+ {narrative.accomplishments.map((a, i) => - {a}
)}
+
+
+ )}
+ {narrative.challenges.length > 0 && (
+
+
Challenges
+
+ {narrative.challenges.map((c, i) => - {c}
)}
+
+
+ )}
+
+ {/* Segments */}
+
+
Activity Segments
+
+ {narrative.segments.map(seg => {
+ const isOpen = expandedSegment === seg.id;
+ const phase = PATTERN_TO_PHASE[seg.pattern] || 'Implementation';
+ return (
+
+
setExpandedSegment(isOpen ? null : seg.id)}
+ >
+
+ {phase.charAt(0)}
+
+ {seg.summary}
+ {formatDuration(seg.durationMs)}
+ {seg.isActive && }
+
+ {isOpen && (
+
+
+ {formatTime(seg.startTime)} — {formatTime(seg.endTime)}
+ {seg.eventCount} events
+
+ {seg.entities.files && seg.entities.files.length > 0 && (
+
+ Files:
+ {seg.entities.files.slice(0, 5).map((f, i) => (
+ {f.split('/').pop()}
+ ))}
+ {seg.entities.files.length > 5 && (
+ +{seg.entities.files.length - 5}
+ )}
+
+ )}
+ {seg.entities.tools && seg.entities.tools.length > 0 && (
+
+ Tools:
+ {seg.entities.tools.map((t, i) => (
+ {t}
+ ))}
+
+ )}
+
+ )}
+
+ );
+ })}
+
+
+
+ {/* Full narrative text */}
+ {narrative.fullNarrative && (
+
+
Narrative
+
{narrative.fullNarrative}
+
+ )}
+
+ );
+};
+
+export { WorkerNarrativeInline };
+
+// ── Standalone panel (toggled from header) ─────────────────
+
+interface SemanticNarrativePanelProps {
+ visible: boolean;
+ onClose: () => void;
+}
+
+const SemanticNarrativePanel: React.FC