chore: replace em dashes with hyphens, add no-em-dash rule to CLAUDE.md

This commit is contained in:
2026-09-10 09:18:54 +00:00
parent 1ad46dfda2
commit b777ffcf58
15 changed files with 52 additions and 48 deletions
+1 -1
View File
@@ -28,7 +28,7 @@ func collect(r *pb.InventoryReport, includeStatic bool) {
if m.TotalPhys > m.AvailPhys {
r.Memory.UsedBytes = m.TotalPhys - m.AvailPhys
}
// TotalPageFile is the commit limit physical memory plus the pagefile
// TotalPageFile is the commit limit - physical memory plus the pagefile -
// so the pagefile alone is the difference.
swapTotal := sub(m.TotalPageFile, m.TotalPhys)
swapUsed := sub(sub(m.TotalPageFile, m.AvailPageFile), sub(m.TotalPhys, m.AvailPhys))
+1 -1
View File
@@ -16,7 +16,7 @@ const collectTimeout = 2 * time.Minute
//
// The format strings below are raw string literals on purpose. The "\t" and
// "\n" reach dpkg-query and rpm as two characters each, and those tools do the
// interpreting themselves Go must not consume the escapes first.
// interpreting themselves - Go must not consume the escapes first.
func Collect() (OSRelease, []Package, error) {
if runtime.GOOS != "linux" {
return OSRelease{}, nil, fmt.Errorf("package collection is linux-only, got %s", runtime.GOOS)
+3 -3
View File
@@ -9,7 +9,7 @@ import (
)
// Package is one installed package as the distribution reports it. Version is
// the distribution's own version string, verbatim never normalised, because
// the distribution's own version string, verbatim - never normalised, because
// the advisory feeds are keyed on exactly this form.
type Package struct {
Name string
@@ -29,7 +29,7 @@ type Package struct {
//
// The fifth column is why "rc" packages do not appear. dpkg-query -W lists
// every package dpkg knows about, including ones removed with their config
// files left behind a host that has upgraded its kernel a dozen times reports
// files left behind - a host that has upgraded its kernel a dozen times reports
// a dozen old linux-modules versions that are not on disk, and the oldest of
// them sorts first and reads as the installed version. Only "installed" is
// installed. An empty status means dpkg did not understand the field, in which
@@ -143,7 +143,7 @@ func splitAPK(s string) (name, version string) {
//
// It sorts first: the ordering of dpkg or rpm output is not guaranteed stable,
// and an ordering-sensitive hash would resend the full ~150KB list every hour
// for no reason a cost visible only as traffic.
// for no reason - a cost visible only as traffic.
func Hash(pkgs []Package) string {
lines := make([]string, 0, len(pkgs))
for _, p := range pkgs {
+3 -3
View File
@@ -15,7 +15,7 @@ import (
)
// collectPackagesFlag is written by the 30s key poll and read by the hourly
// package loop two different goroutines, hence the atomic.
// package loop - two different goroutines, hence the atomic.
//
// It defaults to false, so an agent that has not yet completed a poll, or is
// talking to a server too old to send the field, collects nothing. Off is the
@@ -27,7 +27,7 @@ var collectPackagesFlag atomic.Bool
//
// Without it the boot-time package report loses a race it can only lose: the
// hourly loop starts before the first poll, reads a flag that is still false by
// construction, and skips so a freshly installed agent reports no packages for
// construction, and skips - so a freshly installed agent reports no packages for
// an hour and the server shows nothing to scan.
// How long the boot package report waits for that first poll. Two poll
// intervals plus slack: long enough to cover one failed attempt, short enough
@@ -43,7 +43,7 @@ func markFirstPoll() { firstPollOnce.Do(func() { close(firstPoll) }) }
// waitFirstPoll blocks until the flag is known, or gives up. The wait is
// bounded because this loop also reports OS updates, which do not depend on the
// flag at all a control plane that cannot be polled must not silence those too.
// flag at all - a control plane that cannot be polled must not silence those too.
func waitFirstPoll(ctx context.Context, limit time.Duration) {
t := time.NewTimer(limit)
defer t.Stop()
+6 -6
View File
@@ -134,7 +134,7 @@ func poll(client *grpcclient.Client, cfg *config.Config, version string) error {
const streamHealthyAfter = time.Minute
// Stream staleness. The server beats every 20s, so 70s tolerates three missed
// beats before the stream is written off high enough that a slow network or a
// beats before the stream is written off - high enough that a slow network or a
// briefly busy server does not cost a reconnect, low enough that an agent is
// not uncommandable for minutes after a control-plane restart.
const (
@@ -142,7 +142,7 @@ const (
streamStaleCheck = 10 * time.Second
// How often a healthy stream reports itself. Also the interval at which an
// agent talking to a control plane too old to send heartbeats says so
// agent talking to a control plane too old to send heartbeats says so -
// that agent is running without a watchdog, and the journal should not be
// silent about it.
pingSummaryInterval = 5 * time.Minute
@@ -184,7 +184,7 @@ func runCommandStream(ctx context.Context, cfg *config.Config) {
// The uptime is in the line because it is what distinguishes a stream
// that never worked from one that ran for hours and was dropped by a
// deploy and it is the same measure that decides whether the backoff
// deploy - and it is the same measure that decides whether the backoff
// resets, so a reader can see why the delay is what it is.
up := time.Since(started).Truncate(time.Second)
if err != nil {
@@ -253,7 +253,7 @@ func connectAndHandleStream(ctx context.Context, cfg *config.Config) error {
// the operator watches nothing happen.
//
// The watchdog only arms once a ping has actually been seen. A server too
// old to send them must not be treated as dead that would put the agent
// old to send them must not be treated as dead - that would put the agent
// in a reconnect loop against a control plane that is working perfectly.
var (
lastMu sync.Mutex
@@ -283,7 +283,7 @@ func connectAndHandleStream(ctx context.Context, cfg *config.Config) error {
// Reported periodically rather than per beat: at one every 20s the
// journal would be nothing else. The count is what makes a partial
// failure visible beats arriving but fewer than expected is a
// failure visible - beats arriving but fewer than expected is a
// different problem from beats stopping altogether.
summary := time.NewTicker(pingSummaryInterval)
defer summary.Stop()
@@ -450,7 +450,7 @@ func runInventory(ctx context.Context, cfg *config.Config) {
r := inventory.Collect(static)
r.ServerId = cfg.ServerID
r.AgentToken = cfg.AgentToken
// Static snapshots only every 15 minutes, not every 30 seconds. On
// Static snapshots only - every 15 minutes, not every 30 seconds. On
// Windows this spawns a PowerShell process, which is not something to
// do twice a minute forever, and a host rebooted by hand clearing the
// flag within a quarter of an hour is soon enough.
+2 -2
View File
@@ -1,7 +1,7 @@
// Package winexec runs PowerShell on Windows hosts.
//
// It exists because three subsystems updates, workload collection and
// workload logs all need the same invocation, and because getting a
// It exists because three subsystems - updates, workload collection and
// workload logs - all need the same invocation, and because getting a
// multi-line script past Go quoting, cmd.exe quoting and PowerShell's own
// parser is a problem worth solving once.
package winexec
+1 -1
View File
@@ -9,7 +9,7 @@ import (
"gitea.hostxtra.co.uk/vantage/vantage-agent/internal/winexec"
)
// AgentUnit is the service this agent runs as the NSSM service name written
// AgentUnit is the service this agent runs as - the NSSM service name written
// by installer/setup.ps1. Change one, change the other.
const AgentUnit = "VantageAgent"
+3 -3
View File
@@ -30,8 +30,8 @@ const dockerTimeout = 30 * time.Second
// dockerInspect is the subset of `docker inspect` output we read.
//
// We use inspect rather than `docker ps --format '{{json .}}'` because ps
// reports health and uptime inside a human Status string "Up 2 hours
// (healthy)" and anything built on that is parsing English that is
// reports health and uptime inside a human Status string - "Up 2 hours
// (healthy)" - and anything built on that is parsing English that is
// localised, reworded between releases, and silently different for a paused or
// restarting container. inspect gives typed fields instead.
type dockerInspect struct {
@@ -59,7 +59,7 @@ type dockerInspect struct {
}
// collectDocker enumerates containers. It returns ok=false with an empty error
// string when Docker is simply not installed the common case on this fleet,
// string when Docker is simply not installed - the common case on this fleet,
// and not a fault.
func collectDocker(ctx context.Context) ([]Workload, bool, string) {
if _, err := exec.LookPath("docker"); err != nil {
+3 -3
View File
@@ -25,7 +25,7 @@ func logsPlatform(ctx context.Context, kind, id string, tail int) (string, error
// Timestamps are formatted PowerShell-side rather than left to
// ConvertTo-Json, whose DateTime rendering differs between PowerShell
// versions one of them emits /Date(1699...)/.
// versions - one of them emits /Date(1699...)/.
//
// $ErrorActionPreference = 'SilentlyContinue' because Get-WinEvent
// treats "no events matched" as a terminating error, and a quiet
@@ -38,7 +38,7 @@ func logsPlatform(ctx context.Context, kind, id string, tail int) (string, error
// ProviderName includes the host-wide Service Control Manager, so a
// -MaxEvents cap of exactly tail would apply to the combined stream
// before parseEvents narrows SCM rows down to this service on a
// before parseEvents narrows SCM rows down to this service - on a
// host with busy service churn the target's own events could be
// squeezed out of the window entirely. Over-fetch instead, hard-capped
// so a pathological host cannot pull an unbounded batch across the
@@ -76,7 +76,7 @@ ConvertTo-Json -InputObject @($rows) -Depth 3 -Compress
}
// serviceDisplayName resolves a service's display name, which is what Service
// Control Manager events name it by. An empty answer is fine the filter then
// Control Manager events name it by. An empty answer is fine - the filter then
// matches on the service name alone.
func serviceDisplayName(ctx context.Context, id string) string {
out, err := winexec.Run(ctx,
+1 -1
View File
@@ -15,7 +15,7 @@ const systemdTimeout = 30 * time.Second
var excludedPrefixes = []string{"systemd-", "user@", "user-", "session-", "init.scope"}
// collectUnits enumerates services in two passes, because "running or
// failed" and "enabled but stopped" are different questions and an enabled
// failed" and "enabled but stopped" are different questions - and an enabled
// unit that is not running is exactly the one worth seeing.
func collectUnits(ctx context.Context) ([]Workload, bool, string) {
if _, err := exec.LookPath("systemctl"); err != nil {
+1 -1
View File
@@ -1,6 +1,6 @@
//go:build !linux && !windows
// The build constraint is load-bearing see updates_other.go.
// The build constraint is load-bearing - see updates_other.go.
package workloads
import (
+6 -6
View File
@@ -19,7 +19,7 @@ type winService struct {
}
// exitCodeNeverStarted is ERROR_SERVICE_NEVER_STARTED. A stopped service
// carrying it has not failed it has not run since boot and painting that
// carrying it has not failed - it has not run since boot - and painting that
// red would cry wolf on every host.
const exitCodeNeverStarted = 1077
@@ -52,8 +52,8 @@ func servicePath(pathName string) string {
}
// exeBoundaryIndex finds the first ".exe" (case-insensitive) in s that
// actually ends the executable name followed by end-of-string, whitespace,
// or a double quote rather than continuing into a longer segment such as
// actually ends the executable name - followed by end-of-string, whitespace,
// or a double quote - rather than continuing into a longer segment such as
// ".exec". It returns -1 when no such occurrence exists, so a path like
// `C:\Program Files\Ad.exec\tool.com -flag` is not misparsed by matching the
// ".exe" inside "Ad.exec" and silently dropping the real filename.
@@ -113,8 +113,8 @@ func parseServices(jsonText, systemRoot string) ([]Workload, error) {
continue
}
// The wire shape is shared with the systemd collector both report
// under kind "unit" so the state word has to be too, or the UI
// The wire shape is shared with the systemd collector - both report
// under kind "unit" - so the state word has to be too, or the UI
// (which colours and filters on it, and does so before it knows
// which platform sent the row) needs two vocabularies for one kind.
// running/stopped/failed become active/inactive/failed to match.
@@ -168,7 +168,7 @@ type winEvent struct {
// applied before SCM rows are narrowed down to this service would squeeze the
// target's own events out of the window on a host with busy service churn.
// tail is therefore applied here, AFTER filtering and AFTER the oldest-first
// reversal, keeping the last tail lines the most recent lines are the ones
// reversal, keeping the last tail lines - the most recent lines are the ones
// worth keeping, matching capLog's front-trim reasoning in the shared
// logs.go.
func parseEvents(jsonText, serviceName, displayName string, tail int) (string, error) {
+2 -2
View File
@@ -13,7 +13,7 @@ func TestServicePath(t *testing.T) {
{`"C:\no\args.exe"`, `C:\no\args.exe`},
{``, ``},
// ".exe" appearing inside an earlier segment ("Ad.exec") must not be
// treated as the end of the executable that would drop the real
// treated as the end of the executable - that would drop the real
// filename and arguments.
{`C:\Program Files\Ad.exec\tool.com -flag`, `C:\Program`},
// An unterminated quote falls back to the unquoted handling on the
@@ -72,7 +72,7 @@ func TestParseServicesFilters(t *testing.T) {
}
}
// 1077 means "no attempt to start since boot" a clean stopped service, not a
// 1077 means "no attempt to start since boot" - a clean stopped service, not a
// failure, and reporting it red would cry wolf on every host.
func TestParseServicesExitCode1077(t *testing.T) {
in := `[{"Name":"Idle","DisplayName":"Idle","State":"Stopped","StartMode":"Auto","PathName":"C:\\Idle\\i.exe","ExitCode":1077}]`
+1 -1
View File
@@ -37,7 +37,7 @@ func Collect(ctx context.Context) Result {
//
// It sorts first: `docker ps` output ordering is not stable, and an
// ordering-sensitive hash would resend the full list every 60 seconds forever
// a cost visible only as traffic.
// - a cost visible only as traffic.
//
// StartedAt is deliberately excluded: it does not change while a container
// runs, and including it would add nothing. Restarts IS included, because a