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 environment, 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, 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 a live router, not just against mocks.
validate.shagainst that router 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 in the development environment 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 exactly where it cannot
run — an agent off the router, or a router with no tcpdump — and captures everywhere
else, and why a WireGuard peer that has never completed a handshake is drawn as such
rather than as one with no traffic.
What a change owes the next person#
Beyond the six, three habits the code already assumes:
Comment the reasoning, not the mechanism. Nearly every non-obvious line in this repository carries a note saying what goes wrong without it. Those comments are what lets the code be changed 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 — the inventory of what is built.