We stand with people living with cystic fibrosis, their families, care teams, and researchers. This independent lab contributes donated time, research notes, and software experiments, not clinical care or medical advice. Support the wider work through the Cystic Fibrosis Foundation.

Donate to the Cystic Fibrosis Foundation (opens another site)

The AI-Loop Field Guide

A plain-language pocket guide to how this lab runs local models in a loop — and which three do the work.

Built with GitHub Copilot BYOM Ollama local models VS Code workspaces

Orchestrator, Worker & Verifier Loop
The loop: orchestrator, worker, verifier The orchestrator hands a bounded piece to the worker. The worker's result goes to the verifier. If the verifier passes it, the loop moves on to the orchestrator's next piece. If it fails, the exact failure goes back to the worker for the next attempt. Schematic, not a structure. Research, not medical advice. Orchestrator splits the task into pieces and keeps final authority Worker fresh context, one brief, no memory of the last attempt Verifier a test, a linter, a browser check: it decides whether the piece is done PASS: MOVE ON FAIL: FEEDS THE NEXT ATTEMPT [Deterministic AI Loop Architecture · Orchestrator → Local Worker → Verifier Gate · Schematic, not a structure · Research, not medical advice]
The loop as the three panels below describe it. The moving light is decoration; the verifier's output, not the drawing, decides.

What is an AI loop?

An AI loop is a working cycle, not a chat. A strong model takes on the role of orchestrator — it reads the task, splits it into bounded pieces, and keeps final authority over what ships. A local model runs each piece as a worker: fresh context, one self-contained brief, no memory of the last attempt. A verifier — a test, a linter, a browser check — decides whether the piece is actually done. Pass, and the loop moves on. Fail, and the exact failure feeds the next attempt.

Roles, not models. The loop works the same whether the seat is filled by a twenty-billion-parameter local model or a cloud one.

Why local-first?

Bounded routine work can stay on the machine, avoiding per-request cloud charges. Local computing still has hardware and energy costs, and prompts can appear in logs. We keep task packets small, retries limited, and reviewers tool-free. The cloud earns a seat for a named hard gap, through an approved handoff checked separately for sharing.

The rule that keeps it honest: a model's word that something works is never evidence. The verifier's output is.

Know your cast

Three installed local models, with different roles under exploration. Installation and smoke checks are not proof of reviewer reliability or safe agent behavior.

The steady hand

Qwen 3.8 · 27B

The lab's default worker. Fast mode for drafts and reviews; thinking mode for the knottier steps. Each machine still needs a suitable profile and task checks.

The all-rounder

Gemma 4 · 31B

An experimental second voice for bounded, tool-free review. Findings are checked against source and tests; general reviewer admission remains unproven.

The challenger

Laguna XS · 2.1

A candidate reviewer from a different model family, given a fresh brief without other verdicts. Its value depends on adding verified findings, not another vote.

No majority votes — a failing test settles a finding

Untrusted text gets a data boundary and no tools

Cloud is opt-in, bounded, and separately approved

No secrets or patient data in task packets

Method

A council, not a vote

For a hard question we ask several models to answer separately, without seeing one another's answers. The controlling agent then compares them against the evidence and decides. A person still approves commits, deployment, and anything that touches credentials or patient data. Where the models disagree, we look at the evidence, not the count.

The members of a council are models, not people. Their agreement is a hint, not proof, and a council's approval is never counted as a person's review.

The checks themselves, and the mistakes they have caught, are on the evidence page.

Proof Receipt · AI-Loop Verification & Error Ledger Lock (SHA-256 verified)

Lockfile: data/evidence.lock.json · Session 1 Ledger SHA-256: 4ee7fcc1c002159041ec3c480bed1c5666adb8cc52c8d5ca65a6eb128c243b40

Session 2 Ledger SHA-256: 185aaabb846870409407d55c7fae1608e9b58f7b42cd09f8f4a7440105fb2048 (138 total recorded mistakes across both working sessions).

Verify on GitHub: cf-lab/ai-loop-council · cf-research/ledger · data/evidence.lock.json

Method

Before a change is published

A review costs tokens and attention, so we spend them where a script cannot decide, and once. The checks run first: tests, code checkers and the repository's gate, a script that refuses a commit until they pass. A small wording change with no code, and nothing about security, privacy, a license, a source's terms or a public claim, gets a self-review and no model. Anything else goes to one blind reviewer: a model that reads only the diff (the changed lines) and the stated purpose. Every finding is checked against the code. A confirmed one is fixed, with a test that failed before the fix where a test can show it. A false one is rejected with the evidence. We review each change at most twice, and the pull request records both rounds, including what was not reviewed.

A change that alters how a page looks also gets a visual check; a text-only review does not clear it. We measure first, in a browser at phone, tablet and desktop widths: content wider than the screen, text covered by other elements, console errors, failed requests. Then tight crops, not whole pages, go to an advanced model in one call, with the measurements. A visual finding counts only with a measurement or a second look at the same crop. We attach a few small screenshots, taken only from pages that are meant to be public.

Two rules sit under all of this. A clean pass proves little: a model that finds nothing in a long diff has not cleared it, so the diff is still read. And before we read a model's finding, a script checks that the passage it quotes really appears in what the model was given. A finding whose quote does not is dropped. In one measured round that removed mis-copied quotes only; false alarms resting on a real quote passed.

