Working agreements#
AGENTS.md is the standing instruction for anyone changing this
repository, and it opens with the reason the rest of it exists: you are working on a
product with commercial ambitions — act like it: decisions get recorded, shortcuts get
flagged, and the plan stays truthful. Six agreements follow, plus a protocol for which
of three repositories a change belongs in and a boundary that keeps proprietary code
proprietary. This page restates them, with the file to open in each case.
Read these first, in this order#
PLAN.md— mission, architecture, milestones. The standing prompt.wheelhouse-infra's ownAGENTS.md— the development bench, its access paths, and the shell traps that have already cost hours.HomelabInfra— the environment. The production router configuration there is the reference workload.
Which repository a change belongs in#
| Kind of change | Repository |
|---|---|
| Product decisions, feature scope, UX, architecture | This one — PLAN.md, or docs/adr/NNN-*.md for a decision that changes it |
| Platform, bench, build-host and deployment work | wheelhouse-infra |
| Facts about the homelab: hosts, the production router, addresses | HomelabInfra |
Never duplicate; always link. A commit message that spans repositories names the sibling commit.
There is a fourth boundary inside this repository, and it is the one two people most often
collide on: docs/ and the root Markdown files are the repository's own documentation and
are versioned with the code. site/ is the published website and is built separately.
Where the website carries something better, docs/ links to it rather than repeating it.
The six agreements#
1. Milestones are the backlog#
Work the lowest unfinished milestone in PLAN.md §10. A deviation is
allowed; an unexplained one is not — edit PLAN.md in the same change with a one-line
reason.
2. The definition of done#
A feature is done when all of this is true:
- It works against the live
vyoslabinstance, not just against mocks. validate.shon the bench is still green.- The API contract is typed and documented.
- There are tests: unit, plus one end-to-end happy path.
- The change carries a screenshot or a terminal capture.
PLAN.md's coverage matrix is updated if coverage changed.
3. The reference workload is sacred#
The production router's configuration — 19 forwards, 20 reservations, split DNS, PXE and CAKE — is the fixture set. A feature that cannot express it is not done. That is what keeps the product measured against a real network rather than against a demo.
4. Licence hygiene#
This is the rule with the least room for interpretation, because the company depends on it:
- No GPL or AGPL code is copied into
agent/orui/. Not a function, not a parser, not a constant table. - VyOS is driven through its API and its op-mode commands only.
- Every compiled-in dependency is permissive, and each is recorded in
docs/licenses.mdwith its version and licence.
Two of the three architecture decision records are, in part, a written justification for taking a dependency instead of writing a half-implementation. That is the shape the trade is meant to have: name the dependency, name its licence, record it.
The boundary is also what the image pipeline defends — The flavor and the branding hooks — and what the customer-facing statement on About Wheelhouse rests on.
5. Secrets#
Development credentials live in one place on the bench and nowhere else. Nothing secret goes into git, an issue or a transcript. The dev instance password is to be rotated before any external collaborator gets access, because it appeared in a session log once.
The same discipline is enforced in code: the agent refuses a secret file that is group- or
world-readable, and every secret has a --…-file form because a flag value is visible to
every user on the box through /proc.
6. Honesty over demo-ware#
If a panel shows state, it must be real state from the router. Mocked data ships only
behind an explicit --demo flag.
That single rule explains a surprising amount of the codebase: why an app health probe
reports "not probed — this agent runs off-router" instead of a red cross it cannot justify,
why packet capture answers 501 with the command to run by hand rather than pretending,
and why the WireGuard page says handshake counters need something the agent does not do
yet instead of showing a plausible number.
What a change owes the next person#
Beyond the six, three habits are visible throughout the tree and are worth adopting because the code already assumes them:
Comment the reasoning, not the mechanism. Nearly every non-obvious line in this
repository carries a note saying what went wrong without it — the login limiter that ran
after the decode, the health probe that only spoke HTTP and rolled back a good binary, the
two postinst scripts where the stale one won. Those comments are why the code can be
changed safely by someone who was not there.
Assert, do not assume. The image pipeline patches a file and then checks the patch took; the branding hooks fail the build rather than ship a half-branded image; the ISO inspection refuses an artefact older than 48 hours. An upstream change should break the build loudly, on the machine that can still do something about it.
Name a regression test after the behaviour. TestAStaleCookieDoesNotMaskAValidBearerToken
tells a reader what they broke from the failure line alone; TestBug47 does not.
See also#
- Architecture decision records — where a decision that changes the architecture is written down.
- The test suites — what "tests" means in each part of the tree.
- What CI does — and what it cannot check for you.
- Contributing — the separate rules for this documentation site.
- About Wheelhouse · Built on VyOS · Third-party licences — the licence boundary, stated for a customer.
- What is finished, and what is not — what "honesty over demo-ware" looks like when it is written down for a buyer.
Checked against#
AGENTS.md ·
PLAN.md ·
docs/licenses.md ·
agent/main.go ·
agent/catalog.go ·
docs/adr/001-desired-state-file.md ·
docs/adr/002-oidc-client.md