diff --git a/src/components/Dashboard.tsx b/src/components/Dashboard.tsx
index 7106f58..420be52 100644
--- a/src/components/Dashboard.tsx
+++ b/src/components/Dashboard.tsx
@@ -52,7 +52,7 @@ export default function Dashboard({ session }: { session: Session }) {
}, [session.snapshots, turns, activeTurn]);
const hotFile =
- activeTurn === anomalyTurnIndex ? turn.changedFiles[0] : undefined;
+ activeTurn === anomalyTurnIndex && turn ? turn.changedFiles[0] : undefined;
const stop = useCallback(() => {
setPlaying(false);
@@ -195,7 +195,9 @@ export default function Dashboard({ session }: { session: Session }) {
t.id === autopsy.blamedTurnId) ?? null
+ : null;
+ const blameIndex = blameTurn ? blameTurn.index : null;
const selectedTower = selectedFile
? session.snapshots
.flatMap((snapshot) => snapshot.files)
.find((file) => file.path === selectedFile)
: null;
- const healed = rolledBack || activeTurn >= 5;
+ // live recordings heal only when the recording says so; the demo scrub keeps
+ // its activeTurn-driven narrative.
+ const isLive = session.agent?.startsWith("ghost-live") ?? false;
+ const healed = rolledBack || (!isLive && activeTurn >= 5) || !!autopsy?.healed;
+ if (!turn) {
+ return (
+
+ );
+ }
return (
-
-
- Blamed turn
-
- {healed ? "curve flat" : "+38 MB / sample"}
-
-
-
-
t4
-
-
src/store/invoices.ts
-
- {anomaly.kind} · {anomaly.severity} · turn 4
+ {anomaly && autopsy ? (
+
+
+ Blamed turn
+
+ {healed ? "curve flat" : `${anomaly.kind} over threshold`}
+
+
{blameIndex !== null ? `t${blameIndex}` : "t—"}
+
+
+ {blameTurn?.changedFiles?.length
+ ? blameTurn.changedFiles.join(", ")
+ : "files captured per checkpoint"}
+
+
+ {anomaly.kind} · {anomaly.severity}
+ {blameIndex !== null ? ` · turn ${blameIndex}` : ""}
+
+
+
+
+
+
+
-
-
-
+ ) : (
+
+
+
—
+
+ no anomaly detected
+
+ the recorded samples stayed inside every threshold so far
+
+
+
-
+ )}
{selectedFile && (