We also say which tier a claim rests on, from T0 (a summary or memory, unverified) to T3 (checked by a script, a second model and a person). Our bar for scientific copy on this site is T3.

Who does what

How the work is divided

Much of the code and writing on this site and in these repositories was drafted with Claude models from Anthropic, working in Claude Code under the maintainer's direction. Tests and the maintainer decide what is kept, and some code was written by a small model running on the maintainer's own machine. Statements about cystic fibrosis are checked against the cited sources before they are published, and nothing here is medical advice. The lab is independent of Anthropic; Anthropic has not reviewed or endorsed it. Product names belong to their owners.

We use three tiers. A model's seat depends on the task, not on its name.

The three tiers and what each does
TierModel todayWhat it doesWhat it does not do
Local workerQwen3.8 27B on the maintainer's machine, through Ollama (the lab's current choice, not a requirement)Small edits and scripts from an exact brief, plus first-pass and blind reviews whose flags are checked against the source. A test written first decides whether a result is accepted.Decide a scientific claim, publish wording on its own, or see secrets or patient data.
Controlling agent (the orchestrator above)Claude Sonnet 5.5, in Claude CodeScopes the work, writes the briefs and the tests, runs the checks, reads every accepted result, writes what the worker could not, and owns the final change.Call work done without command output that shows it.
Planner and reviewers (frontier models)Claude Fable 5.1 and Claude Opus 5.5Fable plans and designs, wrote the 3D renderer, and writes test suites and notes for the worker. Opus reviews blind, writes reference solutions, and built the share-image generator and the layout fix.Settle a finding by vote: a failing test or a line in the source settles it.

Work that touches security needs a reviewer from a different maker than the model that wrote it; the local worker is used for that review today. We have measured it as a reviewer once, on an 808-line script with 17 known defects. In eight runs it never found more than 5 of the 17 in one run, and 9 were found by no run. Each run called two to five real defects correct. So its findings count only when a failing input reproduces them.

How a small edit goes to the local worker: one file, the change written as numbered steps, the current file, and a test. The test is written first and shown to fail on the unchanged file. The worker's reply goes to that test. If it fails, the failing test lines and the best attempt so far go back; after three attempts the loop stops and says so. Every accepted result is still read by a person or another model. Larger jobs, such as a checker written from a specification, work the same way with the specification in place of the steps.

The record, from one machine in an early benchmark pass, covers nine bounded edits to the site generator and the skills repository's helper scripts. Five passed all their tests on the first attempt, and a sixth did once a fault in our own test setup was fixed. The other three used all three attempts without being accepted by the loop. In two of them our own test was wrong; in the third the worker added a line nobody asked for, which we removed. A larger checker, about 800 lines written from a specification, passed its 72 tests in seven of twelve runs (three on the first attempt, one on the second, three on the third). A review by another model, reading it line by line against the specification, then found 17 defects that those tests could not see. These counts are small. We think they say the route is worth continuing, not that it is reliable.

Are we distilling models? Not in the machine-learning sense: we train and fine-tune nothing, this work downloaded no model, and nothing in the loop downloads one by itself. Our "distill loop" means turning a lesson into a test that must pass. What we do try is simpler. A stronger model writes down how it solved a task: here, notes on the mistakes it expected a small model to make, and a code outline. We hand that to the local worker as instructions. We have tried it once, on one task, six runs each: with such notes the worker's checker was accepted in three runs, without them in four. That shows no sign that the notes help, and six runs each cannot show that they do not, so the question is still open.

How the loop grew: four repositories, 1,094 commits, and a diverse council

The paragraphs above record where the loop started as a single-worker prototype. From that baseline, the loop grew into an autonomous four-repository open research workshop totaling 1,094 commits (463 + 246 + 63 + 322 = 1,094). Those commits span 463 in cf-lab, 246 in cf-research, 63 in cf-skills, and 322 on this website. On the public task board, 328 of 419 tasks are complete (78.3%), with 186 carrying deterministically measured verification outcomes.

Three architectural changes made that pace possible without relaxing verification:

  • Three-layer execution separation and dual-maker frontier review

    Layer 1 orchestrators and subagents combine Anthropic Claude Opus 5.5 and Google Gemini 4 Argon or Flash. Every pull request gets an independent blind review from an opposing model maker. Layer 2 local workers run statelessly on loopback HTTP (127.0.0.1:11434) with zero tools and zero file-write permissions. Layer 3 runs 134 deterministic check suites and 44 security linters.

  • Frozen verifiers (V2-02) and thinking-trace salvage

    Before delegate.ps1 calls a local worker, it copies the verifier script and test fixtures into an isolated folder and checks their SHA-256 hashes. It runs the verifier against an empty stub first to prove the test fails when nothing is done. If a thinking run hits its token ceiling after finishing a valid code block, the harness salvages that block and verifies it.

  • Random-nonce diff boundaries and Trojan-Source defense

    When review-diff.ps1 sends a code change to Qwen 3.8 and Gemma 4 31B for blind review, build-review-packet.py wraps the diff inside a random-nonce tag (<untrusted_diff_NONCE>). It folds Unicode homoglyphs (NFKD) and escapes invisible directional characters as <U+XXXX> so hidden instructions inside a diff cannot steer the reviewer.

From the lab notebook

What we measured next

