diff --git a/frontend/src/pages/TechniqueDetailPage.tsx b/frontend/src/pages/TechniqueDetailPage.tsx index 83bd6d0..50d6b6c 100644 --- a/frontend/src/pages/TechniqueDetailPage.tsx +++ b/frontend/src/pages/TechniqueDetailPage.tsx @@ -373,11 +373,70 @@ export default function TechniqueDetailPage() { ) : templates.length > 0 ? (
- {templates.map((tpl) => ( + {templates.map((tpl) => { + // ── Derive test status for this technique ────────────── + const allTests = (technique as any).tests ?? []; + + // Any test currently in a non-terminal state + const ACTIVE_STATES: TestState[] = [ + "draft", "red_executing", "blue_evaluating", "in_review", + ]; + const activeTest = allTests.find( + (t: { state: TestState }) => ACTIVE_STATES.includes(t.state) + ) ?? null; + + // Most recent validated test + const latestValidated: { + id: string; + detection_result: TestResult | null; + updated_at: string | null; + created_at: string; + } | null = + [...allTests] + .filter((t: { state: TestState }) => t.state === "validated") + .sort((a: { updated_at: string | null; created_at: string }, b: { updated_at: string | null; created_at: string }) => + (b.updated_at || b.created_at).localeCompare(a.updated_at || a.created_at) + )[0] ?? null; + + // Coverage is stale if the sync job raised the review flag + // (only meaningful when we already have a validated test) + const isStale = technique.review_required && !!latestValidated; + + // ── Helpers ──────────────────────────────────────────── + const ACTIVE_LABEL: Partial> = { + draft: "Draft", + red_executing: "Executing", + blue_evaluating: "Evaluating", + in_review: "In Review", + }; + + const detResult = latestValidated?.detection_result; + const detBadgeStyle = + detResult === "detected" + ? "border-green-500/30 bg-green-500/10 text-green-400" + : detResult === "partially_detected" + ? "border-yellow-500/30 bg-yellow-500/10 text-yellow-400" + : detResult === "not_detected" + ? "border-red-500/30 bg-red-500/10 text-red-400" + : "border-gray-600/30 bg-gray-800/50 text-gray-400"; + + const detLabel = + detResult === "detected" ? "Detected" + : detResult === "partially_detected" ? "Partial" + : detResult === "not_detected" ? "Not detected" + : "Validated"; + + const needsReRun = + !activeTest && + latestValidated && + (detResult !== "detected" || isStale); + + return (
+ {/* Left: template info */}

{tpl.name}

@@ -396,15 +455,60 @@ export default function TechniqueDetailPage() { )}
- + + {/* Right: status + action */} +
+ {/* ── Status badge ── */} + {activeTest && ( + + + {ACTIVE_LABEL[activeTest.state as TestState] ?? activeTest.state.replace(/_/g, " ")} + + )} + + {!activeTest && latestValidated && ( +
+ + {detResult === "detected" + ? + : + } + {detLabel} + + {isStale && ( + + ⚠ Coverage may be stale + + )} +
+ )} + + {/* ── Action button ── */} + {activeTest ? ( + + ) : ( + + )} +
- ))} + ); + })}
) : (