diff --git a/decnet_web/src/components/AttackerDetail.tsx b/decnet_web/src/components/AttackerDetail.tsx index d2f03a18..3d35a665 100644 --- a/decnet_web/src/components/AttackerDetail.tsx +++ b/decnet_web/src/components/AttackerDetail.tsx @@ -1,6 +1,6 @@ import React, { useEffect, useState } from 'react'; import { useParams, useNavigate } from 'react-router-dom'; -import { Activity, AlertTriangle, ArrowLeft, ChevronDown, ChevronLeft, ChevronRight, ChevronUp, Crosshair, Eye, Fingerprint, Globe, Shield, Clock, Wifi, Lock, FileKey, Radio, Timer, Paperclip, Terminal, Package, FileText, Mail, AtSign } from '../icons'; +import { Activity, AlertTriangle, ArrowLeft, ChevronDown, ChevronLeft, ChevronRight, ChevronUp, Cpu, Crosshair, Eye, Fingerprint, Globe, Keyboard, Shield, Clock, Sparkles, Wifi, Lock, FileKey, Radio, Timer, Paperclip, Terminal, Package, FileText, Mail, AtSign } from '../icons'; import api from '../utils/api'; import ArtifactDrawer from './ArtifactDrawer'; import MailDrawer from './MailDrawer'; @@ -912,6 +912,24 @@ const BEHAVIOUR_DOMAIN_ORDER: ReadonlyArray = [ 'environmental', 'emotional_valence', ]; +const BEHAVIOUR_DOMAIN_LABELS: Record = { + motor: 'MOTOR', + cognitive: 'COGNITIVE', + temporal: 'TEMPORAL', + operational: 'OPERATIONAL', + environmental: 'ENVIRONMENTAL', + emotional_valence: 'EMOTIONAL VALENCE', +}; + +const BEHAVIOUR_DOMAIN_ICONS: Record> = { + motor: Keyboard, + cognitive: Cpu, + temporal: Clock, + operational: Activity, + environmental: Globe, + emotional_valence: Sparkles, +}; + function _domainOf(primitive: string): string { return primitive.split('.', 1)[0]; } @@ -963,25 +981,81 @@ export const BehaviouralPrimitivesPanel: React.FC<{ ...Array.from(groups.keys()).filter((d) => !BEHAVIOUR_DOMAIN_ORDER.includes(d)).sort(), ]; return ( -
- {orderedDomains.map((domain) => ( -
-
{domain.toUpperCase()}
- {groups.get(domain)!.map((obs) => ( -
- {_leafOf(obs.primitive)} - {_renderValue(obs.value)} - - {(obs.confidence * 100).toFixed(0)}% +
+ {orderedDomains.map((domain) => { + const Icon = BEHAVIOUR_DOMAIN_ICONS[domain] ?? Activity; + const label = BEHAVIOUR_DOMAIN_LABELS[domain] ?? domain.toUpperCase(); + const rows = groups.get(domain)!; + return ( +
+
+ + + {label} + + + {rows.length} {rows.length === 1 ? 'PRIMITIVE' : 'PRIMITIVES'}
- ))} -
- ))} +
+ {rows.map((obs) => ( +
+ + {_leafOf(obs.primitive)} + + + {_renderValue(obs.value)} + + + {(obs.confidence * 100).toFixed(0)}% + +
+ ))} +
+
+ ); + })}
); }; @@ -1894,7 +1968,7 @@ const AttackerDetail: React.FC = () => { {/* Behavioural primitives (BEHAVE-SHELL) */}
toggle('behavioural')} >