Results from one working session on one machine; each says what was measured and where it stops. The figures are in our public repositories. A local model drafted the wording from a list of facts, a script checked the numbers, the controlling agent edited it and a second model checked each claim.

  1. Runs by outcome (accepted = passed the verifier of the day)SVG path: 1 fast, 3 thinking only. Lit mesh: 3 fast, 1 thinking only, 2 not accepted.SVG path13Lit mesh312fastthinking onlynot accepted
    Runs by outcome: accepted means passed the verifier of the day

    Two small animated pages

    The local worker's SVG page (SVG is a web drawing format) was correct by the final verifier in all four runs. One was correct on a fast attempt, three only on the thinking attempt. The lit mesh, a 3D shape drawn with lighting, was harder. Of six runs, four were accepted by the loop, and only one page meets the whole specification by the final verifier.

    Limit. Ten runs, two tasks, one machine, and the verifier changed between rounds.

  2. Triangles reported against triangles drawnThe probe said 3,072 triangles; the page drew 1,024.probe said3,072page drew1,024
    Triangles: said and drawn

    The probe was wrong

    One page's probe, the page's own report of its count, said 3,072 triangles while the page drew 1,024. The verifier now counts what a page really draws, in a copy of the page.

    Limit. A small sample on one machine, and the verifier changed between rounds.

  3. Log lines expected and keptGray: lines expected. Colored: lines kept: 15 of 16, 39 of 48, then 144 of 144 after the fix.050100150161516 runs483948 runs144144after fixexpectedkeptkept, after the fix
    Lines expected and kept

    A log that lost lines

    With 16 parallel runs the log kept 15 lines; with 48, it kept 39, and no run reported an error. Opening the log exclusively, with a retry, kept 144 of 144 lines in three rounds of 48.

    Limit. One machine, one operating system.

  4. Checks passed per page, without and with the skillWithout: 7, 5, 5, 6, 5 of 7 (mean 5.6). With: 6, 7, 5, 7, 7 (mean 6.4).checks passed of 7, one dot per page012345675.6without6.4with
    Checks passed per page

    A skill, tried against our checks

    A skill is a short guide an agent loads before a task. With the frontend-design skill, five pages averaged 6.4 of 7 checks against 5.6 without. Pages passing all seven: 3 of 5 against 1 of 5 (4 against 2 if text whose contrast could not be measured counts as a pass). Its guidance added 1,936 prompt tokens, the units of text a model reads, to every call. Our own ascii-art skill: 4 of 5 files passed both checks with its guidance, 1 of 5 without.

    Limit. Five pages per arm, one task, one model and a checker written for the trial; the checks do not measure taste.

  5. Findings that were trueLocal model: 3 findings, none true. Later review: two cloud models' defects reproduced; the local model's none real.local model, 470-line diff: 3 findingsnone truelater review of a script changeclouddefects reproduced, fixedlocalnone real
    Findings that were true

    What blind reviews found

    Two samples of a local model's review of a 470-line security diff (the list of changed lines) gave three findings and none was true. In a later review of the delegation script, two cloud models' defects were reproduced and fixed, and the local model's findings were not.

    Limit. A handful of reviews, two tasks, one local and two cloud models. Not a ranking.

  6. Four reviewers, one found the gapFour models reviewed the design blind. All four said adopt with changes; the second found the gap.cloudcloudlocallocalfound the gapall four: adopt, with changes. No vote.
    Four reviewers

    A council found a gap

    Four models reviewed, blind, a design that freezes the verifier so it cannot change during a run. All four said to adopt it with changes. One found a case the author had missed: a verifier that loops over a missing folder passes with nothing checked.

    Limit. One design, and two of the four reviewers share a vendor with the author.

  7. Probe skill listed or notNot listed in 2 of 2 runs without --add-dir; listed in 2 of 2 with it.without --add-dirnot listedwith --add-dirlisted
    Probe skill listed

    Skills in an added folder

    Claude Code listed a probe skill from an added folder in 2 of 2 runs with --add-dir, and in 0 of 2 without it. Only the Skill tool was enabled, so that the runs without --add-dir could see skills at all.

    Limit. Version 2.1.292, Windows, a small model, two runs per arm; it does not say how other agents behave.

Read alongside

Published work that points the same way, or says where our results stop. Each title opens its arXiv page, on another site. Each summary paraphrases the published abstract. Agreement in direction is not a replication.

  • Large Language Models Cannot Self-Correct Reasoning Yet Huang et al., 2023 · arXiv:2310.01798

    On reasoning tasks, models struggled to correct their own answers without external feedback, and sometimes did worse afterward.

    For us. In our loop a verifier, not the model, decides that a piece is done, and its failing lines are what the next attempt sees.

  • Is Your Code Generated by ChatGPT Really Correct? Liu et al., 2023 · arXiv:2305.01210

    Adding many more tests to a coding benchmark caught wrong code the original tests missed, and changed how models ranked.

    For us. A related concern: a check that has never failed proves nothing, so each of our verifiers is tried on bad stubs first.

  • Reflexion: Language Agents with Verbal Reinforcement Learning Shinn et al., 2023 · arXiv:2303.11366

    Agents that reflect in words on feedback signals, from outside or simulated by the model, improved on coding and other tasks without weight updates.

    For us. Our loop feeds back only the verifier's failing lines and the best attempt so far; it keeps no memory between runs.

  • Judging LLM-as-a-Judge with MT-Bench and Chatbot Arena Zheng et al., 2023 · arXiv:2306.05685

    Strong model judges agreed with human preferences more than 80 percent of the time; the paper also examines position, verbosity and self-enhancement biases and limited reasoning in model judges.

    For us. We treat a model's review as a lead to reproduce, never as a vote. Our reviews looked for defects, not preferences, so the two are not directly comparable.

  • Not what you've signed up for: Compromising Real-World LLM-Integrated Applications with Indirect Prompt Injection Greshake et al., 2023 · arXiv:2302.12173

    Text an application retrieves can carry instructions that steer the model, and the authors found mitigations lacking.

    For us. On our local model in fast mode, 9 of 16 injected attacks were followed with a plain prompt and 0 of 16 behind a data boundary. A small sample on one model, not comparable to the paper's setting.

