Tests were run against a private reference implementation: gate ok after every task in order, smoke ok (stream spread ~1000 ms). The reference is not in the repository. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
v0 implementation plan: static routing, health, streaming proxy
For the implementing model: do not work from this file. The owner gives you one task file at a time (
01-…to05-…). This file is the index for the owner and the reviewer.
Goal: a crossbar binary that reads a TOML file, polls each host's /health and
/v1/models, and forwards /{route}/v1/* to the first healthy host on that route's preference
list, streaming responses chunk by chunk, marking a host down when a proxied request fails, and
showing the health table at /_crossbar/hosts. This is PLAN.md §10 v0: no leases, no SQLite,
no /slots, no queueing.
Architecture: four small packages under internal/ — config (TOML + validation), health
(poller + table), proxy (route → host → httputil.ReverseProxy), admin (read-only JSON) —
and two binaries under cmd/: crossbar and the given fakeupstream. Behaviour is pinned by
the tests in files/, which were run against a private reference implementation at each task's
end state; the reference is not in this repository and the implementer must not look for it.
Tech stack: Go 1.26, standard library, github.com/BurntSushi/toml v1.6.0. Nothing else.
Global constraints
- Everything in
AGENTS.md. - Branch
v0. One task, one fresh OpenCode session, one commit.gofmt -wbefore the gate. - No source file over 400 lines. Library code never panics on input, never logs a body.
- The given files are copied and never edited. If a copied test fails, the code is wrong.
Tasks
| # | File | Delivers | Tests that define it |
|---|---|---|---|
| 01 | 01-module-gate-config.md |
go.mod, the gate, internal/config |
internal/config/config_test.go + testdata/ |
| 02 | 02-health.md |
internal/health: poller and table |
internal/health/health_test.go |
| 03 | 03-proxy.md |
internal/proxy: routing reverse proxy |
internal/proxy/proxy_test.go |
| 04 | 04-admin-main.md |
internal/admin, cmd/crossbar, the given cmd/fakeupstream |
internal/admin/admin_test.go, a start/stop check |
| 05 | 05-smoke-readme-deploy.md |
tools/smoke.sh run, README.md, deploy/crossbar.service |
make smoke |
At the end: make gate prints gate: ok, make smoke prints smoke: ok (stream spread N ms).
For the owner: running a task
From a clean checkout on master:
tools/run-plan.sh docs/plans/v0 # all tasks, each in a fresh `opencode run` session
tools/run-plan.sh docs/plans/v0 03 # from task 03
The default model is llama.cpp/ornith-1.5-35b-a3b (override with CROSSBAR_MODEL). The driver
stops at the first task that does not end with a commit, a clean tree and a done row in
docs/implementer-log.md. Keep the OpenCode TUI closed while it runs.
For the reviewer: after task 05
git log --oneline master..v0: five commits with theImplemented-Bytrailer.- Copied files are unchanged:
for f in $(cd docs/plans/v0/files && find . -type f); do cmp "docs/plans/v0/files/$f" "$f"; done git diff master..v0 --stat -- PLAN.md AGENTS.md docs/plansis empty.make gateandmake smokeon straylight.- Read every source file against its task. Probe from outside with inputs the tests do not
contain: a route with query strings and encoded characters, a host that hangs after headers, a
3 MB request body,
/_crossbar/hostswhile a poll is in flight, SIGTERM during a stream. - Write findings under "Reviews" in
docs/implementer-log.md.