import { useEffect, useMemo, useRef, useState } from 'react'; import { Link } from 'react-router-dom'; import { api } from '../../api/client'; import { atlasSkipDisplayLabel, buildAccessDepthModel, parseAccessDepthServerPolicy, type AccessDepthDiagnostics, } from '../../help/accessDepth'; import { clearanceLabel, clearancePermissions, formatClearanceElevation, } from '../../help/clearance'; import { useWebSocket } from '../../hooks/useWebSocket'; import type { Agent, StrainCard, StrainHospiceRecord } from '../../types'; import { HelpTip } from '../HelpTip'; import JoinLaneBadge from './JoinLaneBadge'; import LotlTierBadge from './LotlTierBadge'; import './AccessDepthPanel.css'; import './LotlVisuals.css'; import './ReconVisuals.css'; interface Props { agent: Agent; diagnostics?: AccessDepthDiagnostics; } function OnionList({ rows, empty }: { rows: ReturnType['miningOnion']; empty: string }) { if (rows.length === 0) { return
{empty}
; } return (
    {rows.map((row) => (
  1. {row.index}. {row.label} {row.status === 'active' && active} {row.status === 'skipped' && skipped} {row.status === 'skipped_by_atlas' && ( atlas skip )} {row.status === 'done' && ok} {row.status === 'failed' && fail} {row.status === 'pending' && pending}
  2. ))}
); } function AttemptMiniList({ rows, empty, }: { rows: ReturnType['succeeded']; empty: string; }) { if (rows.length === 0) return
{empty}
; return ( ); } export default function AccessDepthPanel({ agent, diagnostics }: Props) { const { latestMessage } = useWebSocket(); const [policyLoaded, setPolicyLoaded] = useState(false); const [serverPolicy, setServerPolicy] = useState(parseAccessDepthServerPolicy({})); const [elevationFlash, setElevationFlash] = useState(null); const [strainCards, setStrainCards] = useState([]); const [hospiceStrains, setHospiceStrains] = useState>(new Set()); const [strainPlayBusy, setStrainPlayBusy] = useState(null); const flashTimerRef = useRef(null); const clearanceLevel = agent.clearance_level ?? 1; useEffect(() => { if (!latestMessage || latestMessage.type !== 'clearance_elevated') return; const p = latestMessage.payload as { agent_id?: string; to_level?: number; source?: string; reason?: string; }; if (p.agent_id !== agent.id || typeof p.to_level !== 'number') return; const text = formatClearanceElevation({ to_level: p.to_level, source: p.source, reason: p.reason, }); setElevationFlash(text); if (flashTimerRef.current != null) window.clearTimeout(flashTimerRef.current); flashTimerRef.current = window.setTimeout(() => setElevationFlash(null), 6000); }, [latestMessage, agent.id]); useEffect(() => { return () => { if (flashTimerRef.current != null) window.clearTimeout(flashTimerRef.current); }; }, []); useEffect(() => { let cancelled = false; api .getConfig() .then((cfg) => { if (!cancelled) { setServerPolicy(parseAccessDepthServerPolicy(cfg)); setPolicyLoaded(true); } }) .catch(() => { if (!cancelled) setPolicyLoaded(true); }); return () => { cancelled = true; }; }, []); useEffect(() => { let cancelled = false; api .listStrainCards(agent.id) .then((cards) => { if (!cancelled) setStrainCards(cards ?? []); }) .catch(() => { if (!cancelled) setStrainCards([]); }); return () => { cancelled = true; }; }, [agent.id]); useEffect(() => { let cancelled = false; api .listStrainHospice() .then((rows: StrainHospiceRecord[]) => { if (!cancelled) { setHospiceStrains(new Set(rows.map((r: StrainHospiceRecord) => r.strain_id.trim().toLowerCase()))); } }) .catch(() => { if (!cancelled) setHospiceStrains(new Set()); }); return () => { cancelled = true; }; }, []); useEffect(() => { if (!latestMessage) return; if (latestMessage.type === 'strain_card' || latestMessage.type === 'strain_card_played') { const p = latestMessage.payload as { card?: StrainCard; agent_id?: string }; if (p.card && (p.card.source_agent_id === agent.id || p.card.root_agent_id === agent.id || p.agent_id === agent.id)) { setStrainCards((prev) => { const next = prev.filter((c) => c.id !== p.card!.id); return [p.card!, ...next]; }); } } }, [latestMessage, agent.id]); const strainInHospice = (strain?: string) => { const id = strain?.trim().toLowerCase().replace(/^#/, '') ?? ''; return id !== '' && hospiceStrains.has(id); }; const playStrainCard = async (card: StrainCard) => { if (strainPlayBusy || strainInHospice(card.spread_strain)) return; setStrainPlayBusy(card.id); try { await api.playStrainCard({ agent_id: agent.id, card_id: card.id }); } finally { setStrainPlayBusy(null); } }; const model = useMemo( () => buildAccessDepthModel(agent, diagnostics, serverPolicy), [agent, diagnostics, serverPolicy], ); return (
ACCESS DEPTH {clearanceLabel(clearanceLevel)} {elevationFlash && ( {elevationFlash} )} {!policyLoaded && loading policy…} Oath
OS & posture
{model.osLine}
{model.probes.length > 0 && (
{model.probes.map((p) => ( {p.label} ))}
)} {model.spreadCaps.length > 0 && (
spread: {model.spreadCaps.join(', ')}
)} {model.privilegeHints.length > 0 && (
{model.privilegeHints.join(' · ')}
)}
Active
{model.activeTier ? ( ) : (
No active mining tier
)} {model.joinLane ? (
join lane
) : (
No join lane yet
)} {strainInHospice(agent.spread_strain) && (
strain in hospice — museum read-only lineage
)} {(agent.parent_agent_id || agent.spread_generation || agent.spread_strain) && (
lineage gen {agent.spread_generation ?? 0} {agent.spread_strain ? ( ) : null} {agent.parent_agent_id ? ( · parent {agent.parent_agent_id.slice(0, 8)} ) : null}
)} {strainCards.length > 0 && (
{strainCards.slice(0, 2).map((card) => (
{card.spread_strain ? ( ) : null} strain · {card.persona} {strainInHospice(card.spread_strain) ? ( hospice ) : null}
{card.wins.length}W · {card.losses.length}L · {card.subnets.length} subnets {card.erasure_recovery_rate > 0 ? ` · erasure ${Math.round(card.erasure_recovery_rate * 100)}%` : ''}
))}
)} {model.phenotypeSource && (
phenotype cloned from {model.phenotypeSource} {model.phenotypeSpreadLane ? ( <> {' '} · spread ) : null}
)} {serverPolicy.graft_enabled && (agent.graft_tier || agent.graft_source_strain) && (
genealogy graft pending · tier {agent.graft_tier} {agent.graft_source_strain ? ` · strain ${agent.graft_source_strain}` : ''} {' '}(applies on next spread)
)}
Succeeded
Failed / in progress
{model.inProgressLabel && (
trying {model.inProgressLabel}
)} {model.pendingLabels.length > 0 && (
pending: {model.pendingLabels.slice(0, 6).join(' → ')} {model.pendingLabels.length > 6 ? ` +${model.pendingLabels.length - 6}` : ''}
)}
{model.atlasSkips.length > 0 && (
Atlas skips
    {model.atlasSkips.map((skip) => (
  • {atlasSkipDisplayLabel(skip)}
  • ))}
)} {model.strategyReasoning.length > 0 && (
Strategy {model.adaptiveActive && ( Adaptive )}
    {model.strategyReasoning.map((row, i) => (
  • {row.fact} {row.inference} {row.action}
  • ))}
{typeof model.adaptiveConfidence === 'number' && (
confidence {Math.round(model.adaptiveConfidence * 100)}%
)}
)}
Effective onion order ({model.miningOrderSource}) {model.adaptiveActive && ( AI path )}
Mining tiers
Spread contingency{' '} Calibrate
{model.tripleOnionSummary && (
Triple onion: {model.tripleOnionSummary}
)}

{' '} Calibrate → lotl_onion_tiers changes spread order on next agent reconnect.

); }