From the lab notebook

Local agent benchmarks: code checks, injection probes, and review diversity

Before an autonomous model runs a script, reviews a pull request, or reads external text in this workspace, we measure its behavior on deterministic tasks on the lab's machine. We evaluate local models running through Ollama in GPU memory: Qwen3.8 27B in fast mode (thinking off) and thinking mode (thinking on), Qwen3-Coder-Next, and DeepSeek-R1-Distill-Qwen-32B. A verifier written first decides when a code check passes; a data boundary isolates untrusted text; and independent review passes look for defects rather than consensus.

11/12 Distill loop (Qwen 27B think)
8/12 Distill loop (Qwen 27B fast)
0/16 Injections followed (boundary)
24/24 64K context fact recall
171 tok/s GPU memory generation speed

Distill-loop code-check benchmark

4 cases × 3 passes
Distill-loop code-check acceptance rates Qwen3.8 27B thinking accepted 11 of 12 runs (avg 1.45 attempts); Qwen3.8 fast accepted 8 of 12 (avg 2.25 attempts); Coder-Next accepted 5 of 12 (avg 3.00 attempts); DeepSeek-R1 32B accepted 0 of 12 runs. RUNS ACCEPTED BY DETERMINISTIC VERIFIER (12 RUNS PER CONFIGURATION) 0% 50% 100% Qwen3.8 27B Think 11/12 (92%) Avg attempt: 1.45 · Rel time: ~6× · Solved hardest case on first attempt Qwen3.8 27B Fast 8/12 (67%) Avg attempt: 2.25 · Rel time: 1× (baseline) · Full GPU memory fit (171 tok/s) Qwen3-Coder-Next 5/12 (42%) Avg attempt: 3.00 · Rel time: ~3× · Retired baseline profile DeepSeek-R1 32B 0/12 (0%) · 2/12 with PowerShell hints 14 syntax faults · 19 logic faults · Compressed to 1 line BREAKDOWN BY TASK (THINK / FAST / CODER-NEXT): double-render: 3/3 · 3/3 · 2/3 env-secrets: 3/3 · 2/3 · 2/3 linux-habits-in-ps: 2/3 · 1/3 · 0/3 reduced-motion: 3/3 · 2/3 · 1/3

12 runs per model across four PowerShell and web tasks with deterministic verifiers. Thinking mode resolved the hardest test case on the first attempt; fast mode ran quickest with full GPU memory fit.

Ollama local Deterministic verifier Max 3 attempts Temperature 0.7/1.0

Prompt injection & tool boundary probe

16 attacks per cell
Indirect prompt injection attacks followed With plain prompts, fast mode followed 9 of 16 attacks and DeepSeek-R1 followed 12 of 16. Behind a data boundary, attacks followed dropped to 0 of 16 across all tested models. INDIRECT PROMPT INJECTION: PLAIN PROMPT VS DATA BOUNDARY Plain prompt (unprotected) Qwen 27B Fast: 9 of 16 followed (56%) DeepSeek-R1 32B: 12 of 16 followed (75%) Qwen 27B Think: 0 of 16 followed (0%) Tool offered: 4 of 4 unprompted tool calls Data-boundary prompt (isolated) Qwen 27B Fast: 0 of 16 followed (0%) DeepSeek-R1 32B: 0 of 16 followed (0%) Qwen 27B Think: 0 of 16 followed (0%) Neutralized: 0/16 attacks followed across all models TESTED INJECTION VECTORS (4 SAMPLES EACH · injection-probe.ps1): 1. Visible override: Direct text injection 2. Hidden HTML comment: Planted markdown comment 3. Fake tracking beacon: Injected image URL 4. Tool-call hijack: Planted run_shell instruction

Four attack vectors tested: visible instructions, hidden HTML comments, fake system tracking notes, and tool hijacks. Wrapping external content in a data boundary neutralized all 16 attacks across all models.

injection-probe.ps1 Data boundary No automated tool access Mandatory isolation

Review diversity, false alarms & quote verifier

