chore: replace em dashes with hyphens, add no-em-dash rule to CLAUDE.md
Chart Release / chart (push) Successful in 20s
Server Deploy / deploy (push) Failing after 1m52s

This commit is contained in:
2026-09-10 09:18:55 +00:00
parent b36a696d0e
commit 6ee203f5e9
172 changed files with 860 additions and 856 deletions
+2 -2
View File
@@ -8,8 +8,8 @@ import { Button } from "@/components/ui";
/*
* Every action this page can take, behind one control.
*
* The header used to carry up to six buttons a Connect per console protocol,
* OS updates, Generate key, Remove and which of them appeared depended on the
* The header used to carry up to six buttons - a Connect per console protocol,
* OS updates, Generate key, Remove - and which of them appeared depended on the
* server, so the row an operator reached for moved between machines. One button
* in one place is worth more than a shortcut that is sometimes there.
*
+1 -1
View File
@@ -15,7 +15,7 @@ import { clsx } from "clsx";
*
* Counts live on the labels because that is the only way an operator learns
* there is something wrong on a tab they are not looking at. A count with a
* tone is still labelled by its tab name, so tone is never the whole message
* tone is still labelled by its tab name, so tone is never the whole message -
* and in the select, where tone cannot survive, the count still does.
*/
+1 -1
View File
@@ -6,7 +6,7 @@ import { api } from "@/lib/api";
import { Button, useToast } from "@/components/ui";
/*
* A tag is key:value, so the chip shows both halves with the key dimmed the
* A tag is key:value, so the chip shows both halves with the key dimmed - the
* value is the part people scan for, the key is what disambiguates it.
*/
+9 -9
View File
@@ -10,7 +10,7 @@ import { formatBytes, relativeAge } from "./format";
* part of the page that does not move when the tab changes.
*
* A meter is a hairline, not a bar: four of them across the top would otherwise
* out-shout the hostname, and the number beside each is the value being read
* out-shout the hostname, and the number beside each is the value being read -
* the meter only says how close to full it is.
*/
@@ -29,7 +29,7 @@ function Meter({ pct }: { pct: number }) {
/** The phone strip: four readings on one line, no sub-lines and no byte
* totals. A percentage is the reading; "70.9 GB / 100.0 GB · NTFS" is the
* working, and the working belongs on the Overview tab, which is one scroll
* away. Memory is shown as a percentage here for the same reason it is the
* away. Memory is shown as a percentage here for the same reason - it is the
* only form that fits a quarter of a phone without wrapping. */
function CompactVital({ label, value, pct }: { label: string; value: string; pct?: number }) {
return (
@@ -43,7 +43,7 @@ function CompactVital({ label, value, pct }: { label: string; value: string; pct
function Vital({ label, value, pct, sub }: { label: string; value: string; pct?: number; sub?: string }) {
return (
// sm and up only the phone gets CompactVital instead.
// sm and up only - the phone gets CompactVital instead.
<div className="min-w-0 bg-surface px-4 py-3">
<div className="flex items-baseline justify-between gap-3">
<span className="truncate font-mono text-[0.62rem] uppercase tracking-[0.16em] text-text-secondary">{label}</span>
@@ -56,7 +56,7 @@ function Vital({ label, value, pct, sub }: { label: string; value: string; pct?:
}
/** The partition an operator means by "the disk": the root filesystem, or the
* fullest one if there is no root a Windows agent reports no `/`. */
* fullest one if there is no root - a Windows agent reports no `/`. */
function primaryPartition(inv: Inventory) {
const parts = inv.partitions ?? [];
if (parts.length === 0) return undefined;
@@ -64,7 +64,7 @@ function primaryPartition(inv: Inventory) {
}
/** "10.8 / 16.0 GB" rather than "10.8 GB / 16.0 GB" when both halves carry the
* same unit the repeated unit is what pushes the memory cell onto a second
* same unit - the repeated unit is what pushes the memory cell onto a second
* line on a phone, and it says nothing the right-hand half does not. */
function pair(used: number, total: number) {
const u = formatBytes(used);
@@ -124,16 +124,16 @@ export function VitalsRail({ server, agentUpToDate }: { server: Server; agentUpT
/>
<Vital
label={disk ? `Disk ${disk.mountpoint}` : "Disk"}
value={disk ? `${diskPct.toFixed(0)}%` : ""}
value={disk ? `${diskPct.toFixed(0)}%` : "-"}
pct={disk ? diskPct : undefined}
sub={disk ? `${pair(disk.used_bytes, disk.total_bytes)}${disk.fstype ? ` · ${disk.fstype}` : ""}` : "no partitions reported"}
/>
</>
) : (
<>
<Vital label="CPU" value="" sub="no metrics reported" />
<Vital label="Memory" value="" sub="no metrics reported" />
<Vital label="Disk" value="" sub="no metrics reported" />
<Vital label="CPU" value="-" sub="no metrics reported" />
<Vital label="Memory" value="-" sub="no metrics reported" />
<Vital label="Disk" value="-" sub="no metrics reported" />
</>
)}
<Vital label="Last seen" value={relativeAge(server.last_seen)} pct={server.status === "active" ? 100 : 0} sub={agentSub} />
@@ -178,8 +178,8 @@ export function MaintenanceTab({
body={
<>
<p>
<span className="font-mono text-text-primary">{server.hostname}</span> and its history keys,
inventory, workflow runs and findings are removed from Vantage.
<span className="font-mono text-text-primary">{server.hostname}</span> and its history - keys,
inventory, workflow runs and findings - are removed from Vantage.
</p>
<p>
The agent stays installed on the machine and keeps trying to connect until you uninstall it
+2 -2
View File
@@ -8,7 +8,7 @@ import type { TabId } from "../ServerTabs";
/*
* Overview answers one question: is anything wrong with this machine, and where
* do I go about it. The detail lives on the other tabs everything here either
* do I go about it. The detail lives on the other tabs - everything here either
* states a fact about the host or points at the tab that can act on it.
*/
@@ -108,7 +108,7 @@ function AttentionPanel({ items, onGoTo }: { items: Attention[]; onGoTo: (tab: T
{items.map((item) => (
<li key={item.title} className="flex flex-wrap items-center justify-between gap-3 px-6 py-3.5">
<div className="flex min-w-0 items-start gap-3">
{/* The dot is recognition, never the message the title says
{/* The dot is recognition, never the message - the title says
what is wrong on its own. */}
<span className={clsx("mt-1.5 h-1.5 w-1.5 shrink-0 rounded-full", item.tone === "danger" ? "bg-danger" : "bg-warning")} />
<div className="min-w-0">