Add fleet evolution: genetic breeding, atlas gossip, BGP router, seeder/miner, genealogy, court gates, APK scout, personas, WSUS mimic, and P2 test coverage

This commit is contained in:
AetherForge
2026-06-07 05:00:22 -07:00
parent 7b2d41cda8
commit 82d74abfcf
38 changed files with 486 additions and 120 deletions

View File

@@ -2,7 +2,7 @@ import { useCallback, useEffect, useRef, useState } from 'react';
import { api } from '../api/client';
import { useModalAmbientDuck } from '../context/AmbientMusicContext';
import { useWebSocket } from '../hooks/useWebSocket';
import type { Agent, PathTraceHop } from '../types';
import type { Agent, PathTraceHop, SpreadRouteRecommendation } from '../types';
import { HelpTip } from '../components/HelpTip';
import './PathTracerPage.css';
@@ -13,6 +13,7 @@ interface TraceStatus {
ready: boolean;
error?: string;
hops: PathTraceHop[];
spread_routes?: SpreadRouteRecommendation[];
}
interface QRData {
@@ -111,6 +112,7 @@ export default function PathTracerPage() {
const [tracing, setTracing] = useState(false);
const [qr, setQR] = useState<QRData | null>(null);
const [showQR, setShowQR] = useState(false);
const [spreadRoutes, setSpreadRoutes] = useState<SpreadRouteRecommendation[]>([]);
const pollRef = useRef<ReturnType<typeof setInterval> | null>(null);
const [autoEndCountdown, setAutoEndCountdown] = useState<number | null>(null);
@@ -146,6 +148,7 @@ export default function PathTracerPage() {
setTracing(true);
setHops([]);
setQR(null);
setSpreadRoutes([]);
try {
const res = await api.startTrace(selected);
setSessionID(res.session_id);
@@ -165,6 +168,9 @@ export default function PathTracerPage() {
try {
const status: TraceStatus = await api.getTraceStatus(sid);
setHops(status.hops);
if (status.spread_routes?.length) {
setSpreadRoutes(status.spread_routes);
}
if (status.error) {
setError(status.error);
clearInterval(pollRef.current!);
@@ -205,6 +211,7 @@ export default function PathTracerPage() {
setTracing(false);
setQR(null);
setSelected([]);
setSpreadRoutes([]);
setError('');
}, [sessionID]);
@@ -418,6 +425,21 @@ export default function PathTracerPage() {
All hops ready tunnel is active.
</div>
)}
{spreadRoutes.length > 0 && (
<div className="pt-route-hints" style={{ marginTop: '0.75rem' }}>
<div className="pt-chain-title">Spread Routes</div>
<ul style={{ margin: '0.35rem 0 0', paddingLeft: '1rem', fontSize: '0.65rem', fontFamily: 'monospace', color: '#00ffaa99' }}>
{spreadRoutes.map((route) => (
<li key={`${route.target_subnet}-${route.seed_agent_id}`}>
{route.target_subnet} {route.seed_agent_name ?? route.seed_agent_id.slice(0, 8)}
{route.join_lane ? ` (${route.join_lane})` : ''}
{route.score ? ` · ${route.score.toFixed(2)}` : ''}
</li>
))}
</ul>
</div>
)}
</div>
</div>