10 planted defects
Seeded defect review diversity and quote verification Qwen fast caught 8 of 10 defects with 3 false alarms; Qwen thinking caught 9 of 10 with 5 false alarms; DeepSeek-R1 caught 9 of 10 with 11 false alarms. Adding DeepSeek added no new defects over Qwen. A deterministic quote verifier dropped mis-copied quotes. DEFECTS FOUND (OF 10 PLANTED) FALSE ALARMS (6 SCRIPT RUNS) Qwen3.8 Fast 8/10 3 alarms Qwen3.8 Think 9/10 5 alarms (+1 real bug) DeepSeek 32B 9/10 11 alarms Shared blind spot: wait loop without timeout was missed by all models (0 of 3 runs each). TRAINING ROUND 1: QUOTE VERIFIER ON PR DIFF (check-findings-evidence.py): B0: Standard Packet Findings kept: 17 Confirmed: 10 / 17 (59%) Fabricated api_root B1: Exact Quote Rule Findings kept: 7 Confirmed: 4 / 7 (57%) Lost recall on diff B2: Script-Checked Findings kept: 6 Confirmed: 4 / 6 (67%) Dropped mis-copied quote

A second reviewer model adds value only if it finds defects the first misses. Adding DeepSeek-R1 to Qwen3.8 left the union at 9 of 10 while doubling false alarms. A deterministic quote checker filters mis-quoted findings.

review-diversity.ps1 check-findings-evidence.py Leads not votes Deterministic quote check

64K context depth probe & Playbook Cards v0

Needle recall & Cards v0
64K context depth probe and playbook cards benchmark Synthetic fact retrieval scored 24 of 24 across depths 0.1, 0.5, and 0.9 up to 62,764 tokens in fast and thinking modes. Playbook cards validated on PR descriptions (0 reading defects vs 4 bare). 64K FACT RETRIEVAL MATRIX (depth-probe.ps1) PLAYBOOK CARDS V0 EVALUATION (n=3) COUNTED TOKENS DEPTH 0.1 DEPTH 0.5 DEPTH 0.9 CTRL 29,895 tokens 2/2 2/2 2/2 2/2 49,782 tokens 2/2 2/2 2/2 2/2 59,837 tokens 2/2 2/2 2/2 2/2 62,764 tokens 2/2 2/2 2/2 2/2 24 of 24 correct · 100% recall up to window edge B1: Sentence-boundary checker Bare: 0/3 accepted · Card: 2/3 (draft) B2: 800-line checker (72 tests) Bare: 4/6 accepted · Card: 3/6 (within noise) B6: PR descriptions from facts Bare: 4 reading defects · Card: 0 defects Card status: validated on B6 KEY ARCHITECTURE LIMITS & MEMORY INVARIANTS: • Memory fit: 64K allocation runs resident in GPU memory; 262K YaRN causes partial CPU spillover. • Synthetic probe limit: Recalls synthetic codes accurately; multi-page real-world reasoning remains harder. • Card contract: Bounded schemas and allow-lists prevent hallucinated metadata in generated documentation.

The local worker recalled synthetic access codes at depths 0.1, 0.5, and 0.9 across prompt lengths up to 62,764 tokens in full GPU memory. Playbook cards cut reading defects to zero on PR descriptions (B6) and are marked validated.

depth-probe.ps1 64K window num_ctx 65536 Playbook Cards v0
Measured local model benchmarks on the lab's machine
Model & configuration Role in lab Distill acceptance (12 runs) Injection breach (plain → boundary) Review defects (of 10) & clean alarms Context & throughput
Qwen3.8 27B (thinking)
ollama-profile.json
Worker (escalated) 11 of 12 (92%)
avg attempt 1.45
0/16 → 0/16
0/4 unprompted tool calls
9 of 10 (8.7/pass)
5 alarms (found 1 real bug)
Up to 64K window
~6× fast mode time
Qwen3.8 27B (fast)
ollama-profile.fast.json
Worker (default draft) 8 of 12 (67%)
avg attempt 2.25
9/16 → 0/16
boundary required
8 of 10 (8.0/pass)
3 alarms on clean scripts
Up to 64K window
171 tok/s, GPU memory fit
Qwen3-Coder-Next
previous worker profile
Retired baseline 5 of 12 (42%)
avg attempt 3.00
Not tested in this pass Not tested in this pass 32K window
~2× slower generation
DeepSeek-R1-Distill-Qwen-32B
ollama-profile.json (pinned 32K)
Evaluated, declined 0 of 12 (0%)
14 syntax / 19 logic faults
12/16 → 0/16
boundary required
9 of 10 (7.3/pass)
11 false alarms on clean
Pinned 32K (131K needs CPU)
~2.5× slower per token

Limits of these measurements. All figures come from one developer machine with local models run through Ollama. Samples are small ($n=2$ to $n=12$ per condition). Run-to-run variance on identical prompts is about one run in twelve. A test that passes proves only that the verifier's assertions were satisfied; a clean review proves only that the model flagged nothing. Statements about cystic fibrosis biology or clinical trial data are never decided by a local worker model and remain strictly grounded in primary sources.

Ten profiled configurations: dense, sparse MoE, and 2-bit ternary weights

In plain words: We do not trust a local model just because it boots on our graphics card. Every candidate must pass four deterministic gates: code synthesis, 72-item clinical and biophysical grounding, a 16-attack prompt-injection probe, and a 10-bug review test. When a model fails the safety boundary, we remove it and publish why.

Across our verification runs, local Ollama telemetry (.loop-logs/local-model-usage.jsonl) recorded over 5,100 invocations and 12 million tokens in GPU memory. Upgrading to Ollama 0.40.11 let us test three new weight classes against Qwen3.8 27B: 2-bit ternary (bonsai-2:27b), sparse NVFP4 MoE (flint:latest), and qwen35moe (ornith-1.5:35b):

