Every given test compiled against a panic-only interface skeleton (go vet clean); nothing was implemented. modernc.org/sqlite v1.59.0 vetted in a scratch module (WAL works); go.sum given. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
3.7 KiB
v1 implementation plan: leases, queueing, accounting
For the implementing model: do not work from this file. The owner gives you one task file at a time (
01-…to07-…). This file is the index for the owner and the reviewer.
Goal: PLAN.md §4–§7a. Every conversation gets a sticky lease on one host (chosen by free
slots × weight when it starts), requests queue per (host, model) instead of overflowing a
router, an operator can pin a route or drain a host, and SQLite keeps the leases and an accounting
log that answers "which session used which host and model, for how long, at what cache-hit rate".
Architecture: five new packages — store (SQLite, modernc.org/sqlite), fingerprint
(conversation key), choose (the scoring rule), limiter (per-(host, model) slots + bounded
FIFO), lease (the sticky table, persisted through store) — and v1 versions of proxy,
admin, config and cmd/crossbar. The proxy tees streamed responses through an SSE scanner
to read the final usage/timings chunk; it never buffers or alters the stream.
How this plan was made: acceptance tests first, from PLAN.md; no reference implementation.
Every given test file was compiled against a panic-only skeleton of the interfaces named in the
tasks (go vet ./... clean), and nothing else was run. If a test turns out to be wrong, that is
the owner's finding: stop and report as AGENTS.md says; do not edit it.
Tech stack: Go 1.26, stdlib, github.com/BurntSushi/toml v1.6.0, modernc.org/sqlite
v1.59.0 (pure Go; go.sum given). No other module.
Global constraints
- Everything in
AGENTS.md. Branchv1. One task, one fresh OpenCode session, one commit. - Bodies are never logged or stored. Rows carry names, counts and timings only.
- Given files (tests,
example.toml,cmd/fakeupstream/main.go,tools/smoke.sh,go.sum) are copied and never edited. Some replace v0 files of the same name; the task says so.
Tasks
| # | File | Delivers | Tests that define it |
|---|---|---|---|
| 01 | 01-store.md |
internal/store: SQLite state + accounting |
internal/store/store_test.go |
| 02 | 02-fingerprint-config.md |
internal/fingerprint; config gains db, lease_idle, retention, day suffix |
fingerprint_test.go, config_v1_test.go |
| 03 | 03-limiter-choose.md |
internal/limiter, internal/choose |
limiter_test.go, choose_test.go |
| 04 | 04-lease.md |
internal/lease: the sticky table |
lease_test.go |
| 05 | 05-proxy.md |
proxy v1: leases, queue, SSE tee, accounting, header route | proxy_test.go (replaces v0's) |
| 06 | 06-admin-main.md |
admin v1 (pin/release/drain/usage/metrics), cmd/crossbar wiring |
admin_test.go (replaces), start/stop check |
| 07 | 07-smoke-readme.md |
tools/smoke.sh v1 run, README update |
make smoke |
For the owner: running a task
tools/run-plan.sh docs/plans/v1 # from a clean checkout on master
For the reviewer: after task 07
git log --oneline master..v1: seven commits with the trailer.- Copied files byte-identical to
_files/;git diff <merge-base>..v1 --stat -- PLAN.md AGENTS.md docs/plansempty. make gate,make smoke.- Read every source file against its task. Probe outside the tests: a lease whose host is
drained and unhealthy;
lease_idleexpiry while a request is in flight; a stream cut by the client mid-way (the accounting row must still be written, with the status it had); a body with"messages"that is not an array; two crossbars on the samedbfile;Prunewhile requests are being recorded. - Every
.(type assertion ininternal/is the two-value form or on a value we constructed. - Findings under "Reviews" in
docs/implementer-log.md, by fault (model / task / test).