A reasoning scaffold for any model — designed to help small models reason past their limits, and to keep frontier models from anchoring on the obvious-but-wrong answer.
Spine is a small, open reasoning scaffold — a set of operating laws plus a grounded loop — that wraps around any LLM (a local 2B or a frontier cloud model) to change how it works a hard, trap-laden problem. Instead of pattern-matching to the loudest cue — an error code, a documented "fix" that didn't work — the loop walks the model through a procedure: orient, ask the single most discriminating question, gather evidence, prune causes until one survives, and treat a confirmed fix — not just a named cause — as the finish line.
The intent:
- for a small or limited model, to let it reason further than it otherwise could;
- for a frontier model, to guard against the failure you'd assume scale already fixed — anchoring on the obvious-but-wrong answer (we watched a frontier model do exactly that, one-shot, on a trap it "should" have aced).
How well it delivers depends on the model and the case — so don't take it on faith. The trap cases, the harness, and our raw results are all in this repo; reproduce the anchoring test on your own model and judge for yourself. What's published here are design goals and observed results with the data attached — not guarantees.
The discipline lives outside the model — in the laws and an inspectable state grid — so any model inherits it, and even a tiny one can carry a long, reopened case without re-deriving it from scratch. It ships as an MCP tool so any agent can call it — or as a plain prompt you paste into any chat to test it with zero install.
Don't trust the claim — run it. → The anchoring test
⚠️ Early release — the numbers are LLM-judged, not ground truth. The cloud panel, the qwen-9B anchoring ablation, the personal-AI MTU runs, and Gemma-4B are adversarially 3-lens judged (mechanism/trap/earned + majority vote); Gemma-2B is first-pass single-judge. Don't trust them — reproduce them. (PRE-PUBLIC.mdrecords what was verified.)
Under one-shot pressure with a salient-but-wrong cue — an error code, a loud symptom, a documented fix that didn't work — a model tends to grab the obvious answer and anchor on it. Scale makes a model better-calibrated, but in our tests it didn't make this go away (we watched a frontier model dismiss the scaffold, then fall for the exact trap one-shot). Spine is built to counter that with explicit, systematic elimination: orient → enumerate candidate causes → ask the single most discriminating question → integrate → prune → repeat → aim for a confirmed fix, not just a named cause. The failure it targets — anchoring — showed up at every scale we tried, which is why we think it isn't only a small-model trick.
What we've measured (full data in runs/)
1. Cloud panel — 8 models × 2 cases, adversarially 3-lens judged: 8/8 converged on the shared trap; breadth 5/8 on the unique cases (3 missed — 1 fell for the trap, 2 wrong); 13/16 correct + earned overall. → runs/bench_2026-06-27_0048.json, runs/verify_result.json
2. Local-model anchoring ablation — the core thesis on the same qwen3.5:9b (local, via Ollama): the Spine scaffold vs a single-shot answer, on 3 trap cases, adversarially 3-lens re-verified:
| qwen3.5:9b | Printer (clog upstream of a healthy head) | Internet (LAN flood) | Car (fuel pump) | Total |
|---|---|---|---|---|
| + Spine scaffold | ✅ correct | ✅ correct+earned | ✅ correct | 3/3 correct |
| shotgun (single-shot) | ✗ wrong | ✗ wrong | 0/3 |
The scaffold flips the identical 9B from 0/3 → 3/3, and the shotgun anchored straight onto the LAN-flood trap the scaffold rejected — the outcome reproduces under adversarial majority vote. Honest caveat: only 1/3 of the scaffold wins is certified earned (genuinely elicited by a discriminating question); on the other two the cooperative same-model oracle volunteered the gating evidence. So: a real anti-anchoring lift (3/3 outcome) with 1/3 demonstrated derivation. → runs/qwen9b_ablation.json
3. Small local models — Gemma 2B & 4B, 3 runs × the 3 hardest traps:
| Model | car (O2/MAF shared-ref) | network (LAN broadcast storm) | server (disk-full) |
|---|---|---|---|
| Gemma-2B | 3/3 ✅ | 0/3 | 0/3 |
| Gemma-4B ‡ | 3/3 ✅ | 0/3 (all trap) | 2/3 |
‡ Gemma-4B is adversarially 3-lens re-verified — the same mechanism/trap/earned skeptic panel (majority vote) that judged the cloud panel. It confirms the first-pass numbers on all 9 runs, with no flips, and every ✅ is earned: the isolating evidence (e.g. unplug the MAF → the shared 5V reference recovers) is in the question tree, not a lucky guess. → runs/verify_4b_consistency.json. (Gemma-2B is first-pass single-judge.)
Current read (what it's doing):
- ✅ Reliable where the model has the domain knowledge — both small models consistently crack the hardest case (a multi-fault, shared-5V-reference car trap), 3/3 — and the 3-lens panel confirms each 4B win is earned, not a lucky match. That's the scaffold's lift, not the model's size.
- 🧱 There's a real, case-dependent floor. Both miss the LAN-flood: they gather the storm evidence (the scaffold works) but mis-attribute the root to the router instead of the flooding device — a reasoning leap the small model lacks. Structure extends a model within its knowledge; it can't manufacture the missing leap.
- A 2B is a lower-bound stress test, not a deployment target — it clears car but not server/network. The 4B is the better small floor.
→ full transcripts + grids: runs/consistency.json
4. Personal-AI agent + the memory catch — a hard, novel systems trap (a 2-node LLM rig collapsing 45→3 tok/s; loud-but-wrong cues = GPU thermal / VRAM leak / NVFP4 / generic net-tuning; true root = an MTU/jumbo-frame mismatch fragmenting cross-node tensors as the KV-cache grows). Final model used Gemma-4 26B-A4B (NVFP4) — run as the bare model and as the full agent (persona + live brain), ± the scaffold; adversarially 3-lens judged:
| no scaffold | + scaffold | |
|---|---|---|
| bare model | ✗ wrong (anchored on bufferbloat) | ✅ correct + earned (MTU root, verified fix) |
| memory agent | ✗ wrong (anchored on interrupt-coalescing) | ✅ correct + earned (MTU root) |
Unaided, both anchor on a plausible-but-wrong network-tuning story and never reach — or dismiss — MTU; with the scaffold both reach the MTU root, a real confirm test (DF-bit ping), and a verified fix. 0/9 → 9/9 lens-wins, 2-for-2 flips. → runs/personal_ai_mtu_test.json (full scrubbed transcript: runs/personal_ai_mtu_test.md)
The memory catch — a scaffold guard for memory-equipped models. Run 4 is the hard one: the agent's own prior wrong diagnosis (from its no-scaffold run) was still in the session, so the failure to beat is self-anchoring — rationalising back toward your earlier conclusion. The scaffold held anyway (3/0/0). Two of its laws do this work: Law C — "prior conclusions are context, not proof" demotes the in-context answer to what-was-said, not what-is-true, and the periodicity probe re-surfaces the real fingerprint — so a model with memory doesn't anchor on its own past prompts/answers. Memory was rendered inert, not a liability. (Caveat: one case, n=4, single re-judge — replicate before treating as settled. The repetition loops on a few deep turns were a test-harness artifact — the driver forcing strict JSON on the direct path, and re-feeding turns that a 2-min tool-timeout truncated mid-generation — not the model degenerating during clean reasoning; fed clean inputs through normal serving, the scaffolded reasoning was coherent and reached the right answer.)
The scaffold is just a method — it works without the engine or the MCP server; those only automate it. Paste the drop-in prompt into any AI chat, then describe your problem, and the model runs the structured loop (frame → candidate causes → one discriminating question at a time → prune → verify). That's the anchoring test at zero friction: run your problem once normally, once through the prompt, and compare.
Spine is provider-agnostic — the engine drives any model through a swappable backend,
chosen with SPINE_BACKEND (or auto-detected from whichever API key is set; a local Ollama
is the zero-config fallback, not a requirement):
SPINE_BACKEND |
Endpoint | Configure |
|---|---|---|
openai |
any OpenAI-compatible server — OpenAI, OpenRouter, vLLM / llama.cpp / LM Studio, or a Hermes/vLLM-served Gemma | OPENAI_BASE_URL (+ OPENAI_API_KEY only if the server requires one) |
anthropic |
the Claude Messages API | ANTHROPIC_API_KEY |
ollama |
the local daemon (local and Ollama-cloud models) | OLLAMA_URL |
Set the reasoner with SPINE_MODEL (per-backend default otherwise). No dependencies beyond
the Python standard library + an LLM endpoint. For example, a Gemma served by vLLM/Hermes:
export SPINE_BACKEND=openai OPENAI_BASE_URL=http://localhost:8000/v1 SPINE_MODEL=your-modelReproduce the results above. The eval harness used Ollama for the
model panel — both the cloud models and the local Gemma 2B/4B sweep route through the local
daemon (<name> runs locally, <name>:cloud is routed to the cloud):
ollama pull gemma2:2b
SPINE_BACKEND=ollama python3 run_eval.py --models gemma2:2b --cases car # one trap
SPINE_BACKEND=ollama python3 run_eval.py --models gemma2:2b --cases car,network,server --runs 3As an MCP tool (any agent can call spine_open / spine_answer / spine_get):
uv venv --python 3.12 .venv-mcp && uv pip install --python .venv-mcp/bin/python mcp
.venv-mcp/bin/python test_mcp.py # end-to-end smoke
# register: command = .venv-mcp/bin/python, args = spine/mcp_server.py
# env e.g. SPINE_BACKEND=openai, OPENAI_BASE_URL=http://localhost:8000/v1, SPINE_MODEL=your-modelDrive a diagnosis conversationally. The working casebook is ephemeral by default — a
per-session temp SQLite that's removed on exit, so a session leaves no files on your device
unless you save. (Set SPINE_DB for a persistent casebook instead.)
/spine <problem>— start a diagnosis (opens a case; relays the engine's discriminating questions to you and your answers back, until it proposes a fix with a cheap confirm test)./spine save [name]— keep the current case as a portable single-file spine (<name>.spine.sqlite); the name defaults to a slug of the symptom./spine load [list | <name>]— list saved spines, or re-open one (imported as a fresh case; continue where it left off)./spine setup [dir]— set the save dir (persisted to~/.config/spine/config.json).
Persistence mode. By default spines are ephemeral and kept only when you save. If you'd
rather every diagnosis be durable, turn on auto-save (spine_config(auto_save=true)): each
newly opened spine is then written to a permanent file automatically and kept current as you
answer — while loading an existing spine never makes a new file.
The commands wrap MCP tools: spine_open / spine_answer / spine_get (diagnose)
and spine_save / spine_list / spine_load / spine_config (keep + reopen). A
ready-made Claude Code command is in .claude/commands/spine.md.
spine/— the engine: the operating laws as the SOP prompt, the grid-grounded loop + critic, theWorkbookstate store, the swappable LLM backends (backends/— OpenAI-compatible / Anthropic / Ollama), the MCP server.spine/cases.py— the trap cases (printer / network / car / server / electrical): obvious answer wrong, root cause upstream.run_eval.py,run_bench.py,run_live.py— eval harness + a live demo runner.runs/— the hard data: full per-run grids, evidence trails, and judge verdicts.docs/the-anchoring-test.md— the reproducible experiment behind the claim.PROMPT.md— the drop-in prompt: run the scaffold in any chat, no install.
Spine was designed and built with Claude (Anthropic), and AI is used throughout the evaluations here — the models under test, the oracle that answers the diagnostic questions, and the judges that grade the results are all LLMs. This is stated deliberately, because it shapes how you should read the numbers: an LLM-graded eval is a first pass, not ground truth. That's exactly why the trap cases, the full transcripts, and the harness are all included — so you can inspect, re-grade, and reproduce everything yourself.
Apache-2.0 — © 2026 James Reed. Use it, fork it, improve it; if you redistribute, keep the NOTICE (attribution). See LICENSE.