# AGENTS.md crossbar is an affinity router for the fleet's `llama-server` instances, written in Go. You are implementing it one task at a time. ## How you work 1. The owner gives you one task file, `docs/plans//NN-name.md`. Read it fully. Do that task and nothing else. Do not start the next task. 2. Do the steps in order. Where a step shows a command and its expected output, run it and compare. 3. Do not read `PLAN.md` or other task files unless the task tells you to. The task file quotes what you need. 4. If something in the task is impossible, contradictory, or fails twice in the same way, **stop**. Do not improvise, do not change a test, do not weaken a check. Add your row to `docs/implementer-log.md` with status `stopped`, say what you tried and what happened, commit only that file, and tell the owner. 5. Work only from files inside this repository. Never read another checkout (such as `~/src/crossbar-ref` or `~/src/crossbar-design`), and never search the file system for code. If you are stuck, stop as in point 4. ## Files you must never edit - `PLAN.md`, `docs/plans/`, `AGENTS.md` - Anything a task told you to copy from `docs/plans/**/files/`: tests, testdata, `Makefile`, scripts, `example.toml`, `cmd/fakeupstream`. If a copied test fails, your code is wrong. ## Code rules - Go 1.26 (the version in `go.mod`). Standard library plus the one dependency named in the tasks (`github.com/BurntSushi/toml`). No other module, ever. - No source file over 400 lines (`scripts/check-lines.sh`). - Library code (`internal/...`) never panics on input: no `panic`, no indexing that can go out of range on data that came from a file, a request or a peer. Check lengths, use `strconv` and `errors`. `main` packages may exit with a message. - Errors are values: return them, wrap with `fmt.Errorf("...: %w", err)`, never log-and-continue in library code. A check that cannot do its job fails; it does not return "ok". - Never log, print or store a request or response body. Log lines carry names, paths, status codes and durations only. - Anything read from the network is bounded (`io.LimitReader`, `http.MaxBytesReader`, timeouts). - Exported names, field names and JSON/TOML tags are exactly as the task gives them; the tests compile against them. - Comments say why, not what. `gofmt` decides layout; run it before the gate. ## The gate `make gate` must print `gate: ok` before a task is done. It runs offline: `gofmt -l`, `go vet`, `go test -race -count=1 ./...`, and `scripts/check-lines.sh`. Run `gofmt -w` on the files you touched before the gate. `go test ./internal//` runs one package. ## Git - Work on the branch the task names. One task is one commit. - Stage only the paths the task lists: `git add ...`. Never `git add -A` or `git add .`. - Never push, amend, rebase, reset, or switch to another branch. - Commit message: the subject line the task gives, a blank line, then this trailer: `Implemented-By: OpenCode session (model recorded in docs/implementer-log.md)` ## The implementer log Before you commit, add one row to the table in `docs/implementer-log.md` and include the file in the commit. Be honest: the log is how the owner judges the process. | Column | What to write | |---|---| | Task | The task file name, for example `v0/02-health` | | Date | Today's date, `YYYY-MM-DD` | | Status | `done` or `stopped` | | Gate runs | How many times you ran `make gate` | | First gate | `pass` or `fail` for the first run | | Deviations | Anything you did that the task did not say, or `none` | | Notes | Problems you hit and how you solved them, in one or two sentences | | Model | Write `?`. The owner fills this in. |