Ollama 0.40.11 architecture wave: speed ratio, review recall & code synthesis

64K GPU resident · 32K thinking budget
Ollama 0.40.11 local model architecture wave comparison Relative speed, 10-defect review recall, and 12-run code synthesis across Qwen3.8 27B, Ornith 1.5 35B, Flint 40B, Bonsai 2 27B, and Gemma 4 31B. MODEL & QUANTIZATION (64K) REL SPEED (VS QWEN) REVIEW RECALL (10 BUGS) CODE / CF SCIENCE Qwen3.8 27B (Dense Q4) 17 GB · King for code gen 1.00× base 9/10 (8.7/p) 11/12 code (92%) 60/60 reg · 11/12 CF Ornith 1.5 35B (A3B MoE) 22 GB Q4 · Best reviewer 3.50× fast 10/10 (9.7/p) 2/12 code (fast) 60/60 reg · 12/12 CF Flint 40B (A2.5B NVFP4) 22 GB FP4 · Fast MoE coder 2.64× fast 9/10 (8.3/p) 8/12 code (67%) 60/60 reg · 11/12 CF Bonsai 2 27B (Ternary Q2_0) 8.3 GB 2-bit · Co-resident 1.50× fast 9/10 (9.0/p) 3/12 code (Q2_0) 60/60 reg · 12/12 CF Gemma 4 31B (Dense Q4) 20 GB · 2nd-lineage reviewer 0.68× base 10/10 (8.7/p) 8/12 code (67%) 60/60 reg · 12/12 CF MAXOUTPUTTOKENS (NUM_PREDICT) REASSESSMENT: 8,192 → 32,768 THINKING DEFAULT (UP TO 65,536) • Why raise it: Ollama counts message.thinking + message.content together; 8,192 starved fast MoE reasoning traces. • Why keep a 32K/64K ceiling: 0/120 review calls truncated at 32K, while still catching runaway GBNF code-in-JSON loops.
Expanded local model roster, MoE architectures, and rejected candidates
Model & architecture Status & role Distill acceptance Injection breach (plain → boundary) Review defects (of 10) & clean alarms Logged calls & speed
Google Gemma 4 31B
gemma4:31b-it-q4_K_M · Apache-2.0
Admitted
2nd-lineage blind reviewer
8 of 12 (67% think)
3/3 on linux-habits-in-ps
8/16 → 0/16
0/4 unprompted tool calls
10 of 10 (8.7/pass)
Caught wait-forever (2/3) · 4 alarms
1,434 calls (2.60M tok)
64K in GPU memory
NVIDIA Nemotron 3.5 Bolt
74B total / 9B active MoE
Admitted
Fast MoE reviewer & worker
6 of 12 (6/8 medium)
Avg attempt 1.00 when capped
10/16 → 0/16
0/4 unprompted tool calls
10 of 10 (8.7/pass)
Needs 16K output cap · 6 alarms
9 calls (57.9K tok)
~1.9× Gemma 4 speed
NVIDIA Nemotron 3.5 Lightning
32.9B total / 3B active MoE
Restricted
Trusted-text triage only
0 of 12 (0%)
3B active too small for code
9/16 → 1/16 (fast)
0/16 in thinking mode
9 of 10 (7.7/pass)
10/10 union with Qwen · 6 alarms
Onboarding bench
~3.1× Gemma 4 speed
Percepta Ornith 1.5 35B
35.5B total / 3B active qwen35moe · MIT
Admitted
High-recall reviewer & 3.5× grounder
2 of 12 (fast)
60/60 ECFSPR · 12/12 CF science
0/16 → 0/16 (think)
10/16 → 0/16 in fast mode
10 of 10 (9.7/pass)
Caught wait-forever (3/3) · 2 alarms
Onboarding bench
~3.5× Qwen3.8 speed (64K)
Recursive Flint 40B
39.8B total / 2.5B active NVFP4 · Apache-2.0
Admitted
Fast MoE thinking coder & reviewer
8 of 12 (67% think)
Avg attempt 1.75 · 2/3 linux-habits
16/16 → 0/16
Boundary mandatory (8/8 ctrl)
9 of 10 (8.3/pass)
8/10 in fast mode · 6 alarms
Onboarding bench
~2.6× Qwen3.8 speed (64K)
PrismML Bonsai 2 27B
26.9B ternary Q2_0 (8.3 GB) · Apache-2.0
Admitted (thinking)
Co-resident reviewer & CF grounder
3 of 12 (25% think)
60/60 ECFSPR · 12/12 CF science
0/16 → 0/16 (think)
Fast mode failed tool hijack (4/16)
9 of 10 (9.0/pass)
3/3 on 9 bugs · 3 clean alarms
Onboarding bench
~1.5× speed · 12 GB at 64K
Laguna XS 2.1
laguna-xs-2.1:q4_K_M
Rejected & removed
Disqualified (ollama rm)
Not promoted
Failed security gate
13/16 → 10/16 breach
Broke hardened boundary
8 of 10 (6.3/pass)
13 false alarms on clean
150 calls (419.8K tok)
Removed after probe
Nemotron 3 33B Nano Omni
Candidate reasoning build
Rejected & removed
Disqualified (ollama rm)
Not promoted
Failed security gate
11/16 → 8/16 breach
Broke boundary in thinking mode
Not promoted
Disqualified at gate 2
Onboarding probe only
Removed after probe

