You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
docs: rewrite CLAUDE.md to the engine era + add docs/handover.md for the next driver
CLAUDE.md was April-vintage (pure interface package, stdlib-only) — now reflects reality: module root go/, the no-cgo metal engine, cmd/lem, the build/test/kernel flows, the receipts discipline, and current perf state. docs/handover.md carries what code can't: the method (instrument first, no receipt no claim/keep, kill-switch adaptive behaviour), the priced traps (test caching, bench->live transfer limits, gate anti-selection, carry off-by-one, stale worktrees), the open #359 theta-stop slice, and a reading order.
Co-Authored-By: Virgil <virgil@lethean.io>
Copy file name to clipboardExpand all lines: CLAUDE.md
+39-44Lines changed: 39 additions & 44 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -4,69 +4,64 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
4
4
5
5
## What This Is
6
6
7
-
Shared inference interfaces for the Core Go ecosystem. Module: `dappco.re/go/inference`
7
+
The sovereign inference engine for the Core Go ecosystem. Module: `dappco.re/go/inference`, module root at **`go/`** (work from there). Two things live here:
8
8
9
-
Zero external dependencies (stdlib only). Compiles on all platforms. See `docs/architecture.md` for design rationale.
9
+
1.**The shared contract** (`go/*.go`) — `TextModel`/`Backend` interfaces, options, registry, discovery. Backends import this; never the reverse.
10
+
2.**The engines** (`go/engine/`) — `engine/metal` (package `native`): the **no-cgo Apple GPU engine** (darwin/arm64, objc bridge via `github.com/tmc/apple`, ICB-replayed decode, MTP speculative pairs, paged SDPA, q8 KV); `engine/hip`: AMD ROCm (linux/amd64). Plus `cmd/lem` (the serving/bench binary), OpenAI/Anthropic/Ollama compat handlers, and conversation state (`-state`, no-prompt-replay).
11
+
12
+
`docs/` at repo root is the manual: `architecture.md`, `backends.md` (registry + **engine runtime levers**), `cmd-lem.md`, `build.md`, and **`handover.md` — read that one first; it is the working handover from the engine-perf campaigns.**
10
13
11
14
## Commands
12
15
13
16
```bash
14
-
go test ./... # Run all tests
15
-
go test -run TestDefault_Good_Metal # Run a single test by name
This is a pure interface package — it defines contracts but contains no backend implementations. The dependency flows one way: backends import this package, never the reverse.
`MLX_METALLIB_PATH` must be inlined per command — it does not persist between shells here.
29
32
30
-
**Backend registry pattern:** Backends register via `init()` with build tags (e.g. `//go:build darwin && arm64`). `Default()` picks backends in priority order: metal > rocm > llama_cpp > any available. `LoadModel()` routes to explicit backend via `WithBackend()` or falls back to `Default()`.
33
+
## Working discipline (how this engine got fast)
31
34
32
-
**Optional interfaces via type assertion:** New capabilities are expressed as separate interfaces (e.g. `AttentionInspector`, `TrainableModel`) rather than extending `TextModel`. Consumers discover them with `model.(inference.AttentionInspector)`.
35
+
-**Instrument before assessment; receipt before claim.** Every perf commit carries its before→after numbers in the message. A theory without a live receipt gets built, measured, and **reverted if it loses** — falsifications are banked in the task tracker, not hidden.
36
+
-**One lever per commit.** Kill-switch env for anything wall-clock-adaptive (`LTHN_MTP_REENGAGE=0`, `LTHN_MTP_DRAFTLEN=0` — the repro anchors).
37
+
-**Bench→live transfer is not guaranteed** — micro-bench wins on >134MB buffers have reproducibly lost in live decode. The live A/B is the only receipt that counts.
38
+
-**No bulk perl/sed refactors** — one site at a time, vet after each.
39
+
- Branch **dev**; origin `github.com/dAppCore/go-inference` (push non-force). Task board via the session task tools; git log is the history of record.
33
40
34
-
**Streaming uses `iter.Seq[Token]`:** Generate/Chat return Go 1.23+ range-over-function iterators. Errors are retrieved via `Err()` after the iterator finishes (follows `database/sql``Row.Err()` pattern).
41
+
## Stability Rules (root contract)
35
42
36
-
## Stability Rules
37
-
38
-
This package is the shared contract. Changes here affect go-mlx, go-rocm, and go-ml simultaneously.
43
+
Changes to `go/*.go` interfaces affect every consumer simultaneously.
39
44
40
45
- Never change existing method signatures on `TextModel` or `Backend`
41
-
- Only add methods when two or more consumers need them
42
-
- Prefer new interfaces that embed `TextModel` over extending `TextModel` itself
43
-
- New fields on `GenerateConfig` or `LoadConfig` are safe (zero-value defaults)
44
-
- All new interface methods require Virgil approval before merging
46
+
- New capabilities are **separate interfaces** discovered by type assertion (`AttentionInspector`, `VisionModel`, `engine.TrainerModel`) — never extend `TextModel`
47
+
- New fields on `GenerateConfig`/`LoadConfig` are safe (zero-value defaults)
48
+
- Streaming is `iter.Seq[Token]`; errors via `Err()` after the iterator (the `database/sql` pattern)
45
49
46
50
## Test Patterns
47
51
48
-
Tests use the `_Good`/`_Bad`/`_Ugly` suffix convention:
Tests touching the global backend registry must call `resetBackends(t)` first (defined in `inference_test.go`, clears the registry map). Use existing `stubBackend`/`stubTextModel` from `inference_test.go` rather than creating new stubs.
54
-
55
-
Use `testify/assert` (general checks) and `testify/require` (preconditions). Use `assert.InDelta` for float comparisons.
0 commit comments