style(web): fix prettier config, format entire web/ tree
Some checks failed
ci / build-test (push) Has been cancelled
ci / docker-build (push) Has been cancelled
ci / web (push) Has been cancelled
Desktop App / Build Linux (amd64) (push) Has been cancelled
Desktop App / Attach to Release (push) Has been cancelled

.prettierrc.json was missing "semi": false, so prettier wanted to add
semicolons to a codebase written without them (763 semicolon-free
statements vs. 150 with, in hand-written .ts; zero hand-written .svelte
files use them at all). That's why prettier --check failed on 249 files
— not because the code was unformatted, but because the config didn't
match the actual house style. Added "semi": false; left printWidth/etc
as configured (printWidth barely moves the failure count: 218/213/212
files at 100/120/140).

Ran `prettier --write .` with the corrected config. Verified
semantics-preserving before and after:
- eslint: 142 problems both before and after, byte-identical
- build passes, 38/38 tests pass
- token-stream diff (whitespace/semicolons/quotes normalized) on all
  218 changed files: only 52 had any remaining token change, all either
  trailing-comma removal (matching trailingComma: "none") or import/
  ternary reflow — no semantic changes
- live smoke test: Knowledge, Tasks, Fleet map, and a chat window
  (AgentTrace, markdown, Scope graph, activity rail) all render
  correctly, no console errors

Most of the diff is shadcn/ui vendor files (lib/components/ui/) moving
from the CLI's own style (double quotes, tabs, semicolons) to house
style; re-running `shadcn-svelte add` on a component will need a
follow-up format pass.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-07-27 12:56:07 +02:00
parent b345783eef
commit 873b00ac42
217 changed files with 4945 additions and 3538 deletions

View File