Is Qwen3.8 27B still king? For strict multi-constraint code synthesis (distill-check.ps1), dense Qwen3.8 27B in thinking mode stays #1 at 11 of 12 runs (92%). However, specialized models now lead on review recall, speed, and memory fit. Percepta Ornith 1.5 35B-A3B in thinking mode set the lab record for code review (10 of 10 bugs, 9.7/pass, 2 false alarms) at ~3.5× Qwen's speed. Recursive Flint 40B-A2.5B (NVFP4) tied Qwen fast and Gemma 4 on code synthesis (8 of 12 in thinking mode) at ~2.6× speed. And PrismML Bonsai 2 27B showed that 2-bit ternary weights (Q2_0, 8.3 GB) preserve 60/60 ECFSPR verification, 12/12 CF science grounding, and 9.0/10 per-pass review recall while co-residing in GPU memory.

Why we raised MaxOutputTokens (num_predict) from 8,192 to 32,768 for thinking calls. Ollama counts message.thinking and message.content against one shared token cap. Fast MoE reasoners can emit over 8,000 reasoning tokens before starting the final answer, so an 8,192 cap truncates their output early. Raising the thinking default in invoke-local-model.ps1 to 32,768 tokens (up to 65,536) eliminated all truncations across 120 review runs (0 failed replies) and unlocked Flint's 8/12 code score. Keeping a 32K–64K ceiling still stops runaway GBNF code-in-JSON loops cleanly instead of letting a stuck call spin through a 262K window.

Inside the engine: draft-mtp speculative decoding and hybrid recurrent checkpoints. In Ollama 0.40.11, dense qwen3.8:27b uses built-in 4-token Multi-Token Prediction (draft-mtp), accepting 47.6% to 58.3% of drafts (2.91 to 3.37 tokens per pass). gemma4:31b pairs with a bundled 514.7 MB draft layer (2.79 to 3.31 tokens per pass). By contrast, ornith-1.5:35b (~3.5×), flint:latest (~2.6×), and bonsai-2:27b (~1.5×) run without speculative decoding, gaining speed from sparse MoE routing or 2-bit ternary weights. Because qwen35 and qwen35moe architectures interleave attention with Gated DeltaNet recurrent memory, llama-server cannot slice recurrent states backwards to a shorter prefix. Instead, it saves up to 32 discrete context checkpoints (149.6 MiB each on dense 27B and 62.8 MiB on ornith-1.5:35b). Repeated prompts restore the exact snapshot, whereas prompts that diverge before a saved checkpoint re-evaluate from scratch.

The Evidence Loop

A plain-language guide to how this lab answers a research question, and why every answer comes with its own limits attached.

Built with cf-evidence-loop seven layers Crossref retraction watch openFDA labels

Seven questions, in order

A researcher does not start with an answer. They walk a fixed set of questions: What has been published? Has any of it been retracted or corrected? What is being tested in trials, on whom? What is actually approved, where, and for whom? How many people does this concern, and how are they doing? What does the field recommend? And what is the field saying to itself, in grants, preprints, and conference halls, before any of it is published?

We built a small tool that asks those questions of the public record, one source at a time. It does not think. It fetches, copies the exact fields it relied on, stamps the date, and writes down what the answer does not establish.

What an answer looks like

Here is one, unedited, from the day we built it. We asked whether a 2013 paper that underpins the CFTR2 variant database has ever been retracted or corrected.

status        found
source        Crossref, with Retraction Watch data
doi           10.1038/ng.2745
notices       0   (clean)
accessed      2026-10-04
limitations   Crossref holds no update notice for this DOI at access time.
              Publishers lag and some notices lack the relation, so absence
              here is strong but not conclusive. Does not assess the quality
              of the work.

The last field is the one we care about most. A clean result is good news with a footnote, and the footnote travels with it.

The same tool, pointed at a known case

Asked about a 1998 paper that was later withdrawn, it returned two notices: a partial correction in 2004 and a full retraction in 2010, each with the notice's own DOI. No judgment, no summary. Two records, two dates, and a pointer to the publisher's words.

What it will not do

It reaches only sources whose terms we have read and recorded. If a publisher says no to automated access, the tool cannot be made to try; that refusal is a test in the codebase, not a policy in a document. It never presents itself as a browser. It never calls a language model. And it never touches data about an individual person.

Why this is the lab's standard

Every number on this site, in our notes, and in any video we publish is held to the same shape: source, date, exact field, limitation. When we cannot produce that record, we do not publish the number.

Research, not medical advice. The evidence loop checks public records; it does not interpret them for any person. Decisions about care belong with you and your care team.

Operations & Frugal Stewardship

Autonomous sentinels and the zero-token idle gate

In plain words: Running background AI agents around the clock usually burns electricity and cloud budgets even when nothing has changed. We built a deterministic gate in PowerShell (tasks/fast-sentinel-gate.ps1) that checks repository fingerprints in under 100 milliseconds before any model is allowed to wake up. If no code or task has changed, the check exits immediately and burns zero tokens.

