v2 given tests compiled against a panic-only skeleton (go vet clean); no reference implementation. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
5.0 KiB
5.0 KiB
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
- The owner gives you one task file,
docs/plans/<plan>/NN-name.md. Read it fully. Do that task and nothing else. Do not start the next task. - Do the steps in order. Where a step shows a command and its expected output, run it and compare.
- Do not read
PLAN.mdor other task files unless the task tells you to. The task file quotes what you need. - 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.mdwith statusstopped, say what you tried and what happened, commit only that file, and tell the owner. - Work only from files inside this repository. Never read another checkout (such as
~/src/crossbar-refor~/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/— in this plan or any earlier one — stays protected: tests, testdata,Makefile, scripts,example.toml,cmd/fakeupstream. If a copied test fails, your code is wrong. If a copied test can no longer be right because the new task changes what it tested, that is the owner's error: stop and report it; the owner hands over the replacement.
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: nopanic, no indexing that can go out of range on data that came from a file, a request or a peer. Check lengths, usestrconvanderrors.mainpackages 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.
gofmtdecides layout; run it before the gate.
Lessons from earlier reviews
These come from defects found in review; the evidence is in docs/implementer-log.md.
- A type assertion on a value that came from outside your package (
w.(http.Flusher), a decoded JSON field) uses the two-value form and handles thefalsecase. An unchecked assertion is a panic waiting for a caller you did not think of. - When a rule says "every" or "everywhere", finish by listing each place it applies and checking them one by one. The task shows one place; the rule covers all of them.
- Never end a turn by describing what you are about to do. Do it, then report.
- Work only inside this repository. Scratch programs under
/tmpor anywhere else are refused by the sandbox, and a refused tool call is not a reason to end the turn: write the experiment as a_test.gofile inside the repository (delete it before committing), or reason it out. Two sessions have ended with a plan and no tool call right after a refusal; that leaves the owner with no commit and nostoppedrow, the worst outcome.
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/<pkg>/ 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 <path> .... Nevergit add -Aorgit 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. If your Notes describe a change you made, it belongs here as well — a row that says none next to Notes that describe a change is wrong. |
| Notes | Problems you hit and how you solved them, in one or two sentences |
| Model | Write ?. The owner fills this in. |