@@ -60,7 +60,11 @@
$effect(() => {
const ev = $liveEvents[0]
if (!ev) return
if (ev.type.startsWith('entity.') || ev.type.startsWith('relationship.') || ev.type === 'health.changed') {
if (
ev.type.startsWith('entity.') ||
ev.type.startsWith('relationship.') ||
ev.type === 'health.changed'
) {
load()
}
})
@@ -276,9 +280,11 @@
const svcRaw = new Map<string, number>()
for (const s of services) {
const p = serviceProvider.get(s.slug)
svcRaw.set(s.slug, (p && yById.has(p) ? yById.get(p)! : TOP0))
svcRaw.set(s.slug, p && yById.has(p) ? yById.get(p)! : TOP0)
}
services.sort((a, b) => (svcRaw.get(a.slug)! - svcRaw.get(b.slug)!) || a.name.localeCompare(b.name))
services.sort(
(a, b) => svcRaw.get(a.slug)! - svcRaw.get(b.slug)! || a.name.localeCompare(b.name)
)
let prevY = TOP0 - ROW_H
for (const s of services) {
const y = Math.max(svcRaw.get(s.slug)!, prevY + ROW_H)
@@ -308,7 +314,9 @@
counts[h]++
const ingress = routesTo.get(n.slug)
const ingressEntity = ingress ? bySlugEntity.get(ingress) : undefined
const publicHost = ingress ? (ingressEntity?.name ?? ingress.replace(/^ingress:/, '')) : undefined
const publicHost = ingress
? (ingressEntity?.name ?? ingress.replace(/^ingress:/, ''))
: undefined
const fauth = ingressEntity ? boolAttr(ingressEntity, 'forward_auth') : undefined
const provider = kind === 'service' ? serviceProvider.get(n.slug) : containerHost.get(n.slug)
const mnt = (kind === 'container' ? mountsOf.get(n.slug) : mountsOf.get(provider ?? '')) ?? []
@@ -361,25 +369,41 @@
const n = bySlug.get(slug)!
return LANE_X[n.lane] + (side === 'r' ? LANE_W[n.lane] : 0)
}
const cy = (slug: string) => (bySlug.get(slug)!.y) + NODE_H / 2
const cy = (slug: string) => bySlug.get(slug)!.y + NODE_H / 2
const edges: LaidEdge[] = []
const provChildren = new Map<string, string[]>() // provider -> [child]
// provision edges: host->container, provider->service
for (const c of containers) {
const host = containerHost.get(c.slug)
if (host && bySlug.has(host)) {
const x1 = cx(host, 'r'), y1 = cy(host), x2 = cx(c.slug, 'l'), y2 = cy(c.slug)
const x1 = cx(host, 'r'),
y1 = cy(host),
x2 = cx(c.slug, 'l'),
y2 = cy(c.slug)
const mx = (x1 + x2) / 2
edges.push({ d: `M${x1},${y1} C${mx},${y1} ${mx},${y2} ${x2},${y2}`, kind: 'prov', s: host, t: c.slug })
edges.push({
d: `M${x1},${y1} C${mx},${y1} ${mx},${y2} ${x2},${y2}`,
kind: 'prov',
s: host,
t: c.slug
})
pushMap(provChildren, host, c.slug)
}
}
for (const s of services) {
const p = serviceProvider.get(s.slug)
if (p && bySlug.has(p)) {
const x1 = cx(p, 'r'), y1 = cy(p), x2 = cx(s.slug, 'l'), y2 = cy(s.slug)
const x1 = cx(p, 'r'),
y1 = cy(p),
x2 = cx(s.slug, 'l'),
y2 = cy(s.slug)
const mx = (x1 + x2) / 2
edges.push({ d: `M${x1},${y1} C${mx},${y1} ${mx},${y2} ${x2},${y2}`, kind: 'prov', s: p, t: s.slug })
edges.push({
d: `M${x1},${y1} C${mx},${y1} ${mx},${y2} ${x2},${y2}`,
kind: 'prov',
s: p,
t: s.slug
})
pushMap(provChildren, p, s.slug)
}
}
@@ -388,9 +412,17 @@
if (!bySlug.has(srcSlug)) continue
for (const t of targets) {
if (!bySlug.has(t)) continue
const x1 = cx(srcSlug, 'r'), y1 = cy(srcSlug), x2 = cx(t, 'r'), y2 = cy(t)
const x1 = cx(srcSlug, 'r'),
y1 = cy(srcSlug),
x2 = cx(t, 'r'),
y2 = cy(t)
const bulge = Math.max(x1, x2) + 34 + Math.min(70, Math.abs(y1 - y2) * 0.32)
edges.push({ d: `M${x1},${y1} C${bulge},${y1} ${bulge},${y2} ${x2},${y2}`, kind: 'dep', s: srcSlug, t })
edges.push({
d: `M${x1},${y1} C${bulge},${y1} ${bulge},${y2} ${x2},${y2}`,
kind: 'dep',
s: srcSlug,
t
})
}
}
@@ -508,7 +540,8 @@
const q = search.trim().toLowerCase()
if (q) {
const s = new Set<string>()
for (const n of m.nodes) if (n.slug.toLowerCase().includes(q) || n.name.toLowerCase().includes(q)) s.add(n.slug)
for (const n of m.nodes)
if (n.slug.toLowerCase().includes(q) || n.name.toLowerCase().includes(q)) s.add(n.slug)
return s
}
return null
@@ -589,7 +622,9 @@
if (!m || !healthFilter) return [] as LaidNode[]
return m.nodes.filter((n) => n.health === healthFilter)
})
const problemCount = $derived(model ? model.nodes.filter((n) => n.health !== 'healthy').length : 0)
const problemCount = $derived(
model ? model.nodes.filter((n) => n.health !== 'healthy').length : 0
)
</script>
{#if loading && !model}
@@ -636,7 +671,8 @@
<div class="stage relative min-w-0 flex-1 overflow-auto">
<div class="relative" style="width:{model.width}px;height:{model.height}px">
<!-- background click target: clears selection -->
<button type="button" class="reset-layer" aria-label="Clear selection" onclick={reset}></button>
<button type="button" class="reset-layer" aria-label="Clear selection" onclick={reset}
></button>
<!-- lane headers -->
<div class="pointer-events-none absolute inset-x-0 top-0 z-10">
{#each [['Hosts', model.nodes.filter((n) => n.kind === 'host').length], ['Containers', model.nodes.filter((n) => n.kind === 'container').length], ['Services', model.nodes.filter((n) => n.kind === 'service').length]] as [label, count], i}
@@ -647,7 +683,11 @@
</div>
<!-- edges -->
<svg class="pointer-events-none absolute inset-0" width={model.width} height={model.height}>
<svg
class="pointer-events-none absolute inset-0"
width={model.width}
height={model.height}
>
{#each model.edges as e}
<path d={e.d} class="edge {e.kind} {edgeState(e)}" />
{/each}
@@ -661,7 +701,9 @@
class:svc={n.kind === 'service'}
class:is-open={selectedSlug === n.slug}
class:pulse={n.health === 'down'}
style="left:{n.x}px;top:{n.y}px;width:{n.w}px;height:{n.h}px;--nc:{HEALTH_COLOR[n.health]}"
style="left:{n.x}px;top:{n.y}px;width:{n.w}px;height:{n.h}px;--nc:{HEALTH_COLOR[
n.health
]}"
onmouseenter={() => setFocus(n.slug)}
onmouseleave={scheduleClear}
onfocus={() => setFocus(n.slug)}
@@ -673,7 +715,11 @@
title={n.slug}
>
{#if n.publicHost}
<span class="badge" title={n.publicHost + (n.fauth ? ' · forward-auth' : n.fauth === false ? ' · no auth gate' : '')}>
<span
class="badge"
title={n.publicHost +
(n.fauth ? ' · forward-auth' : n.fauth === false ? ' · no auth gate' : '')}
>
{#if n.fauth}
<LockIcon class="size-3" />
{:else if n.fauth === false}
@@ -748,7 +794,9 @@
<div class="blast">
<div class="n" class:warn={detailBlast.length > 0}>{detailBlast.length}</div>
<div class="lbl">
{detailNode.kind === 'service' ? 'downstream service' : 'service'}{detailBlast.length === 1 ? '' : 's'}
{detailNode.kind === 'service'
? 'downstream service'
: 'service'}{detailBlast.length === 1 ? '' : 's'}
affected if this goes down
</div>
</div>
@@ -756,18 +804,40 @@
<div class="det-sec">
<h4>Attributes</h4>
{#if detailNode.kind === 'container'}
<div class="row"><span class="k">type</span><span class="v">{detailNode.type}</span></div>
<div class="row">
<span class="k">type</span><span class="v">{detailNode.type}</span>
</div>
{/if}
{#if detailNode.role}<div class="row"><span class="k">role</span><span class="v">{detailNode.role}</span></div>{/if}
{#if detailNode.ip}<div class="row"><span class="k">ip</span><span class="v">{detailNode.ip}</span></div>{/if}
{#if detailNode.role}<div class="row">
<span class="k">role</span><span class="v">{detailNode.role}</span>
</div>{/if}
{#if detailNode.ip}<div class="row">
<span class="k">ip</span><span class="v">{detailNode.ip}</span>
</div>{/if}
{#if detailNode.publicHost}
<div class="row"><span class="k">url</span><span class="v">{detailNode.publicHost}</span></div>
<div class="row"><span class="k">exposure</span><span class="v">{detailNode.fauth ? 'forward-auth gated' : detailNode.fauth === false ? 'no auth gate' : 'public'}</span></div>
<div class="row">
<span class="k">url</span><span class="v">{detailNode.publicHost}</span>
</div>
<div class="row">
<span class="k">exposure</span><span class="v"
>{detailNode.fauth
? 'forward-auth gated'
: detailNode.fauth === false
? 'no auth gate'
: 'public'}</span
>
</div>
{:else if detailNode.url}
<div class="row"><span class="k">url</span><span class="v">{detailNode.url}</span></div>
<div class="row">
<span class="k">url</span><span class="v">{detailNode.url}</span>
</div>
{/if}
{#if detailNode.mounts.length}<div class="row"><span class="k">mounts</span><span class="v">{detailNode.mounts.join(', ')}</span></div>{/if}
{#if detailNode.repo}<div class="row"><span class="k">config</span><span class="v">{detailNode.repo}</span></div>{/if}
{#if detailNode.mounts.length}<div class="row">
<span class="k">mounts</span><span class="v">{detailNode.mounts.join(', ')}</span>
</div>{/if}
{#if detailNode.repo}<div class="row">
<span class="k">config</span><span class="v">{detailNode.repo}</span>
</div>{/if}
</div>
{#if detailRunsOn.length}
@@ -824,18 +894,24 @@
<div class="p-4">
<h3 class="legend-h">Health</h3>
{#each HEALTH_ORDER as h}
<div class="legend-row"><span class="sw" style="background:{HEALTH_COLOR[h]}"></span>{HEALTH_LABEL[h]}</div>
<div class="legend-row">
<span class="sw" style="background:{HEALTH_COLOR[h]}"></span>{HEALTH_LABEL[h]}
</div>
{/each}
<div class="sep"></div>
<h3 class="legend-h">Lanes</h3>
<div class="legend-row"><span class="lane-swatch"></span>Hosts — physical machines</div>
<div class="legend-row"><span class="lane-swatch"></span>Containers — LXCs &amp; VMs</div>
<div class="legend-row"><span class="lane-swatch"></span>Services — what you actually use</div>
<div class="legend-row">
<span class="lane-swatch"></span>Containers — LXCs &amp; VMs
</div>
<div class="legend-row">
<span class="lane-swatch"></span>Services — what you actually use
</div>
<div class="sep"></div>
<p class="hint">
Every service flows right from the machine that runs it. Hover any node to trace its chain
and blast radius — what breaks if it goes down. Click to open it in a window. Dashed arcs are
service-to-service dependencies.
Every service flows right from the machine that runs it. Hover any node to trace its
chain and blast radius — what breaks if it goes down. Click to open it in a window.
Dashed arcs are service-to-service dependencies.
</p>
</div>
{/if}
@@ -843,7 +919,9 @@
</div>
</div>
{:else}
<div class="flex h-full items-center justify-center text-xs text-muted-foreground">Failed to load graph</div>
<div class="flex h-full items-center justify-center text-xs text-muted-foreground">
Failed to load graph
</div>
{/if}
<style>
@@ -883,7 +961,9 @@
stroke: var(--border);
stroke-width: 1.4;
opacity: 0.6;
transition: opacity 0.16s, stroke 0.16s;
transition:
opacity 0.16s,
stroke 0.16s;
}
.edge.dep {
stroke-dasharray: 4 3;
@@ -919,7 +999,11 @@
border-radius: 9px;
overflow: hidden;
cursor: pointer;
transition: opacity 0.16s, border-color 0.14s, transform 0.12s, box-shadow 0.14s;
transition:
opacity 0.16s,
border-color 0.14s,
transform 0.12s,
box-shadow 0.14s;
}
.node::before {
content: '';
@@ -1001,7 +1085,10 @@
background: transparent;
color: var(--muted-foreground);
cursor: pointer;
transition: color 0.12s, border-color 0.12s, background 0.12s;
transition:
color 0.12s,
border-color 0.12s,
background 0.12s;
}
.chip:hover {
border-color: var(--primary);