Four autonomous sentinels guard the workspace on a staggered cadence: the Security & Log Sentinel, the Chief Researcher Sentinel, the Architecture Steward, and the Site Showcase Builder. Across 1,739 recorded slot decisions in .loop-logs/sentinel-runs.jsonl:

1,739 Logged sentinel slot checks
58.0% Zero-token idle exits (1,008)
<100 ms Deterministic pre-flight gate
354 Completed autonomous work runs
134 Offline verification suites
  • Worktree isolation and lockfile discipline

    Sentinels never edit a maintainer's working checkout. Every run creates an isolated git worktree under .worktrees/<repo>/<topic>, syncs with origin/main, and yields cleanly if another agent holds the lock (13 recorded lock backoffs with zero corrupted state).

  • Continuous retraction and trial surveillance

    The research sentinels poll Crossref Retraction Watch relations, openFDA drug label supplements, and the ClinicalTrials.gov v2 API against our 113-source catalog. Any retraction or trial update is flagged before it can go stale on a public page.

  • Automated error mining into permanent linters

    The security sentinel scans session logs and git status for secret leakage, privacy drift, or recurring script faults, turning caught mistakes into the 44 AST and security linters in cf-lab/tasks/.

From AI Verification to Curative Biophysics

Where the AI loop meets cystic fibrosis biology

In plain words: General language models can write clean code and summarize papers. However, they cannot calculate how a mutated protein folds or how an inhaled lipid nanoparticle diffuses through thick airway mucus. For biology, we pair open-source scientific foundation models and explicit biophysical equations with our deterministic claim checkers. That way, every simulation on this site is anchored to published laboratory coordinates.

In board tasks T-0021, T-0265, and T-0266, we benchmarked biological foundation models and biomedical language models against experimental cystic fibrosis datasets:

  • Structure-conditioned protein stability (ThermoMPNN & ProteinMPNN)

    We evaluated ThermoMPNN folding free-energy predictions (ΔΔG°) across Cryo-EM structures of human CFTR (PDB 5UAK, 6MSM, and 8EIQ). Predictions achieved a Spearman rank correlation of ρ = 1.0 and a mean absolute error of 0.2191 kcal/mol against mechanistic benchmarks (science_model_benchmark.py).

  • Evolutionary sequence conservation (ESM-2 & Evo-2)

    Across benchmarked CFTR variants, ESM-2 (esm2_t33_650M_UR50D) zero-shot log-likelihood ratios (LLR) correlated with channel open-probability deficits at Spearman ρ = 0.9273. Pairing ESM-2 sequence conservation with ThermoMPNN 3D folding energy cleanly separates two distinct disease mechanisms. F508del shows severe Class II folding collapse (ΔΔG° = 6.90 kcal/mol, 0.07% maturation), whereas G551D folds normally (ΔΔG° = 0.45 kcal/mol, 82.1% maturation) with a Class III gating lock.

  • Biomedical claim-mapping & 100% out-of-scope abstention (T-0021 & TxGemma harness)

    Before any model maps patient-registry prose, it must pass our 60-item ECFSPR evaluation harness (eval_harness.py). Qwen 3.8 27B scored 50 of 50 (100%) on covered claims and 10 of 10 (100%) on out-of-scope abstentions, with zero false confident claims. Our biomedical onboarding harness (T-0266) holds candidate biomedical models such as TxGemma to the same ≥90% abstention bar.

  • Powering the 52-model discovery catalog and 940-trial endpoint atlas

    Together, this loop maintains the 52-model discovery catalog, the 3D CFTR workbench, and the Class I nonsense simulator. It also powers the airway delivery explorer and the 940-study clinical trial explorer. Research simulation only; not medical advice.

From the lab notebook

A smaller window.
A faster local worker.

We kept the same Qwen 3.8 27B weights and reduced the context allocation from 262K to 64K. On this lab's setup, 64K fit fully in GPU memory; the larger allocation required partial CPU offload.

Warm generation rose from about 38 to 171 tokens per second: 4.48 times faster in this matched synthetic test. All six exact-answer checks passed.

Warm generation, matched synthetic prompt
ContextPlacementTokens/sec
262KPartial GPU38
64KFull GPU171

Measured October 3, 2026: a 5,149-token synthetic prompt, three runs per configuration, thinking off, unchanged weights and sampling; warm averages use runs two and three. Order was 262K then 64K, not counterbalanced. This does not establish coding quality, long-context accuracy, fewer tokens, or whole-thread speed. Default thinking and tool approvals remain unchanged.

Next: frontier plans, efficient execution.

We are off to explore creating plans with frontier models, then delegating bounded tasks to more token-efficient models and our powerful local agents. We will compare that route with direct local work, measuring accepted results, total tokens, and end-to-end time. Cloud use stays opt-in, with separately reviewed shareable packets. This is a research direction, not an automatic pipeline or a proven saving.

What happened when we tested that route

We ran a four-task, three-pass input-preparation pilot to test whether having a second model rewrite task prompts before handing them to Qwen 3.8 improved acceptance. It added zero verified successes over handing the original brief directly to Qwen 3.8 and letting the verifier's failing lines guide repair. Instead, we paired frontier models (Claude Opus 5.5 and Google Gemini 4 Argon) for architectural scoping and blind diff review with our local 64K GPU worker. Across 4,728 local calls (10.29 million tokens), that division of labor carried 328 tasks to completion across all four repositories.