feat: v0.8 Iteration C UI — mesh/temp slot display, N4 reach badge

Diagnostics follow the new topology: network summary shows mesh count against
the cap plus temp referral count (Preferred/Local/Wide tiles are gone), the
connections list labels slots mesh vs temp referral, and peers can show an N4
reach badge. Verified against the Rust DTOs (mesh_count/mesh_cap/temp_count/
n4_distinct, MeshSlot Display -> "mesh"/"temp") and the style.css classes.

Cargo.lock picks up the 0.8.0-alpha version bump.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LGiPD2cF75mnvneSCjdDC5
This commit is contained in:
Scott Reimers 2026-07-30 13:05:20 -04:00
parent 6e22e60c7b
commit fa02ace4cc
3 changed files with 16 additions and 16 deletions

View file

@ -1550,6 +1550,7 @@ async function loadPeers() {
else if (p.reach === 'n1') reachBadge = '<span class="reach-badge reach-n1">N1</span>';
else if (p.reach === 'n2') reachBadge = '<span class="reach-badge reach-n2">N2</span>';
else if (p.reach === 'n3') reachBadge = '<span class="reach-badge reach-n3">N3</span>';
else if (p.reach === 'n4') reachBadge = '<span class="reach-badge reach-n4">N4</span>';
let actions = '';
if (p.nodeId === myNodeId) {
@ -2078,11 +2079,11 @@ async function loadNetworkSummary() {
const s = await invoke('get_network_summary');
networkSummaryEl.innerHTML = `<div class="diag-grid">
<div class="diag-item"><span class="diag-value">${s.totalConnections}</span><span class="diag-label">Connections</span></div>
<div class="diag-item"><span class="diag-value">${s.preferredCount}</span><span class="diag-label">Preferred</span></div>
<div class="diag-item"><span class="diag-value">${s.localCount}</span><span class="diag-label">Mesh</span></div>
<div class="diag-item"><span class="diag-value">${s.wideCount}</span><span class="diag-label">Non-mesh N1</span></div>
<div class="diag-item"><span class="diag-value">${s.meshCount}/${s.meshCap}</span><span class="diag-label">Mesh</span></div>
<div class="diag-item"><span class="diag-value">${s.tempCount}</span><span class="diag-label">Temp referral</span></div>
<div class="diag-item"><span class="diag-value">${s.n2Distinct}</span><span class="diag-label">N2 Reach</span></div>
<div class="diag-item"><span class="diag-value">${s.n3Distinct}</span><span class="diag-label">N3 Reach</span></div>
<div class="diag-item"><span class="diag-value">${s.n4Distinct}</span><span class="diag-label">N4 Reach</span></div>
</div>`;
} catch (e) {
networkSummaryEl.innerHTML = `<p class="empty-hint">Could not load network summary</p>`;
@ -2099,10 +2100,9 @@ async function loadConnections() {
connectionsList.innerHTML = conns.map(c => {
const label = escapeHtml(peerLabel(c.nodeId, c.displayName));
const icon = generateIdenticon(c.nodeId, 18);
const slotClass = c.slotKind === 'Preferred' ? 'slot-preferred'
: c.slotKind === 'Wide' ? 'slot-wide' : 'slot-local';
const slotLabel = c.slotKind === 'Local' ? 'Mesh'
: c.slotKind === 'Wide' ? 'Non-mesh N1' : c.slotKind;
const slotClass = c.slotKind === 'temp' ? 'slot-temp' : 'slot-mesh';
const slotLabel = c.slotKind === 'mesh' ? 'Mesh'
: c.slotKind === 'temp' ? 'Temp referral' : c.slotKind;
const duration = c.connectedAt ? relativeTime(c.connectedAt) : '';
return `<div class="peer-card">
<div class="peer-card-row">${icon} ${label} <span class="slot-badge ${slotClass}">${slotLabel}</span></div>
@ -3680,7 +3680,7 @@ function openDiagnostics() {
</div>
<div style="display:flex;gap:0.5rem;margin-top:0.5rem;flex-wrap:wrap;justify-content:center">
<button id="rebalance-btn" class="btn btn-ghost btn-sm">Rebalance Now</button>
<button id="request-referrals-btn" class="btn btn-ghost btn-sm">Request Referrals</button>
<button id="request-referrals-btn" class="btn btn-ghost btn-sm">Find Peers (Convection)</button>
</div>
<div style="display:flex;gap:0.5rem;margin-top:0.5rem;flex-wrap:wrap;justify-content:center">
<button id="show-ourinfo-btn" class="btn btn-ghost btn-sm">Our Info</button>
@ -3816,11 +3816,11 @@ function openDiagnostics() {
try {
const r = await invoke('request_referrals');
btn.textContent = r;
setTimeout(() => { btn.textContent = 'Request Referrals'; btn.disabled = false; }, 3000);
setTimeout(() => { btn.textContent = 'Find Peers (Convection)'; btn.disabled = false; }, 3000);
loadAllDiagnostics();
} catch (e) {
btn.textContent = 'Failed';
setTimeout(() => { btn.textContent = 'Request Referrals'; btn.disabled = false; }, 3000);
setTimeout(() => { btn.textContent = 'Find Peers (Convection)'; btn.disabled = false; }, 3000);
}
});
loadAllDiagnostics();