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
+18 -14
View File
@@ -30,24 +30,24 @@ vantage-agent/
| Repository | Relationship |
| ---------------- | ------------------------------------------------------------------------------------------------------ |
| `vantage-shared` | a private Go module. `grpc/pb` and `grpc/codec` are the wire contract; `proto/` there documents them |
| `vantage` | the control plane. **No import in either direction** the coupling is the gRPC wire, and it is entirely mediated by `vantage-shared` |
| `vantage` | the control plane. **No import in either direction** - the coupling is the gRPC wire, and it is entirely mediated by `vantage-shared` |
**`vantage-shared` is private**, so every Go build needs
`GOPRIVATE=gitea.hostxtra.co.uk/*` plus a credential. CI writes a netrc from
`REGISTRY_USER` + `RELEASE_TOKEN` (**that token needs read access to the
`vantage` org**) twice, because the `msi` job is Windows and Go looks for
`vantage` org**) - twice, because the `msi` job is Windows and Go looks for
`_netrc` in the profile directory there, not `.netrc`. Locally, either a netrc
or `git config --global url."git@gitea.hostxtra.co.uk:".insteadOf https://gitea.hostxtra.co.uk/`.
### A wire change is three steps, in order
`shared/grpc/pb` is hand-written and shared by both sides, so a new message is a
compile error rather than a silent disagreement but only once each side moves:
compile error rather than a silent disagreement - but only once each side moves:
1. release `vantage-shared` (and change `proto/vantage/v1/vantage.proto` in the
same commit as the Go types)
2. bump the pin in `vantage`'s `server/go.mod` live at the next push to main
3. bump the pin here live only at the next `agent/v*` tag
2. bump the pin in `vantage`'s `server/go.mod` - live at the next push to main
3. bump the pin here - live only at the next `agent/v*` tag
The control plane runs ahead of the fleet in between. That was true before the
split too; it is now explicit in two `go.mod` files rather than implicit in a
@@ -68,7 +68,7 @@ git tag agent/v1.2.0 && git push origin agent/v1.2.0
Builds `linux/amd64`, `linux/arm64` and `windows/amd64`, writes `checksums.txt`,
creates the Gitea release. A second `msi` job on `windows-2022` builds the exe
again, packages it with WiX and appends the MSI to the same release **through
the API** `gitea-release-action` cannot find a tag with a slash in it.
the API** - `gitea-release-action` cannot find a tag with a slash in it.
### The self-update path, and what the move broke
@@ -77,7 +77,7 @@ the API** — `gitea-release-action` cannot find a tag with a slash in it.
SHA-256 from `checksums.txt` before swapping itself. That path is **compiled
into the binary**.
**Every agent built before this move has the old path `mrhid6/vantage`
**Every agent built before this move has the old path - `mrhid6/vantage` -
baked in, and releases are no longer published there.** For those agents the
push-button update in the UI will fail: the download 404s. They are not
stranded, because `/update` and `/update.ps1` are generated by the control plane
@@ -85,8 +85,8 @@ at request time and point wherever the current server says, so re-running the
update one-liner on a host moves it onto a build that knows the new address.
After that, self-update works again permanently.
This was a deliberate choice the alternative was publishing releases to a
repository that no longer holds the source but it means **the fleet needs one
This was a deliberate choice - the alternative was publishing releases to a
repository that no longer holds the source - but it means **the fleet needs one
pass of the update one-liner**, and the control plane must be redeployed with
the new release paths *first*, or the one-liner points at the old repository
too.
@@ -96,7 +96,7 @@ too.
- **It never reboots a host.** `ApplyUpdatesCmd` installs and stops there;
`inventory.reboot_required` reports that one is owed.
- **It decides what it will not touch.** The protected workload set is computed
and enforced agent-side `vantage-agent.service`, `VantageAgent` on Windows,
and enforced agent-side - `vantage-agent.service`, `VantageAgent` on Windows,
and its own container ID from `/proc/self/cgroup`. The control plane may name
a target; the agent decides what it will do to itself. A server-side denylist
alone would be bypassed by the next dispatch path someone adds, and the
@@ -105,12 +105,12 @@ too.
the control plane can name a port and nothing else.
- **No `authorized_keys` management on Windows**, and no package inventory: a
Windows agent never calls `ReportPackages`, so no `server_packages` document
exists for it at all a different, earlier state than the `unsupported` a
exists for it at all - a different, earlier state than the `unsupported` a
Linux distribution reaches when its family has no security feed.
## Platform split
Windows support is build tags, not runtime branches `systemd_linux.go` /
Windows support is build tags, not runtime branches - `systemd_linux.go` /
`services_windows.go` and the matching `control_` and `logs_` pairs. Windows
collection runs PowerShell through `internal/winexec`, and **every script that
reports data emits JSON that a build-tag-free parser reads**, so those parsers
@@ -126,8 +126,8 @@ article ID: a Windows update is not a version bump of a named package.
## Two constants that mirror the control plane
Neither can be shared this is a separate module and the control plane's are
under `internal/` so both must change in step, by hand:
Neither can be shared - this is a separate module and the control plane's are
under `internal/` - so both must change in step, by hand:
- the workload log cap, **500 lines and 256KB whichever binds first**, mirrored
in the control plane's `services.MaxWorkloadLogLines`
@@ -135,3 +135,7 @@ under `internal/` — so both must change in step, by hand:
control plane's 20s `PingCmd`. The watchdog arms only **after** a first ping
has been seen, so an older server that sends none is treated as working rather
than put into a reconnect loop.
## Writing style
Never use em dashes (the long dash character) anywhere: code, comments, UI copy, docs, commit messages. Use a plain hyphen ` - `, a comma, a colon, or split the sentence instead.