logitgate 0.2.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,1236 @@
1
+ Metadata-Version: 2.4
2
+ Name: logitgate
3
+ Version: 0.2.0
4
+ Summary: Fast, calibrated first-token logit evaluation and 3-layer cascaded routing for LLMs.
5
+ Author-email: Jason Bradley <jasonbdly@gmail.com>
6
+ License: Apache-2.0
7
+ Project-URL: Homepage, https://github.com/jasonbdly/LogitGate
8
+ Project-URL: Repository, https://github.com/jasonbdly/LogitGate
9
+ Project-URL: Mirror, https://gitlab.com/jasonbdly/logitgate
10
+ Keywords: llm,evaluation,logprobs,logits,calibration,cascaded-routing
11
+ Classifier: Development Status :: 4 - Beta
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: License :: OSI Approved :: Apache Software License
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Programming Language :: Python :: 3.10
16
+ Classifier: Programming Language :: Python :: 3.11
17
+ Classifier: Programming Language :: Python :: 3.12
18
+ Classifier: Programming Language :: Python :: 3.13
19
+ Classifier: Programming Language :: Python :: 3.14
20
+ Classifier: Programming Language :: Python :: 3.15
21
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
22
+ Requires-Python: >=3.10
23
+ Description-Content-Type: text/markdown
24
+ License-File: LICENSE
25
+ Requires-Dist: pydantic>=2.0.0
26
+ Requires-Dist: httpx>=0.23.0
27
+ Requires-Dist: typing-extensions>=4.0.0
28
+ Provides-Extra: openai
29
+ Requires-Dist: openai>=1.0.0; extra == "openai"
30
+ Provides-Extra: deepeval
31
+ Requires-Dist: deepeval>=1.0.0; extra == "deepeval"
32
+ Provides-Extra: langgraph
33
+ Requires-Dist: langgraph>=0.0.1; extra == "langgraph"
34
+ Provides-Extra: llamacpp
35
+ Requires-Dist: llama-cpp-python>=0.2.0; extra == "llamacpp"
36
+ Provides-Extra: recurrent
37
+ Requires-Dist: torch>=2.0.0; extra == "recurrent"
38
+ Requires-Dist: transformers>=4.40.0; extra == "recurrent"
39
+ Provides-Extra: pytest
40
+ Requires-Dist: pytest>=8.0.0; extra == "pytest"
41
+ Requires-Dist: pytest-asyncio>=0.23.0; extra == "pytest"
42
+ Provides-Extra: test
43
+ Requires-Dist: pytest>=8.0.0; extra == "test"
44
+ Requires-Dist: pytest-asyncio>=0.23.0; extra == "test"
45
+ Provides-Extra: all
46
+ Requires-Dist: openai>=1.0.0; extra == "all"
47
+ Requires-Dist: deepeval>=1.0.0; extra == "all"
48
+ Requires-Dist: langgraph>=0.0.1; extra == "all"
49
+ Requires-Dist: llama-cpp-python>=0.2.0; extra == "all"
50
+ Requires-Dist: torch>=2.0.0; extra == "all"
51
+ Requires-Dist: transformers>=4.40.0; extra == "all"
52
+ Requires-Dist: pytest>=8.0.0; extra == "all"
53
+ Requires-Dist: pytest-asyncio>=0.23.0; extra == "all"
54
+ Dynamic: license-file
55
+
56
+ # LogitGate (`logitgate`)
57
+
58
+ [![Release: v0.2.0](https://img.shields.io/badge/release-v0.2.0-blue.svg)](CHANGELOG.md)
59
+ [![License: Apache-2.0](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](LICENSE)
60
+ [![Python 3.10–3.15](https://img.shields.io/badge/python-3.10--3.15-blue.svg)](https://www.python.org/downloads/)
61
+ [![PEP 561 Typed](https://img.shields.io/badge/typing-PEP%20561-blueviolet.svg)](src/logitgate/py.typed)
62
+ [![Typechecked: mypy](https://img.shields.io/badge/typechecked-mypy-blue.svg)](pyproject.toml)
63
+ [![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff)
64
+ [![GitHub CI](https://github.com/jasonbdly/LogitGate/actions/workflows/ci.yml/badge.svg)](https://github.com/jasonbdly/LogitGate/actions/workflows/ci.yml)
65
+ [![GitLab CI](https://gitlab.com/jasonbdly/logitgate/badges/main/pipeline.svg)](https://gitlab.com/jasonbdly/logitgate/-/pipelines)
66
+
67
+ **Fast, calibrated first-token logit evaluation and 3-layer cascaded routing for LLMs.**
68
+
69
+ LogitGate replaces slow, multi-token LLM-as-a-judge critiques with calibrated first-token logit gates and a 3-layer cascaded routing pipeline (`ASTGate >> LogitGate >> JudgeGate`).
70
+
71
+ ---
72
+
73
+ ## How It Works in Plain English
74
+
75
+ When evaluating whether an LLM output meets a rubric, standard LLM-as-a-judge frameworks prompt another model to write a 200–500 word critique before outputting `PASS` or `FAIL`. This takes **5 to 20 seconds**, generates hundreds of Chain-of-Thought (CoT) tokens, and suffers from positional and label biases.
76
+
77
+ `LogitGate` uses a **3-layer cascade**:
78
+
79
+ 1. **Layer 0 (`ASTGate` / `ContractGate`)**: Runs deterministic checks in **<0.1 ms** on the CPU (Python AST syntax, JSON/Pydantic schemas, regex patterns, acyclic DAG topology, forbidden imports). If an artifact fails a deterministic contract, it fails immediately with no LLM call.
80
+ 2. **Layer 1 (`LogitGate`)**: If Layer 0 passes, we pass the rubric and candidate to the model and read its **first-token log-probabilities (`max_tokens=1`)**. In a single forward pass (**~36–41 ms on GPU**, **~173 ms on CPU**), we compute the model's classification confidence without generating multi-token CoT text. To cancel pretraining token priors (such as models favoring `'A'` over `'B'`), we run a second pass with swapped labels and average them in log-odds space (**~90–113 ms on GPU**).
81
+ 3. **Layer 2 (`JudgeGate`)**: Only when Layer 1 confidence falls into an ambiguous band (e.g., between 20% and 85%) or requires failure diagnostics does the pipeline escalate to generating a full text critique.
82
+
83
+ In our 24-item multi-domain benchmark suite (with `trigger="on_ambiguous_only"`), Layer 0 and Layer 1 resolved **95.8%–100.0% of items** (8.3% at Layer 0 in <0.1ms; 87.5%–91.7% at Layer 1 in 36–113ms) while reusing the already-loaded model, escalating only genuinely ambiguous cases (`4.2%` on `qwen2.5-coder:14b`) to Layer 2 (`JudgeGate`), as detailed in [Falsification Benchmarks](#falsification-benchmarks-where-does-layer-1-break-down--how-to-mitigate-it).
84
+
85
+ ---
86
+
87
+ ## Who Is LogitGate For? (3 Target Workflows)
88
+
89
+ 1. **CI/CD & LLM Evaluation Suites (`pytest` / DeepEval)**:
90
+ - Run hundreds of automated LLM evaluation checks in seconds during CI runs instead of waiting 15+ minutes for generative judges. Works completely offline with local models or deterministic stubs.
91
+ 2. **Multi-Agent & LangGraph Routers**:
92
+ - Conditional routing and decision branching in **36–91 ms** per node transition instead of waiting 2–3 seconds for an LLM supervisor agent to generate JSON routing text.
93
+ 3. **Local & Resource-Constrained LLM Deployments (Laptops, CPU-Only, Single GPU)**:
94
+ - Evaluates using your already-loaded generator model without requiring a second 14–48 GB judge model running in VRAM. Runs on 0-GPU laptops in pure CPU mode or 8 GB consumer GPUs.
95
+
96
+ ---
97
+
98
+ ## Why LogitGate?
99
+
100
+ Traditional LLM evaluation relies on generative judges (prompting an LLM to generate 100–500 critique tokens). This is **slow (1,500ms–8,000ms)**, **expensive**, and suffers from severe **position and label permutation biases**. Dedicated judge models (like Prometheus or Selene) require gigabytes of extra GPU VRAM and still suffer from high token generation latency.
101
+
102
+ | Evaluation Approach | Typical Latency | Generated Output Tokens | Extra GPU VRAM | Token & Positional Bias Mitigation | Ambiguity & Failure Diagnostics |
103
+ | :--- | :--- | :--- | :--- | :--- | :--- |
104
+ | **Generative LLM Judge** *(G-Eval, Ragas, MT-Bench)* | 1,500ms – 8,000ms | 100 – 600 CoT tokens | 0 GB (Shared) | ❌ None (or expensive 2x generative re-query) | ✅ Verbose text critique |
105
+ | **Fine-Tuned Judge Models** *(Prometheus 2, Selene)* | 800ms – 3,500ms | 80 – 300 CoT tokens | 14 GB – 48 GB (Dedicated weights) | ❌ Susceptible to length & positional bias | ✅ Fine-tuned rubric critique |
106
+ | **Naive Raw First-Token Logprobs** | 35ms – 250ms | 1 token (`max_tokens=1`, 0 CoT) | 0 GB (Shared) | ❌ Vulnerable to token prior bias (Zhao et al., 2021) | ❌ No diagnostic rationale |
107
+ | **`LogitGate` (3-Layer Cascade)** | **0.04ms (L0) / 36–113ms (L1)** | **0 (L0) / 1 token prefill probe (L1, 0 CoT)** | **0 GB (Reuses loaded model)** | **✅ Symmetric log-odds debiasing** | **✅ Escalates to Layer 2 Judge on failure / ambiguity** |
108
+
109
+ ---
110
+
111
+ ## Real Multi-Model Live Benchmarks
112
+
113
+ Empirical measurements gathered on local inference across 5 distinct model architectures running under Ollama (`v0.35.0`, `Q4_K_M` 4-bit GGUF quantization, `OLLAMA_FLASH_ATTENTION=1`, `OLLAMA_KV_CACHE_TYPE=q8_0`). All declarative benchmark datasets ([`benchmarks/data/`](benchmarks/data/)), the benchmark runner ([`benchmarks/run_benchmarks.py`](benchmarks/run_benchmarks.py)), and raw JSON outputs ([`benchmarks/latest_results.json`](benchmarks/latest_results.json)) are included in the repository for independent reproduction.
114
+
115
+ - **Testbed Hardware**:
116
+ - **CPU & System Memory**: AMD Ryzen 7 5800X3D (8-Core / 16-Thread), 64 GB DDR4 System RAM (used for all `Pure CPU-Only` benchmarks with `options={"num_gpu": 0}`).
117
+ - **GPU 1 (12 GB Sidecar Tier)**: NVIDIA GeForce RTX 4070 (12 GB GDDR6X VRAM) — used for `4B` (`gemma4:e4b`) and `14B` (`qwen2.5:14b`, `qwen2.5-coder:14b`) benchmarks.
118
+ - **GPU 0 (32 GB Primary Tier)**: NVIDIA GeForce RTX 5090 (32 GB GDDR7 VRAM) — used for `26B MoE` (`gemma4:26b`) and `31B Dense` (`gemma4:31b`) benchmarks.
119
+ - **Benchmark Methodology & Sample Protocol**:
120
+ - **Multi-Sample Latency Protocol ($N=5$)**: Every latency configuration is preceded by `1` untimed warm-up pass (to load GGUF weights into memory and initialize KV-cache buffers), followed by `N=5` sequential timed trials over a persistent HTTP connection pool (`httpx.Client`), reporting `mean ± std` in milliseconds.
121
+ - **Leak-Free Matched Datasets**: All test items in [`benchmarks/data/`](benchmarks/data/) are stripped of meta-comments and structured as matched pass/fail pairs across 4 domains (24 items in Suite 1; 32 items across 4 reasoning tiers in Suite 2; 12 `ChoiceGate`/`ScoreGate` items in Suite 3; and a 12-section enterprise handbook in Suite 4).
122
+ - **Deterministic Classification**: All Layer 1 probes execute with greedy decoding parameters (`temperature=0.0`, `top_p=1.0`, `max_tokens=1`), yielding deterministic log-probabilities across runs for a fixed prompt and model checkpoint.
123
+
124
+ | Model Configuration | Model Family | Compute Device | Single-Pass Latency ($N=5$) | 2-Pass Symmetric Latency ($N=5$) | 4-Rubric Batch Total ($N=5$) | Per-Rubric Batch Latency ($N=5$) | 24-Item Multi-Domain Accuracy |
125
+ | :--- | :--- | :--- | :--- | :--- | :--- | :--- | :--- |
126
+ | **`gemma4:e4b`** | 4B General Model | GPU (RTX 4070) | **40.5 ± 6.0 ms** | **112.6 ± 4.6 ms** | **584.9 ± 51.8 ms** | **146.2 ± 12.9 ms** | **23/24 (95.8%)** |
127
+ | **`qwen2.5:14b`** | 14B General Model | GPU (RTX 4070) | **36.8 ± 6.5 ms** | **90.0 ± 4.1 ms** | **450.1 ± 18.8 ms** | **112.5 ± 4.7 ms** | **23/24 (95.8%)** |
128
+ | **`qwen2.5-coder:14b`** | 14B Code Model | GPU (RTX 4070) | **36.5 ± 6.3 ms** | **90.9 ± 3.3 ms** | **447.4 ± 3.9 ms** | **111.8 ± 1.0 ms** | **23/24 (95.8%)** |
129
+ | **`qwen2.5-coder:1.5b`** | 1.5B Code Model | Pure CPU (0 GPU, 1.4 GB) | **42.3 ± 1.4 ms** | **330.4 ± 63.5 ms** | **1,834.5 ± 75.6 ms** | **458.6 ± 18.9 ms** | **14/24 (58.3%)** |
130
+ | **`llama3.2:1b`** | 1B General Model | Pure CPU (0 GPU, 1.8 GB) | **46.9 ± 1.6 ms** | **459.2 ± 86.0 ms** | **2,665.1 ± 82.9 ms** | **666.3 ± 20.7 ms** | **15/24 (62.5%)** |
131
+ | **`qwen2.5-coder:3b`** | 3B Code Model | Pure CPU (0 GPU, 2.4 GB) | **69.1 ± 2.8 ms** | **625.7 ± 113.9 ms** | **3,626.6 ± 155.8 ms** | **906.7 ± 39.0 ms** | **19/24 (79.2%)** |
132
+ | **`llama3.2:3b`** | 3B General Model | Pure CPU (0 GPU, 3.2 GB) | **74.8 ± 0.8 ms** | **642.7 ± 113.6 ms** | **3,699.9 ± 116.8 ms** | **925.0 ± 29.2 ms** | **19/24 (79.2%)** |
133
+ | *`gemma4:e4b` (Baseline)* | *4B General Model* | *Pure CPU (0 GPU, 9.6 GB)* | *173.0 ± 2.4 ms* | *3,710.5 ± 82.1 ms* | *20,949.5 ± 182.5 ms* | *5,237.4 ± 45.6 ms* | *23/24 (95.8%)* |
134
+
135
+ ### Benchmark Analysis & Insights:
136
+ 1. **Single-Pass Latency (~36–41 ms on GPU, ~42–75 ms on CPU)**:
137
+ - Evaluates a rubric in a single forward pass without autoregressive decoding. Over **35x faster** than waiting for an LLM to generate 150 words of critique.
138
+ - On a CPU-only runner, compact 1B–3B models execute single-pass triage in **42–75 ms**, beating dense 4B CPU models by **2.3x–4.1x**.
139
+ 2. **2-Pass Symmetric Debiasing (~90–113 ms on GPU, ~330–640 ms on CPU)**:
140
+ - Runs both forward ($A=\text{Pass}, B=\text{Fail}$) and reverse ($B=\text{Pass}, A=\text{Fail}$) passes to eliminate pretraining token prior bias. The second pass hits the KV-cache.
141
+ - On CPU, `llama3.2:3b` and `qwen2.5-coder:3b` evaluate symmetric debiasing in **~625–642 ms**—almost **6x faster than dense 4B models (3,710 ms)**.
142
+ 3. **Multi-Rubric Batching (~112–146 ms per rubric on GPU, ~450–925 ms on CPU)**:
143
+ - `evaluate_batch` reuses the candidate prefix across all rubrics, avoiding redundant prompt re-evaluations and preventing KV-cache stampedes on the inference server.
144
+ 4. **Pure CPU-Only Memory Footprint (1.4 GB to 3.2 GB)**:
145
+ - Shifting from dense 4B models (`9.61 GB RAM`) to compact distilled models (`1.39 GB – 3.18 GB RAM`) frees up 65%–85% of host memory on CI runners while reducing wall-clock gating time by up to 83%.
146
+
147
+ ---
148
+
149
+ ## End-to-End Cascade Time Savings & Multi-Gate Benchmarks
150
+
151
+ ### 1. Multi-Domain Cascade Time Savings (24-Item Test Suite)
152
+
153
+ Evaluated across **24 items spanning 4 domains** ([`benchmarks/data/multi_domain_24.json`](benchmarks/data/multi_domain_24.json), 6 items per domain: RAG Groundedness with subtle scope/regional extrapolations, Customer Support Policy Compliance, SQL/API Query Safety, and Python Security). To ensure a fair comparison, the Baseline Generative Judge also runs with `<think>` suppressed (`think=False`):
154
+
155
+ | Model Configuration | Baseline Judge Time | Cascade Time (`on_ambiguous_or_fail`) | Cascade Time (`on_ambiguous_only`) | Speedup (`on_ambiguous_only`) | CoT Tokens Saved | Baseline Accuracy | Cascade Accuracy |
156
+ | :--- | :--- | :--- | :--- | :--- | :--- | :--- | :--- |
157
+ | **`gemma4:e4b` (GPU)** | 34,946.5 ms | 18,773.5 ms | **3,286.5 ms** | **10.6x** | 3,323 | 24/24 (100.0%) | **23/24 (95.8%)** |
158
+ | **`gemma4:e4b` (Pure CPU)** | 143,733.1 ms | 144,976.4 ms | **104,792.0 ms** | **1.4x** | 1,086 | 24/24 (100.0%) | **23/24 (95.8%)** |
159
+ | **`qwen2.5:14b` (GPU)** | 138,858.1 ms | 57,625.2 ms | **8,160.3 ms** | **17.0x** | 2,566 | 23/24 (95.8%) | **23/24 (95.8%)** |
160
+ | **`qwen2.5-coder:14b` (GPU)** | 133,724.5 ms | 65,616.0 ms | **11,786.2 ms** | **11.3x** | 2,578 | 24/24 (100.0%) | **23/24 (95.8%)** |
161
+
162
+ ---
163
+
164
+ ### 2. Fair Pure-CPU CI/CD Runner Benchmark (10-Item CI Test Suite, `options={"num_gpu": 0}`)
165
+
166
+ Simulating a free 0-GPU GitHub Actions runner using `gemma4:e4b` on pure CPU (`num_gpu=0`) across a 10-item Python CI suite (8 valid Python items, 1 Layer-0 AST syntax failure, 1 semantic PII security leak), with token savings and speedup measured against `Baseline A`:
167
+
168
+ | Evaluation Strategy | Total CPU Wall Time | Total Output Tokens | Accuracy | Output Token Savings | Speedup vs. Baseline A |
169
+ | :--- | :--- | :--- | :--- | :--- | :--- |
170
+ | **Baseline A: Uncapped CPU Judge (`think=True`, ~436 tok/item)** | 363.0 s | 4,360 | **10/10 (100%)** | 0.0% | 1.00x |
171
+ | **Baseline B: Naive Capped CPU Judge (`think=True`, `max_tokens=150`)** | 143.5 s | 1,500 | 2/10 (20%) | 65.6% | 2.53x |
172
+ | **Baseline C: Verdict-First CPU Judge (`think=False`, `max_tokens=60`)** | 59.0 s | 600 | **10/10 (100%)** | 86.2% | 6.15x |
173
+ | **`LogitGate(preset="fast_triage") >> JudgeGate(max_tokens=60)`** | **22.0 s** | **60** | **10/10 (100%)** | **98.6%** | **16.50x** |
174
+
175
+ *Key finding*: Why did naive token-capping (`Baseline B`, `max_tokens=150`) fail with 20% accuracy? Because modern reasoning models (`gemma4`, `deepseek-r1`, `qwen3`) emit 300+ hidden `<think>` tokens before writing a single visible character. By suppressing `<think>` in `OllamaBackend.generate` and using Verdict-First prompting (`[VERDICT: PASS/FAIL]` on Line 1 for short caps $\le 80$ tokens), `JudgeGate` produces a complete 60-token diagnostic in ~5.9s per item on CPU (`Baseline C`). Placing `ASTGate >> LogitGate` in front of `JudgeGate` reduces the 10-item suite from **363.0 s (`Baseline A`)** and **59.0 s (`Baseline C`)** down to **22.0 s** (**16.50x faster than `Baseline A`**, **2.68x faster than `Baseline C`**, and **90.0% fewer output tokens than `Baseline C`**) while maintaining **10/10 (100%) accuracy**.
176
+
177
+ #### Compact Models for CPU-Bound Automated Testing (1B–3B vs. 4B Baseline)
178
+
179
+ To determine the optimal model configuration for resource-constrained CI runners (e.g. GitHub Actions, GitLab CI, or local developer pre-commit hooks with zero GPU acceleration), we benchmarked four alternative compact models in pure CPU-only mode (`options={"num_gpu": 0}`) on an AMD Ryzen 7 5800X3D CPU across the complete benchmark suites.
180
+
181
+ Raw benchmark outputs are stored in [`benchmarks/cpu_results.json`](benchmarks/cpu_results.json):
182
+
183
+ | Model Configuration | Model Family | Host RAM | Single-Pass Triage ($N=5$) | 2-Pass Symmetric ($N=5$) | 4-Rubric Batch Total ($N=5$) | Suite 1 Cascade Acc | Suite 2 Reasoning (32 Items) | `ChoiceGate` Routing | `ScoreGate` Monotonicity |
184
+ | :--- | :--- | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: |
185
+ | **`qwen2.5-coder:1.5b`** | 1.5B Code Model | **1.39 GB** | **42.3 ± 1.4 ms** | **330.4 ± 63.5 ms** | **1,834.5 ± 75.6 ms** | 14/24 (58.3%) | 16/32 (50.0%) | **6/6 (100.0%)** | **8/8 (100.0%)** |
186
+ | **`llama3.2:1b`** | 1B General Model | **1.76 GB** | **46.9 ± 1.6 ms** | **459.2 ± 86.0 ms** | **2,665.1 ± 82.9 ms** | 15/24 (62.5%) | 18/32 (56.2%) | 4/6 (66.7%) | 4/8 (50.0%) |
187
+ | **`qwen2.5-coder:3b`** | 3B Code Model | **2.44 GB** | **69.1 ± 2.8 ms** | **625.7 ± 113.9 ms** | **3,626.6 ± 155.8 ms** | **19/24 (79.2%)** | 18/32 (56.2%) | **6/6 (100.0%)** | **8/8 (100.0%)** |
188
+ | **`llama3.2:3b`** | 3B General Model | **3.18 GB** | **74.8 ± 0.8 ms** | **642.7 ± 113.6 ms** | **3,699.9 ± 116.8 ms** | **19/24 (79.2%)** | **23/32 (71.9%)** | **6/6 (100.0%)** | **8/8 (100.0%)** |
189
+ | *`gemma4:e4b` (Baseline)* | *4B General Model* | *9.61 GB* | *173.0 ± 2.4 ms* | *3,710.5 ± 82.1 ms* | *20,949.5 ± 182.5 ms* | *23/24 (95.8%)* | *18/32 (56.2%)* | *6/6 (100.0%)* | *3/8 (37.5%)* |
190
+
191
+ ##### Key Insights for CPU-Bound Automated Testing:
192
+ 1. **The CI/CD Champion (`llama3.2:3b`)**:
193
+ - Reduces RAM consumption by **67%** (from 9.61 GB down to 3.18 GB), easily fitting inside standard 4 GB/7 GB GitHub Actions free runners.
194
+ - Runs 2-pass symmetric debiased gating in **642.7 ms** (**5.8x faster** than the 4B baseline at 3.7 s).
195
+ - Achieves the highest 32-item reasoning accuracy of any tested model (**23/32, 71.9%**), surpassing even 14B models on GPU (68.8%) thanks to Meta's aggressive distillation.
196
+ - Delivers flawless **100% (6/6)** `ChoiceGate` routing and **100% (8/8)** `ScoreGate` pairwise rank monotonicity ($H=3.69 > M=2.92 > L=2.34$).
197
+ 2. **The Micro-Gate Champion (`qwen2.5-coder:1.5b`)**:
198
+ - Microscopic **1.39 GB RAM footprint**, ideal for pre-commit git hooks and resource-constrained Docker test containers.
199
+ - Executes single-pass triage in **42.3 ms** and 2-pass debiasing in **330.4 ms** on pure CPU.
200
+ - Delivers a perfect **100% (6/6)** `ChoiceGate` routing and **100% (8/8)** `ScoreGate` monotonicity on code/incident rubrics.
201
+ 3. **The Multi-Rubric Batching Advantage**:
202
+ - On CPU, running 4 rubrics via `evaluate_batch` takes **1.8 s** on `qwen2.5-coder:1.5b` and **3.7 s** on `llama3.2:3b` (vs **20.9 s** on `gemma4:e4b`), avoiding the CPU memory bus saturation of redundant prefill passes.
203
+
204
+ ##### In-Process `llama.cpp` vs. Ollama Daemon & CPU Thread Scaling Benchmark
205
+
206
+ To determine whether native in-process embedding (`LlamaCppBackend` via `llama-cpp-python`) or background HTTP daemons (Ollama) offer better ergonomics and performance for CPU-only CI environments, we conducted a head-to-head benchmark across 3 compact GGUF models on an AMD Ryzen 9 9955HX3D (16-Core / 32-Thread with 128 MB 3D V-Cache).
207
+
208
+ Raw benchmark outputs are stored in [`benchmarks/cpu_format_runtime_results.json`](benchmarks/cpu_format_runtime_results.json):
209
+
210
+ | Model & Quantization | Disk Size | Cold Load | Host RAM (RSS) | Single-Pass (In-Process) | Single-Pass (Ollama Daemon) | 2-Pass Debiased (In-Process) | 2-Pass Debiased (Ollama Daemon) | 4-Rubric Batch (In-Process) | 4-Rubric Batch (Ollama Daemon) | ChoiceGate (16 Items) | ScoreGate Spearman $\rho$ |
211
+ | :--- | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: |
212
+ | **`llama3.2:1b` (Q8_0)** | 1.26 GB | **1.24 s** | 1,405 MB | 114.5 ± 8.4 ms | **56.0 ± 2.8 ms** | 604.3 ± 154.0 ms | **502.3 ± 96.0 ms** | 3,111.5 ± 415.5 ms | **2,900.2 ± 208.3 ms** | 8/16 (50.0%) | 0.6793 vs. 0.6688 |
213
+ | **`qwen2.5-coder:1.5b` (Q4_K_M)** | **940 MB** | **1.42 s** | **1,008 MB** | 128.0 ± 8.2 ms | **48.7 ± 1.8 ms** | 619.7 ± 99.0 ms | **362.3 ± 62.6 ms** | 3,541.6 ± 614.6 ms | **2,060.4 ± 156.7 ms** | **11/16 (68.8%)** vs. 9/16 | 0.6013 vs. 0.5683 |
214
+ | **`llama3.2:3b` (Q4_K_M)** | 1.93 GB | 3.22 s | 2,367 MB | 105.9 ± 3.7 ms | **80.9 ± 5.2 ms** | 815.8 ± 173.1 ms | **693.4 ± 125.2 ms** | 4,399.4 ± 340.1 ms | **4,111.7 ± 279.3 ms** | **12/16 (75.0%)** | **0.8487 vs. 0.8487** |
215
+
216
+ ##### CPU Thread Scaling Sweep (`llama3.2:3b`, Native In-Process `llama.cpp`):
217
+
218
+ | Thread Allocation | Single-Pass Triage ($N=5$) | 2-Pass Symmetric Debiasing ($N=5$) | 4-Rubric Batch Total ($N=5$) | Per-Rubric Batch Time |
219
+ | :---: | :---: | :---: | :---: | :---: |
220
+ | **$n\_threads = 1$** | 124.0 ± 4.6 ms | **893.1 ± 98.2 ms** | **4,883.7 ± 279.7 ms** | 1,220.9 ms |
221
+ | **$n\_threads = 2$** | **112.6 ± 6.5 ms** | 953.5 ± 82.3 ms | 4,905.9 ± 421.6 ms | 1,226.5 ms |
222
+ | **$n\_threads = 4$** | 117.7 ± 8.4 ms | 992.8 ± 117.7 ms | 5,047.7 ± 768.6 ms | 1,261.9 ms |
223
+ | **$n\_threads = 8$** | 133.8 ± 9.9 ms | 924.2 ± 170.9 ms | 5,152.2 ± 834.6 ms | 1,288.1 ms |
224
+ | **$n\_threads = 16$** | 118.4 ± 9.3 ms | 993.0 ± 90.2 ms | 5,180.3 ± 1514.6 ms | 1,295.1 ms |
225
+
226
+ ##### Key Architectural Findings on CPU Execution:
227
+ 1. **Zero Daemon Overhead & Instant Cold Startup**:
228
+ - In-process `llama.cpp` initializes directly inside your Python process in **1.2 to 3.2 seconds**, consuming only **1.0 GB to 2.4 GB RAM** without needing to launch, configure, or port-manage an external HTTP background daemon.
229
+ 2. **Identical Logit Fidelity Across Runtimes**:
230
+ - The continuous scoring correlation on `llama3.2:3b` was **identical to 4 decimal places** between native `llama.cpp` and Ollama daemon ($\rho = 0.8487$, with 12/16 ChoiceGate accuracy). On `qwen2.5-coder:1.5b`, in-process execution even resolved two additional keyword decoy cases ($11/16$ vs $9/16$).
231
+ 3. **Memory-Bandwidth Saturation (The 2-Thread Optimum)**:
232
+ - For single-token logit probing, CPU computation is strictly memory-bandwidth bound (reading ~1.9 GB of weights per forward pass from system RAM). Allocating more than **2 to 4 threads** provides zero speedup because the memory bus saturates, while higher thread counts introduce thread synchronization and cache-line invalidation overhead.
233
+
234
+ ---
235
+
236
+ ### 3. Empirical Layer Resolution Breakdown (24-Item Multi-Domain Suite)
237
+
238
+ Evaluated across the 24-item multi-domain benchmark suite ([`benchmarks/data/multi_domain_24.json`](benchmarks/data/multi_domain_24.json)):
239
+
240
+ | Model Configuration | Layer 0 (`ASTGate`) | Layer 1 Decisive (`LogitGate`) | Layer 2 Escalated (`JudgeGate`) | Combined L0 + L1 Resolution Rate |
241
+ | :--- | :--- | :--- | :--- | :--- |
242
+ | **`gemma4:e4b` (GPU)** | 2/24 (8.3%) | 22/24 (91.7%) | 0/24 (0.0%) | **24/24 (100.0%)** |
243
+ | **`gemma4:e4b` (Pure CPU, 0 GPU)** | 2/24 (8.3%) | 22/24 (91.7%) | 0/24 (0.0%) | **24/24 (100.0%)** |
244
+ | **`qwen2.5:14b` (GPU)** | 2/24 (8.3%) | 22/24 (91.7%) | 0/24 (0.0%) | **24/24 (100.0%)** |
245
+ | **`qwen2.5-coder:14b` (GPU)** | 2/24 (8.3%) | 21/24 (87.5%) | 1/24 (4.2%) | **23/24 (95.8%)** |
246
+
247
+ ---
248
+
249
+ ### 4. `ChoiceGate` (Multi-Way Routing) & `ScoreGate` (Continuous 1–5 Scoring) Benchmarks
250
+
251
+ #### Initial Baseline (12-Item Suite)
252
+
253
+ Evaluated on the baseline 12-item routing and scoring suite ([`benchmarks/data/choice_and_score_12.json`](benchmarks/data/choice_and_score_12.json), comprising 6 three-way operational/architectural routing cases with orthogonal categories and 6 continuous 1–5 rubric scoring cases across High, Medium, and Low quality extremes):
254
+
255
+ | Model Architecture | `ChoiceGate` Accuracy (2-Pass) | `ChoiceGate` Latency ($N=5$) | `ScoreGate` Mean (High Tier) | `ScoreGate` Mean (Medium Tier) | `ScoreGate` Mean (Low Tier) | `ScoreGate` Pairwise Rank Accuracy | `ScoreGate` Latency ($N=5$) |
256
+ | :--- | :--- | :--- | :--- | :--- | :--- | :--- | :--- |
257
+ | **`gemma4:e4b` (4B General)** | **6/6 (100.0%)** | 116.9 ± 1.7 ms | 4.96 | 2.15 | 1.01 | **6/6 (100.0%)** | 167.6 ± 1.1 ms |
258
+ | **`qwen2.5:14b` (14B General)** | **6/6 (100.0%)** | 318.5 ± 3.0 ms | 5.00 | 2.96 | 1.00 | **6/6 (100.0%)** | 499.0 ± 12.2 ms |
259
+ | **`qwen2.5-coder:14b` (14B Code)** | **6/6 (100.0%)** | 297.4 ± 4.3 ms | 4.28 | 2.61 | 1.43 | **6/6 (100.0%)** | 451.2 ± 14.5 ms |
260
+ | **`gemma4:26b` (26B MoE, ~4B act)** | **6/6 (100.0%)** | **104.0 ± 1.1 ms** | 5.00 | 1.98 | 1.00 | **6/6 (100.0%)** | **139.1 ± 2.3 ms** |
261
+ | **`gemma4:31b` (31B Dense)** | **6/6 (100.0%)** | 237.2 ± 3.8 ms | 5.00 | 1.64 | 1.00 | **6/6 (100.0%)** | 349.1 ± 4.7 ms |
262
+
263
+ ---
264
+
265
+ #### Hardened Stress Testing: Multi-Action Failure Boundaries (32-Item Adversarial Suite, $N=5$ Trials)
266
+
267
+ > [!IMPORTANT]
268
+ > **Why the 12-Item Baseline Was Insufficient**: The initial 12-item suite relied on orthogonal routing categories (e.g. Billing vs. Security Operations) and cartoonish quality extremes (e.g. pristine production code vs. remote code execution). Every model achieved 100% accuracy, masking real failure boundaries.
269
+ >
270
+ > To discover where first-token probability gating actually breaks down, we constructed a hardened 32-item adversarial dataset ([`benchmarks/data/adversarial_choice_and_score_32.json`](benchmarks/data/adversarial_choice_and_score_32.json)) with zero shortcut capability, evaluated across **9 model & hardware configurations** with 1 untimed warm-up pass and $N=5$ sequential timed trials per item (`benchmarks/run_adversarial_choice_score.py`). Raw benchmark results are stored in [`benchmarks/adversarial_choice_score_results.json`](benchmarks/adversarial_choice_score_results.json).
271
+
272
+ ##### Adversarial Dataset Architecture (32 Items):
273
+ 1. **`ChoiceGate` (16 Adversarial Items across 4 Stress Vectors)**:
274
+ - **Vector 1: 6-Way Fine-Grained Operational Scaling (4 items)**: Dispatches complex production incidents across 6 distinct engineering rotations (SecOps, DB Reliability, Infra/TLS, Billing Disputes, Core App Logic, Frontend UI).
275
+ - **Vector 2: Adversarial Keyword Decoys & Lexical Traps (4 items)**: Heavy security terminology embedded inside billing invoices, critical database crashes described casually, and feature requests masquerading as high-severity operational regressions.
276
+ - **Vector 3: Strict Multi-Domain Priority Hierarchy (4 items)**: Production scenarios with multi-category overlap governed by strict policy precedence (Tier 1 Outage > Tier 2 Security Breach > Tier 3 Core App Defect > Tier 4 UX/Formatting).
277
+ - **Vector 4: Architectural Scope Boundaries (4 items)**: In-memory atomic cache vs. public API/RPC breaking contract vs. database range partitioning vs. distributed Kafka cluster.
278
+ 2. **`ScoreGate` (16 Items across 5 Discrete Code Quality Tiers)**:
279
+ - **Tier 5 (Flawless, 3 items)**: Thread-safe $O(1)$ LRU cache with `OrderedDict` & `RLock`, streaming chunked SHA-256 hasher, monotonic token bucket rate limiter. Expected band: `[4.4, 5.0]`.
280
+ - **Tier 4 (Clean but Sub-optimal Complexity, 3 items)**: Functionally correct and cleanly typed code, but with $O(N)$ list search in LRU cache, $O(N^2)$ quadratic deduplication, redundant byte copies. Expected band: `[3.2, 4.2]`.
281
+ - **Tier 3 (Functional with Code Smells, 4 items)**: Mutable default dict argument (`filters={}`), missing network socket timeouts with bare exception catch, unclosed file descriptors, global un-locked state mutation. Expected band: `[2.4, 3.2]`.
282
+ - **Tier 2 (Latent Critical Defects & TOCTOU Traps, 3 items)**: Time-of-Check to Time-of-Use file race condition, naive local datetime failing across daylight saving transitions, unpickling untrusted payload. Expected band: `[1.6, 2.5]`.
283
+ - **Tier 1 (Catastrophic Flaws, 3 items)**: Direct raw SQL string interpolation, unquoted shell command execution, financial wire transfer swallowing `BaseException` and returning false success. Expected band: `[1.0, 1.8]`.
284
+
285
+ ##### Master Empirical Results Across CPU, GPU 1, and GPU 0 Configurations ($N=5$ Trials):
286
+
287
+ | Model & Hardware Configuration | Host Footprint | `ChoiceGate` Acc ($N=5$) | Order Stability | Choice Latency ($N=5$) | Score T5 (Flawless) | Score T4 (Complexity) | Score T3 (Smells) | Score T2 (TOCTOU) | Score T1 (Fatal) | Adjacent Monotonicity | Spearman $\rho$ | Dynamic Range | Score Latency ($N=5$) |
288
+ | :--- | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: |
289
+ | **`llama3.2:1b` (Pure CPU)** | 1.76 GB RAM | **50.0% ± 0.0%** | 15/16 (93.8%) | 1005.2 ± 310.1 ms | 3.22 | 3.20 | 3.00 | 3.07 | 2.56 | 29/42 (69.0%) | **0.6688** | 0.66 | 602.6 ± 276.7 ms |
290
+ | **`qwen2.5-coder:1.5b` (Pure CPU)** | 1.39 GB RAM | **61.2% ± 2.8%** | 13/16 (81.2%) | **644.8 ± 278.4 ms** | 3.28 | 3.08 | 3.03 | 3.02 | 3.02 | 28/42 (66.7%) | **0.5683** | 0.26 | **434.7 ± 192.1 ms** |
291
+ | **`llama3.2:3b` (Pure CPU)** | 3.18 GB RAM | **75.0% ± 0.0%** | 15/16 (93.8%) | 1422.5 ± 441.3 ms | 3.63 | 3.05 | 2.55 | 2.54 | 2.05 | 33/42 (78.6%) | **0.8487** | 1.58 | 872.1 ± 401.0 ms |
292
+ | **`qwen2.5-coder:3b` (Pure CPU)** | 2.44 GB RAM | **75.0% ± 0.0%** | 14/16 (87.5%) | 1265.0 ± 568.2 ms | 3.61 | 2.99 | 2.85 | 3.04 | 2.78 | 28/42 (66.7%) | **0.6013** | 0.83 | 838.3 ± 399.8 ms |
293
+ | **`gemma4:e4b` (Pure CPU)** | 9.57 GB RAM | **93.8% ± 0.0%** | **16/16 (100%)** | 4186.4 ± 1619.0 ms | 4.66 | 2.73 | 2.01 | 1.70 | 1.00 | 33/42 (78.6%) | **0.8907** | 3.66 | 6028.0 ± 1678.2 ms |
294
+ | **`gemma4:e4b` (GPU 1, 16GB)** | 3.25 GB VRAM | **93.8% ± 0.0%** | **16/16 (100%)** | **137.4 ± 20.8 ms** | 4.58 | 2.74 | 2.02 | 1.69 | 1.01 | 33/42 (78.6%) | **0.8907** | 3.57 | 165.0 ± 24.1 ms |
295
+ | **`qwen2.5:14b` (GPU 1, 16GB)** | 10.39 GB VRAM | **87.5% ± 0.0%** | **16/16 (100%)** | 141.1 ± 27.2 ms | 4.62 | 2.98 | 2.67 | 2.19 | 1.00 | 34/42 (81.0%) | **0.8764** | 3.62 | **130.1 ± 17.6 ms** |
296
+ | **`qwen2.5-coder:14b` (GPU 1, 16GB)** | 10.39 GB VRAM | **87.5% ± 0.0%** | **16/16 (100%)** | 156.7 ± 33.6 ms | 4.43 | 2.63 | 2.08 | 1.98 | 1.16 | 32/42 (76.2%) | **0.8787** | 3.27 | 131.7 ± 17.6 ms |
297
+ | **`gemma4:31b` (GPU 0, 32GB)** | 2.93 GB VRAM | **100.0% ± 0.0%** | **16/16 (100%)** | 357.8 ± 31.5 ms | 5.00 | 2.33 | 1.72 | 1.33 | 1.00 | 33/42 (78.6%) | **0.9096** | **4.00** | 407.1 ± 72.3 ms |
298
+
299
+ ##### Category Breakdown for `ChoiceGate` Routing:
300
+
301
+ | Model & Hardware Configuration | 6-Way Operational Scaling (4 items) | Adversarial Keyword Decoys (4 items) | Priority Hierarchy Conflicts (4 items) | Architectural Scope (4 items) | Total Accuracy |
302
+ | :--- | :---: | :---: | :---: | :---: | :---: |
303
+ | **`llama3.2:1b` (Pure CPU)** | 10/20 (50.0%) | 10/20 (50.0%) | 10/20 (50.0%) | 10/20 (50.0%) | **50.0% ± 0.0%** |
304
+ | **`qwen2.5-coder:1.5b` (Pure CPU)** | 19/20 (95.0%) | 5/20 (25.0%) | 5/20 (25.0%) | **20/20 (100.0%)** | **61.2% ± 2.8%** |
305
+ | **`llama3.2:3b` (Pure CPU)** | **20/20 (100.0%)** | 15/20 (75.0%) | 10/20 (50.0%) | 15/20 (75.0%) | **75.0% ± 0.0%** |
306
+ | **`qwen2.5-coder:3b` (Pure CPU)** | **20/20 (100.0%)** | 5/20 (25.0%) | 15/20 (75.0%) | **20/20 (100.0%)** | **75.0% ± 0.0%** |
307
+ | **`gemma4:e4b` (Pure CPU / GPU 1)** | **20/20 (100.0%)** | 15/20 (75.0%) | **20/20 (100.0%)** | **20/20 (100.0%)** | **93.8% ± 0.0%** |
308
+ | **`qwen2.5:14b` (GPU 1)** | **20/20 (100.0%)** | 15/20 (75.0%) | 15/20 (75.0%) | **20/20 (100.0%)** | **87.5% ± 0.0%** |
309
+ | **`qwen2.5-coder:14b` (GPU 1)** | **20/20 (100.0%)** | 15/20 (75.0%) | 15/20 (75.0%) | **20/20 (100.0%)** | **87.5% ± 0.0%** |
310
+ | **`gemma4:31b` (GPU 0)** | **20/20 (100.0%)** | **20/20 (100.0%)** | **20/20 (100.0%)** | **20/20 (100.0%)** | **100.0% ± 0.0%** |
311
+
312
+ ##### Key Scientific Findings from the Hardened Suite:
313
+ 1. **Shattering the 100% Ceiling Effect**:
314
+ - The hardened adversarial suite completely exposes the true limits of compact and mid-sized models. Where the 12-item baseline reported 100% across the board, `llama3.2:1b` drops to **50.0%**, `qwen2.5-coder:1.5b` drops to **61.2%**, and the 14B models plateau at **87.5%**.
315
+ 2. **The TOCTOU Inversion Bug in Compact Code Models**:
316
+ - On `ScoreGate`, `qwen2.5-coder:3b` exhibits a critical failure mode: it scores Tier 2 code (3.04) **higher** than Tier 4 code (2.99) and Tier 3 code (2.85). Because Tier 2 code is cleanly typed and well-formatted, the 3B model is blinded by surface appearance and fails to spot the latent TOCTOU concurrency race or daylight-saving timezone bug.
317
+ 3. **Severe Score Compression in Sub-3B Models**:
318
+ - `qwen2.5-coder:1.5b` exhibits extreme score compression ($\Delta = 0.26$), collapsing all 5 tiers into the narrow band between 3.02 and 3.28 ($\rho = 0.5683$). It cannot differentiate between a flawless LRU cache and a catastrophic SQL injection via first-token logits alone.
319
+ 4. **`llama3.2:3b` Outperforms `qwen2.5-coder:3b` on Continuous Scoring**:
320
+ - For CPU-only CI deployments, `llama3.2:3b` achieves a **Spearman $\rho = 0.8487$** with a healthy dynamic range of **1.58** ($T5=3.63 \to T1=2.05$), preserving strictly monotonic ordering across all adjacent tiers without the inversion bugs seen in Qwen Coder 3B.
321
+ 5. **Cross-Card Scaling: GPU 1 (16GB) vs. GPU 0 (32GB)**:
322
+ - On GPU 1, `gemma4:e4b` achieves **93.8%** ChoiceGate accuracy in **137.4 ms** (30x faster than CPU at 4.2 s).
323
+ - On GPU 0 (RTX 5090 32GB), **`gemma4:31b` is the only model to achieve a flawless 100.0% on `ChoiceGate`**, successfully untangling all adversarial keyword decoys and multi-domain priority conflicts, with a near-perfect **Spearman $\rho = 0.9096$** spanning the complete 1.00 to 5.00 score range.
324
+
325
+ ---
326
+
327
+ ## Falsification Benchmarks: Where Does Layer 1 Break Down & How to Mitigate It?
328
+
329
+ To establish clear empirical boundaries for first-token logit probing, we evaluated `LogitGate` across **5 model architectures** (`4B`, `14B General`, `14B Code`, `26B MoE`, `31B Dense`), **4 reasoning depth tiers** (32 items total, 8 cases per tier in [`benchmarks/data/reasoning_tiers_32.json`](benchmarks/data/reasoning_tiers_32.json)), **document lengths** (200 to 16,000 tokens across a 12-section enterprise handbook), and **context window allocations** (`num_ctx` from 512 to 131,072).
330
+
331
+ ### 1. Reasoning Depth & Circuit-Depth Boundary (32-Item Suite, 8 Cases per Tier)
332
+
333
+ A causal transformer evaluates its first token in a single forward pass through $L$ attention layers. This corresponds to a sequential circuit depth of $O(1)$. When a verification task requires sequential recurrence, multi-hop state tracking, scratchpad arithmetic, or resistance against adversarial distractors, first-token probing encounters an architectural boundary:
334
+
335
+ - **Tier A — Direct Semantic / Format / Policy Compliance (Single-Hop, 8 Cases: 4 Pass, 4 Fail)**:
336
+ RAG groundedness checks (including subtle scope and regional extrapolations), customer support 2FA/CVV policy enforcement, and SQL read-only CTE safety.
337
+ - **Tier B — Nuanced Partial Compliance (Compound 4-Part Rubric vs. Atomic Batch, 8 Cases: 4 Pass, 4 Fail)**:
338
+ Testing 4 simultaneous Python engineering rules: (1) valid syntax, (2) Google docstrings with `Args:` and `Returns:`, (3) full parameter and return type annotations, and (4) absence of mutable default arguments (`=[]`, `={}`) and bare `except:` clauses. Failing cases satisfy 3 of the 4 rules and subtly violate only 1 (e.g. missing return annotation `-> float`, mutable list default, or missing `Args:` section).
339
+ - **Tier C — Multi-Hop Arithmetic & Algorithmic Loop Invariants (8 Cases: 4 Pass, 4 Fail)**:
340
+ Matched pass/fail counterparts with zero inline comments: multi-item invoice arithmetic (`$92.52` vs `$96.52`), binary search termination (`high = mid - 1` vs `high = mid` infinite loop), sliding window loop bounds (`len(series) - window_size + 1` vs off-by-one `len(series) - window_size`), and half-open interval overlap logic (`max(a_start, b_start) < min(a_end, b_end)` vs `a_start < b_end and a_end < b_start`).
341
+ - **Tier D — Adversarial Distractors, Deceptive Docstrings & Self-Correction (8 Cases: 4 Pass, 4 Fail)**:
342
+ Zero inline giveaway comments: a non-atomic cache class whose docstring claims `"Formally verified lock-free concurrent cache"`, an invoice with a \$10 arithmetic error accompanied by `"AUDIT STAMP: All arithmetic sums verified by BillingEngine v4.2"`, an SQL query function claiming `"hardened, SQL-injection-safe lookup"` that interpolates `ORDER BY {order_by}`, a payment function that swallows exceptions and logs `"Settlement pipeline completed"`, plus passing cases with self-correcting support transcripts and runbooks listing forbidden `DROP TABLE` commands inside a policy table.
343
+
344
+ | Model Architecture | Tier A (Direct) | Tier B (Compound) | Tier B (Atomic Batch) | Tier C (Multi-Hop) | Tier D (Adversarial) | Cascade Accuracy (Compound B) | Cascade Accuracy (Atomic B) |
345
+ | :--- | :--- | :--- | :--- | :--- | :--- | :--- | :--- |
346
+ | **`gemma4:e4b` (4B General)** | **8/8 (100.0%)** | 6/8 (75.0%) | **7/8 (87.5%)** | 7/8 (87.5%) | 6/8 (75.0%) | 27/32 (84.4%) | 28/32 (87.5%) |
347
+ | **`qwen2.5:14b` (14B General)** | **8/8 (100.0%)** | 7/8 (87.5%) | **7/8 (87.5%)** | 6/8 (75.0%) | 7/8 (87.5%) | 28/32 (87.5%) | 28/32 (87.5%) |
348
+ | **`qwen2.5-coder:14b` (14B Code)** | **8/8 (100.0%)** | 7/8 (87.5%) | **7/8 (87.5%)** | 7/8 (87.5%) | 7/8 (87.5%) | 29/32 (90.6%) | 29/32 (90.6%) |
349
+ | **`gemma4:26b` (26B MoE, ~4B act)** | **8/8 (100.0%)** | **8/8 (100.0%)** | **7/8 (87.5%)** | 7/8 (87.5%) | 7/8 (87.5%) | **30/32 (93.8%)** | 29/32 (90.6%) |
350
+ | **`gemma4:31b` (31B Dense)** | **8/8 (100.0%)** | **8/8 (100.0%)** | **7/8 (87.5%)** | 7/8 (87.5%) | 7/8 (87.5%) | **30/32 (93.8%)** | 29/32 (90.6%) |
351
+
352
+ #### Crucial Insights & Mitigation Strategies:
353
+ 1. **Model Capacity & Atomic Decomposition on Compound Rubrics (`Tier B`)**:
354
+ - While the 26B MoE and 31B Dense models achieved **8/8 (100.0%)** even on the monolithic 4-part compound rubric, smaller 4B and 14B models suffered from rubric dilution when 3 of 4 requirements passed and only 1 subtle requirement failed (such as an omitted `-> float` return annotation on a function whose parameters were fully typed).
355
+ - Decomposing the 4-part rubric into atomic rubrics via `evaluate_batch(candidate, rubrics)` lifted `gemma4:e4b` from `6/8 (75.0%)` to `7/8 (87.5%)` and `qwen2.5-coder:14b` from `7/8 (87.5%)` to **8/8 (100.0%)** (where atomic rule #3 produced an ambiguous probability $P=0.81$ that escalated to `JudgeGate`, which caught the missing return type annotation).
356
+ 2. **Reason-Then-Verdict Escalation in `JudgeGate` (`Tier C` & `Tier D`)**:
357
+ - Even with zero inline comments, Layer 1 (`LogitGate`) accurately detected the binary search infinite loop (`high = mid`), sliding window off-by-one (`range(len(series) - window_size)`), interval overlap bug, deceptive thread-safe cache docstring, and deceptive SQL `ORDER BY` injection across almost all models.
358
+ - However, when presented with the multi-line invoice containing a plausible arithmetic error (`17 * $24.00 + $19.00 = $417.00` instead of `$427.00`) accompanied by `"AUDIT STAMP: All arithmetic sums verified by BillingEngine v4.2"`, **all five models awarded $P \ge 0.94$ false passes at Layer 1**. A single forward pass ($O(1)$ circuit depth) cannot execute multi-digit arithmetic in the presence of authoritative surface distractors.
359
+ - On `tier_c_2_invoice_math_fail` (where no adversarial audit stamp was present), `qwen2.5-coder:14b` produced an ambiguous Layer 1 probability ($P=0.5824$), triggering Layer 2 (`JudgeGate`). Because `JudgeGate` instructs the model to verify calculations step-by-step in bullet points before emitting `[VERDICT: PASS/FAIL]` on the final line, `JudgeGate` computed `$108.85 - $16.33 = $92.52 \ne $96.52` and rejected the faulty invoice.
360
+ - **Recommended Mitigations**: Use `evaluate_batch` for multi-part rubrics, configure `preset="strict"` (`pass_threshold=0.90, fail_threshold=0.25`) to widen the Layer 2 escalation band for subtle logic checks, and route exact arithmetic or schema assertions to `ASTGate` / `ContractGate` validators.
361
+
362
+ ---
363
+
364
+ ### 2. Context Length Scaling & Diverse Multi-Section Handbook Haystack (200 to 16,000 Tokens)
365
+
366
+ Rather than repeating a single boilerplate paragraph, [`benchmarks/data/haystack_handbook.json`](benchmarks/data/haystack_handbook.json) constructs a realistic 12-section enterprise architecture handbook (covering VPC routing, `config.yaml` schema validation, OIDC federation, HashiCorp Vault credential injection, PostgreSQL HA, PII log redaction, and break-glass procedures—where multiple surrounding sections legitimately discuss `config.yaml`, passwords, and emergency maintenance). We embedded a 1-paragraph policy addendum at the midpoint of the document (either strictly prohibiting hardcoded credentials in `config.yaml` or permitting a fallback password during maintenance) and evaluated `"Does this architecture document strictly prohibit hardcoding plaintext passwords or credentials in config.yaml under all circumstances (including emergency maintenance)?"`:
367
+
368
+ | Document Length | `gemma4:e4b` Latency | `gemma4:e4b` $\Delta P$ | `qwen2.5:14b` Latency | `qwen2.5:14b` $\Delta P$ | `gemma4:26b` Latency | `gemma4:26b` $\Delta P$ | `gemma4:31b` Latency | `gemma4:31b` $\Delta P$ |
369
+ | :--- | :--- | :--- | :--- | :--- | :--- | :--- | :--- | :--- |
370
+ | **Short (~200 tok)** | 280.1 ms | 1.0000 | 434.6 ms | 1.0000 | **207.2 ms** | 1.0000 | 738.0 ms | 1.0000 |
371
+ | **Medium (~1,500 tok)** | 467.9 ms | 0.9985 | 1,366.2 ms | 1.0000 | **524.6 ms** | 1.0000 | 1,807.9 ms | 1.0000 |
372
+ | **Long (~4,500 tok)** | 1,128.1 ms | 0.9506 | 2,611.5 ms | 1.0000 | **827.6 ms** | 1.0000 | 2,858.9 ms | 1.0000 |
373
+ | **Very Long (~8,000 tok)** | 1,985.5 ms | 0.9621 | 4,774.7 ms | 1.0000 | **1,229.7 ms** | 1.0000 | 4,406.8 ms | 1.0000 |
374
+ | **Massive (~16,000 tok)** | 4,044.0 ms | 0.9448 | 11,122.8 ms | 1.0000 | **2,118.3 ms** | 1.0000 | 7,621.9 ms | 1.0000 |
375
+
376
+ #### Key Architectural Findings:
377
+ - **Realistic Attention Dilution on 4B vs. 14B–31B Models**: In a diverse technical haystack where surrounding sections also mention `config.yaml` and Vault credentials, the 4B model (`gemma4:e4b`) exhibits gradual probability attenuation from $\Delta P = 1.0000$ at 200 tokens down to $\Delta P = 0.9448$ ($P_{\text{compliant}} = 0.9448$, $P_{\text{violating}} = 0.0000$) at 16,000 tokens—still well above the `0.85` pass threshold, while 14B, 26B MoE, and 31B Dense models maintain $\Delta P = 1.0000$ across all lengths.
378
+ - **MoE vs. Dense Pre-Fill Advantage**: At 16,000 tokens, **`gemma4:26b` (MoE)** processed the prompt in **2,118.3 ms**—**3.60x faster than `gemma4:31b` (Dense, 7,621.9 ms)** and **5.25x faster than `qwen2.5:14b` (11,122.8 ms)** because MoE routes each token through ~4B active parameters while retaining 26B capacity.
379
+
380
+ ---
381
+
382
+ ### 3. Context Window Squeezing (`num_ctx`) & Hardware Scaling Sweep (512 to 65,536 Tokens)
383
+
384
+ Configuring the context window size via `LOGITGATE_NUM_CTX` or `logitgate.configure(num_ctx=...)` allows developers to control KV-cache allocation and prevent GPU-to-CPU memory spillover:
385
+
386
+ #### Allocated Memory Footprint by Context Window (`num_ctx`)
387
+
388
+ | Model & Hardware Configuration | `num_ctx=512` | `num_ctx=4,096` | `num_ctx=16,384` | `num_ctx=32,768` | `num_ctx=65,536` | Spillover Boundary |
389
+ | :--- | :--- | :--- | :--- | :--- | :--- | :--- |
390
+ | **`gemma4:e4b` (RTX 4070 12 GB)\*** | 9.41 GB VRAM | 9.41 GB VRAM | 9.45 GB VRAM | 9.54 GB VRAM | 9.71 GB VRAM | **100% GPU up to 131,072 tokens** |
391
+ | **`gemma4:e4b` (Ryzen 7 5800X3D CPU)\*** | 9.41 GB RAM | 9.41 GB RAM | 9.57 GB RAM | 9.60 GB RAM | 9.60 GB RAM | **Zero VRAM footprint** |
392
+ | **`qwen2.5:14b` (RTX 4070 12 GB)** | 8.71 GB VRAM | 9.09 GB VRAM | 10.39 GB VRAM | 10.33 GB VRAM + 2.40 GB RAM | 10.33 GB VRAM + 2.40 GB RAM | **Spills to CPU at $\ge$ 32,768 (>12 GB)** |
393
+ | **`gemma4:26b` (MoE, RTX 5090 32 GB)** | 17.42 GB VRAM | 17.69 GB VRAM | 17.72 GB VRAM | 17.84 GB VRAM | 18.18 GB VRAM | **100% GPU up to 65,536 tokens** |
394
+ | **`gemma4:31b` (Dense, RTX 5090 32 GB)** | 20.97 GB VRAM | 21.50 GB VRAM | 21.71 GB VRAM | 21.46 GB VRAM | 22.00 GB VRAM | **100% GPU up to 65,536 tokens** |
395
+
396
+ #### Warm 2-Pass Symmetric Latency by Context Window (`num_ctx`)
397
+
398
+ | Model & Hardware Configuration | `num_ctx=512` | `num_ctx=4,096` | `num_ctx=16,384` | `num_ctx=32,768` | `num_ctx=65,536` |
399
+ | :--- | :--- | :--- | :--- | :--- | :--- |
400
+ | **`gemma4:e4b` (RTX 4070 12 GB)\*** | 92.7 ms | 94.5 ms | 101.9 ms | 94.4 ms | 94.5 ms |
401
+ | **`gemma4:e4b` (Ryzen 7 5800X3D CPU)\*** | 2,150.0 ms | 2,170.0 ms | 2,200.0 ms | 2,130.0 ms | 2,450.0 ms |
402
+ | **`qwen2.5:14b` (RTX 4070 12 GB)** | 94.4 ms | 93.4 ms | 99.7 ms | 314.5 ms | 314.3 ms |
403
+ | **`gemma4:26b` (MoE, RTX 5090 32 GB)** | 92.4 ms | 89.9 ms | 86.4 ms | 90.3 ms | 87.9 ms |
404
+ | **`gemma4:31b` (Dense, RTX 5090 32 GB)** | 194.8 ms | 184.3 ms | 177.4 ms | 175.1 ms | 182.1 ms |
405
+
406
+ *\*Note on `gemma4:e4b` memory footprint & 128k scaling: Google's Gemma 4 `e4b` ("Effective 4B") packs `8.0B` total parameters (`8.95 GB` Q4_K_M GGUF weights, including 42-layer Per-Layer Embeddings plus 16-layer Vision and 12-layer Audio encoders, with ~4B active text parameters). At `num_ctx=131,072` (128k tokens), `gemma4:e4b` allocates `10.04 GB` VRAM (`95.9 ms` warm latency), still fitting 100% inside a 12 GB GPU. Text-only 3B–4B Q4 models (`qwen2.5:3b`, `llama3.2:3b`) require only `~2.5–3.2 GB` VRAM/RAM.*
407
+
408
+ > [!TIP]
409
+ > **Why `LogitGate` Survives GPU-to-CPU RAM Spillover (~314 ms vs. 80+ Seconds)**:
410
+ > On `qwen2.5:14b` (which uses full global attention across all 48 layers), raising `num_ctx` to `32,768` spills `2.4 GB` of KV-cache into System RAM over PCIe, increasing 2-pass latency from **99.7 ms to 314.5 ms**. In traditional generative LLM-as-a-Judge, that PCIe transfer penalty is paid **sequentially on every generated token** ($200\text{ ms} \times 400\text{ tokens} \approx 80\text{ seconds}$). Because `LogitGate` only evaluates the first-token forward pass (`max_tokens=1`), the PCIe spillover penalty is paid only during prefill—allowing users to evaluate 16k–32k documents in **~0.31 seconds** even when KV-cache spills into System RAM.
411
+ > Furthermore, hybrid sliding-window architectures like **`gemma4:e4b` and `gemma4:26b` (MoE)** grow their KV-cache by only **`+0.63 GB` to `+0.76 GB` up to `64k–128k` context**, staying in VRAM at **~88–96 ms**.
412
+
413
+ ---
414
+
415
+ ### 4. Reason-Then-Verdict & Self-Healing Logit Probe in `JudgeGate`
416
+
417
+ In traditional LLM-as-a-judge frameworks, evaluators often ask for a verdict before reasoning or rely on naive regex/substring matching (`if "FAIL" in text.upper()`). Asking a non-thinking model to emit its verdict on Line 1 forces it to guess before performing step-by-step arithmetic or logic verification, while naive substring matching triggers false failures when a model writes `"The candidate does not fail any requirements"`.
418
+
419
+ `JudgeGate` handles Layer 2 verdict extraction in three steps:
420
+ 1. **Reason-Then-Verdict Prompting**: On standard calls, `JudgeGate` instructs the model to verify each requirement or calculation step-by-step in 2–4 concise bullet points first, and emit `[VERDICT: PASS]` or `[VERDICT: FAIL]` on the concluding line (matching the final tag via `re.finditer`). For ultra-short CPU caps (`max_tokens <= 80`), it switches to Verdict-First on Line 1 so the tag is never truncated.
421
+ 2. **Self-Healing 1-Token Logit Probe**: If an upstream model omits the explicit `[VERDICT: ...]` tag or JSON field, **`JudgeGate` runs a 1-token `LogitGate` probe on its own generated critique text** before falling back to heuristics:
422
+ ```python
423
+ # Inside JudgeGate._parse_verdict:
424
+ probe_gate = LogitGate(
425
+ rubric="Does this review critique conclude that the candidate artifact PASSED the evaluation?",
426
+ backend=self.backend,
427
+ symmetric_debiasing=False,
428
+ )
429
+ is_pass = probe_gate.evaluate(critique_text).probability >= 0.5
430
+ ```
431
+ 3. **Negation-Safe Line Fallback**: If the backend does not implement `LogitBackend`, it falls back to negation-safe parsing of concluding lines.
432
+
433
+ ---
434
+
435
+ ### 5. The Frontier of Circuit Depth: Elastic Recurrent Layer-Looping (NVIDIA-Nemotron Dory & Universal Transformers)
436
+
437
+ A causal transformer evaluates its first token in a single forward pass through $L$ attention layers ($O(1)$ sequential circuit depth). Standard causal models cannot compute multi-digit arithmetic, complex state machines, or nested boolean logic in a single pass without emitting intermediate scratchpad tokens (Chain-of-Thought / `<think>`), which incurs substantial autoregressive decoding latency.
438
+
439
+ #### Latent Reasoning in Hidden-State Space
440
+ Architectures like **NVIDIA-Nemotron-Labs Dory** (`nvidia/NVIDIA-Nemotron-Labs-Dory1.0-4B-BF16`) and Universal Transformers overcome this limitation by introducing **elastic recurrent depth**. Instead of traversing intermediate transformer layers once, Dory recirculates hidden state representations through a shared recurrent block for $K$ iterations (`num_loops`, typically 1 to 4) before projecting to output logits:
441
+
442
+ $$\mathbf{h}^{(k+1)} = \text{RecurrentLayerBlock}(\mathbf{h}^{(k)}, \mathbf{x}), \quad k \in \{1, \dots, K\}$$
443
+
444
+ This performs multi-step iterative latent reasoning directly in embedding space prior to emitting token 1. While looping increases prefill compute by ~30–60%, it completely eliminates the memory-bandwidth bottleneck of autoregressive token generation, providing high-fidelity first-token logits on complex constraints with **zero generated CoT tokens**.
445
+
446
+ #### Seamless Integration via `RecurrentPyTorchBackend`
447
+ LogitGate provides native support for latent recurrent architectures via `RecurrentPyTorchBackend` and the `recurrent://` URI scheme:
448
+
449
+ ```python
450
+ from logitgate import LogitGate
451
+
452
+ # Elastic recurrent depth: 2 internal latent loops before first-token projection
453
+ gate = LogitGate(
454
+ rubric="Does the SQL query use proper parameterized statements without dynamic string interpolation?",
455
+ backend="recurrent://nvidia/NVIDIA-Nemotron-Labs-Dory1.0-4B-BF16",
456
+ num_loops=2,
457
+ )
458
+
459
+ verdict = gate.evaluate(candidate_sql)
460
+ print(f"Passed: {verdict.passed} (Calibrated P={verdict.probability:.4f})")
461
+ ```
462
+
463
+ #### Empirical Multi-GPU & Recurrent Depth Benchmark (RTX 5090 vs. RTX 4070 Across $K=1, 2, 4$)
464
+
465
+ To rigorously evaluate how latent recurrent looping impacts first-token logit gating, we executed the full 4-suite benchmark suite against **NVIDIA-Nemotron-Labs Dory-4B** (`nvidia/NVIDIA-Nemotron-Labs-Dory1.0-4B-BF16`, 7.5 GB safetensors, BF16 native PyTorch execution) across both physical GPUs:
466
+ - **Device 0 (`cuda:0`)**: NVIDIA GeForce RTX 5090 (32 GB GDDR7 VRAM, Blackwell `sm_120`, CUDA 13.2 runtime).
467
+ - **Device 1 (`cuda:1`)**: NVIDIA GeForce RTX 4070 (12 GB GDDR6X VRAM, Ada Lovelace `sm_89`).
468
+
469
+ Raw benchmark measurements are stored in [`benchmarks/dory_results.json`](benchmarks/dory_results.json).
470
+
471
+ ##### 1. Suite 2: Reasoning Depth Tiers Across Recurrent Depth ($K=1, 2, 4$)
472
+ Evaluating the 32-item reasoning depth suite (8 items per tier) across recurrent loop passes:
473
+
474
+ | Model & Device | Recurrent Loops | Tier A (Surface) | Tier B (Compound) | Tier C (Multi-Hop) | Tier D (Adversarial) | Overall 32-Item Reasoning |
475
+ | :--- | :---: | :---: | :---: | :---: | :---: | :---: |
476
+ | **Dory-4B (RTX 5090)** | $K=1$ | 4/8 (50.0%) | 4/8 (50.0%) | 6/8 (75.0%) | 3/8 (37.5%) | **17/32 (53.1%)** |
477
+ | **Dory-4B (RTX 5090)** | $K=2$ | 5/8 (62.5%) | **6/8 (75.0%)** | 6/8 (75.0%) | 4/8 (50.0%) | **21/32 (65.6%)** *(+12.5% jump)* |
478
+ | **Dory-4B (RTX 5090)** | $K=4$ | 4/8 (50.0%) | 4/8 (50.0%) | 5/8 (62.5%) | 5/8 (62.5%) | **18/32 (56.2%)** |
479
+ | **Dory-4B (RTX 4070)** | $K=1$ | 4/8 (50.0%) | 3/8 (37.5%) | 6/8 (75.0%) | 3/8 (37.5%) | **16/32 (50.0%)** |
480
+ | **Dory-4B (RTX 4070)** | $K=2$ | 5/8 (62.5%) | **5/8 (62.5%)** | 6/8 (75.0%) | 4/8 (50.0%) | **20/32 (62.5%)** *(+12.5% jump)* |
481
+ | **Dory-4B (RTX 4070)** | $K=4$ | 4/8 (50.0%) | 4/8 (50.0%) | 5/8 (62.5%) | 5/8 (62.5%) | **18/32 (56.2%)** |
482
+ | *Baseline Feed-Forward 4B (`gemma4:e4b`)* | *N/A ($K=1$)* | *6/8 (75.0%)* | *4/8 (50.0%)* | *4/8 (50.0%)* | *4/8 (50.0%)* | *18/32 (56.2%)* |
483
+ | *Baseline Feed-Forward 14B (`qwen2.5:14b`)* | *N/A ($K=1$)* | *8/8 (100.0%)* | *5/8 (62.5%)* | *5/8 (62.5%)* | *4/8 (50.0%)* | *22/32 (68.8%)* |
484
+
485
+ ##### 2. Suite 3: Multi-Action Gates (`ChoiceGate` & `ScoreGate`)
486
+ Evaluating discrete 3-way routing (`ChoiceGate`, 6 items) and continuous 1–5 scoring monotonicity (`ScoreGate`, 6 items):
487
+
488
+ | Model & Device | Recurrent Loops | `ChoiceGate` Accuracy | `ScoreGate` Monotonicity | High Tier Mean | Med Tier Mean | Low Tier Mean | First-Token Latency |
489
+ | :--- | :---: | :---: | :---: | :---: | :---: | :---: | :---: |
490
+ | **Dory-4B (RTX 5090)** | $K=1$ | **6/6 (100.0%)** | 3/8 (37.5%) | 2.39 | 2.90 | 2.80 | 216.3 ms |
491
+ | **Dory-4B (RTX 5090)** | $K=2$ | **6/6 (100.0%)** | **6/8 (75.0%)** | **3.13** | **3.10** | **2.91** | 335.5 ms |
492
+ | **Dory-4B (RTX 5090)** | $K=4$ | **6/6 (100.0%)** | 3/8 (37.5%) | 2.68 | 3.27 | 3.15 | 628.9 ms |
493
+ | **Dory-4B (RTX 4070)** | $K=1$ | **6/6 (100.0%)** | 2/8 (25.0%) | 2.35 | 2.85 | 2.81 | 327.8 ms |
494
+ | **Dory-4B (RTX 4070)** | $K=2$ | **6/6 (100.0%)** | **5/8 (62.5%)** | **3.07** | **3.15** | **2.98** | 436.0 ms |
495
+ | **Dory-4B (RTX 4070)** | $K=4$ | **6/6 (100.0%)** | 3/8 (37.5%) | 2.70 | 3.31 | 3.14 | 809.1 ms |
496
+ | *Baseline Feed-Forward 4B (`gemma4:e4b`)* | *N/A* | *6/6 (100.0%)* | *3/8 (37.5%)* | *3.20* | *3.15* | *2.90* | *76.0 ms* |
497
+ | *Baseline Feed-Forward 14B (`qwen2.5:14b`)* | *N/A* | *6/6 (100.0%)* | *6/8 (75.0%)* | *4.25* | *3.10* | *1.85* | *115.0 ms* |
498
+
499
+ ##### 3. Suite 4: Long-Context Haystack & Hardware Throughput Scaling (RTX 5090 vs. RTX 4070)
500
+ Evaluating needle-in-a-haystack compliance across prompt lengths up to 16,000 tokens:
501
+
502
+ | Context Length | RTX 5090 ($K=1$) | RTX 4070 ($K=1$) | RTX 5090 ($K=2$) | RTX 4070 ($K=2$) | RTX 5090 Speedup | Correct Retrieval ($\Delta P > 0$) |
503
+ | :--- | :---: | :---: | :---: | :---: | :---: | :---: |
504
+ | **Short (~200 tok)** | 231.8 ms | 337.3 ms | 358.0 ms | 430.9 ms | 1.4x | Yes ($\Delta P = +0.134$) |
505
+ | **Medium (~1,000 tok)** | 293.0 ms | 1,153.2 ms | 435.0 ms | 1,761.0 ms | 3.9x | Yes ($\Delta P = +0.100$) |
506
+ | **Long (~4,000 tok)** | 894.1 ms | 3,552.1 ms | 1,374.3 ms | 5,546.2 ms | 4.0x | Yes ($\Delta P = +0.030$) |
507
+ | **Very Long (~8,000 tok)** | 1,769.4 ms | 6,584.0 ms | 2,741.0 ms | 10,432.1 ms | 3.8x | Edge ($\Delta P = -0.090$) |
508
+ | **Massive (~16,000 tok)** | **3,754.7 ms** | **13,928.6 ms** | **5,812.2 ms** | **22,172.2 ms** | **3.8x** | **Yes ($\Delta P = +0.095$)** |
509
+
510
+ ##### 4. Suite 1: 24-Item Multi-Domain Cascade Efficiency
511
+ - Across all configurations, the 3-layer cascade (`ASTGate >> LogitGate >> JudgeGate`) consistently outperformed the baseline standalone generative judge:
512
+ - **Baseline Standalone Generative Judge**: 9/24 to 12/24 accuracy (37.5%–50.0%), taking 109s–195s and consuming 960 output tokens.
513
+ - **Cascade (`on_ambiguous_only`)**: **14/24 to 16/24 accuracy (58.3%–66.7%)**, running in 91s–177s (**1.1x–1.3x wall-time speedup**) and saving **200–280 output tokens** per 24 items by short-circuiting clean passes at Layer 1 and AST violations at Layer 0.
514
+
515
+ #### Key Architectural Findings:
516
+ 1. **The $K=2$ Latent Recurrence Sweet Spot**:
517
+ - In both GPUs, recirculating hidden states through the recurrent block twice ($K=2$) delivers an immediate **+12.5% boost** in compound reasoning ($53.1\% \to 65.6\%$ on RTX 5090; $50.0\% \to 62.5\%$ on RTX 4070), elevating the compact 4B model within 1 item of the 14B dense model (`qwen2.5:14b` at 68.8%) with **zero generated output tokens**.
518
+ - Concurrently, `ScoreGate` pairwise monotonicity **doubles** ($37.5\% \to 75.0\%$).
519
+ - Increasing recurrence to $K=4$ causes a slight regression ($56.2\%$), replicating NVIDIA's findings that $K=2$ reaches optimal latent equilibrium for general semantic tasks, while excessive looping ($K=4$) can oversmooth embeddings on concise prompts.
520
+ 2. **Flawless Multi-Way Routing**:
521
+ - `ChoiceGate` achieved a perfect **100% (6/6)** routing accuracy across every single tested configuration ($K=1, 2, 4$ on both GPUs), proving that discrete routing logits are extremely stable in latent recurrent architectures.
522
+ 3. **Blackwell Memory Bandwidth Advantage**:
523
+ - On the massive 16,000-token haystack evaluation, the RTX 5090 completed the forward pass in **3.75s** ($K=1$) and **5.81s** ($K=2$), outperforming the RTX 4070 (13.9s and 22.2s) by **~3.8x**, demonstrating the substantial value of GDDR7 memory bandwidth for high-throughput zero-token gating.
524
+
525
+ ---
526
+
527
+ ### 6. Summary: When to Use Layer 1 (`LogitGate`) vs. Escalate to Layer 2 (`JudgeGate`)
528
+
529
+ - **Use Layer 1 (`LogitGate`) — First-Token Forward Pass ($O(1)$ Circuit Depth)**:
530
+ - **Semantic Rubric & Policy Compliance**: Factual groundedness against context, tone/safety compliance, PII/secret leak checks, and atomic requirement verification via `evaluate_batch`.
531
+ - **Discrete Routing & Classification (`ChoiceGate`)**: Selecting downstream agent tools, intent buckets, or workflow branches in ~40–90 ms.
532
+ - **Continuous Rubric Scoring (`ScoreGate`)**: Probability-weighted expected value scoring ($\mathbb{E}[S] = \sum s \cdot P(s)$) with symmetric scale reversal.
533
+ - **Escalate to Layer 2 (`JudgeGate`) — Autoregressive Generation**:
534
+ - **Multi-Step Deductive Reasoning**: Proof verification or multi-hop logic where conclusions depend on intermediate reasoning steps.
535
+ - **Complex Symbolic Arithmetic**: Calculations requiring scratchpad calculation or token-by-token recurrence (or route deterministic math checks to Layer 0 `ASTGate` / `ContractGate`).
536
+ - **Diagnostic Reporting**: When a human developer or logging pipeline needs an actionable explanation of *why* an artifact failed (or replay a CI failure locally via `logitgate explain`).
537
+
538
+ ---
539
+
540
+ ## System Requirements & Hardware Tiers
541
+
542
+ `LogitGate` adapts dynamically across hardware environments:
543
+
544
+ | Hardware Tier | Recommended Model | Backend Specifier / Config | Typical Single-Pass Latency | Target Workflows |
545
+ | :--- | :--- | :--- | :--- | :--- |
546
+ | **0-GPU CI Runners / Air-Gapped** | Offline Deterministic Stub | `stub://default` | **< 0.05 ms** | Unit tests, mock suites, CI smoke tests |
547
+ | **CPU-Only Laptops / Edge** | `gemma4:e4b` / `llama3.2:3b` | `ollama://localhost:11434/gemma4:e4b` (`options={"num_gpu": 0}`) | **~170 ms** | Local developer testing without discrete GPU |
548
+ | **8–12 GB VRAM Consumer GPU** | `qwen2.5:7b` / `gemma4:e4b` | `ollama://localhost:11434/gemma4:e4b` | **~40–45 ms** | Desktop development, real-time agent loops |
549
+ | **16–24 GB VRAM Workstation** | `qwen2.5-coder:14b` / `qwen2.5:14b` | `ollama://localhost:11434/qwen2.5-coder:14b` | **~40–50 ms** | Production evaluation suites, coding agents |
550
+ | **Cloud Inference / Hosted APIs** | `gpt-4o-mini` / `vLLM` | `openai://api.openai.com/v1` or `vllm://localhost:8000/v1` | **~60–120 ms** (network bounded) | High-concurrency enterprise pipelines |
551
+
552
+ ### 3 Deployment Topologies: Preventing KV-Cache Eviction & Thrashing
553
+
554
+ When deploying LLM evaluation pipelines, a common production failure mode is **KV-Cache Thrashing**: when a primary generation model (e.g., an agent synthesizing code) is interrupted by an evaluation judge loading into the same VRAM or context window, evicting the primary generator's KV-cache and forcing expensive full recomputation.
555
+
556
+ `LogitGate` supports three deployment topologies designed to prevent cache eviction:
557
+
558
+ 1. **Topology 1: Single-Model Shared KV-Cache (Batch Evaluation Suites)**
559
+ - Used when evaluating multiple criteria on the same candidate artifact.
560
+ - Using `evaluate_batch(candidate, rubrics)`, the candidate tokens are evaluated once. Subsequent rubric logit probes reuse the shared `[EVALUATION RUBRICS] + [CANDIDATE ARTIFACT]` prompt prefix in the KV-cache without evicting the context, reducing per-rubric latency to ~110ms.
561
+ 2. **Topology 2: Heterogeneous Dual-GPU Sidecar (High-Throughput Production)**
562
+ - **GPU 0**: Pinned exclusively to the primary generator model (e.g., `gemma4:26b` MoE or `gemma4:31b` Dense) with 16k–32k context. Its generation KV-cache is **never evicted**.
563
+ - **GPU 1**: Dedicated to a lightweight `LogitGate` sidecar (`qwen2.5:14b` or `gemma4:e4b` in ~8.7–9.4 GB VRAM, or `llama3.2:3b` in ~3.2 GB VRAM).
564
+ - Real-time gating queries complete in ~40–50ms (single-pass) or ~85–120ms (2-pass symmetric) over local IPC (`http://localhost:11435`) without contending for GPU 0's memory bandwidth.
565
+ 3. **Topology 3: Single-GPU Workstation + Pure-CPU `LogitGate` Sidecar (Memory-Constrained)**
566
+ - 100% of GPU VRAM is preserved for the primary generator model.
567
+ - Layer 1 `LogitGate` runs on host CPU with `options={"num_gpu": 0, "num_ctx": 2048}` in ~170ms (single-pass) using standard System RAM (~3.2 GB for 3B Q4 models like `qwen2.5:3b` / `llama3.2:3b`, or ~9.4 GB for `gemma4:e4b`).
568
+ - Clear passes short-circuit without GPU VRAM interference. Only ambiguous items or failures escalate to the GPU-backed `JudgeGate`.
569
+
570
+ ---
571
+
572
+ ## Role-Based Setup & Use-Case Guides
573
+
574
+ LogitGate is designed to fit directly into diverse software engineering and AI workflows across general and non-SDLC domains:
575
+
576
+ ### 1. CI/CD Final Merge Gate vs. Local Developer Inner Loop (Speed vs. Correctness)
577
+
578
+ In production engineering, **local iteration** and **CI/CD merge gates** have different priorities:
579
+ - **CI/CD is your final quality gate**: Correctness and minimizing false passes are paramount. However, you do not need to wait 5–20 seconds per test to generate a 400-token LLM essay when Layer 1 already reached a decisive, non-ambiguous conclusion (`P >= 0.85` pass or `P <= 0.20` fail).
580
+ - **Local execution is your fast inner loop**: Developers iterating on code or live agent routers want ~40–90ms GPU feedback (or ~170ms 1-pass triage on CPU-only laptops).
581
+
582
+ | Dimension | Local Inner-Loop / Live Agent Triage | CI/CD Final Merge Gate (Recommended) |
583
+ | :--- | :--- | :--- |
584
+ | **Primary Goal** | Fast developer feedback / low-latency routing | **High correctness & minimal false passes** without waiting for LLM essays on clear verdicts |
585
+ | **Preset & Debiasing** | `preset="balanced"` on GPU (`~86ms`), or `preset="fast_triage"` (`1-pass`, `~170ms`) on CPU-only laptops | **`preset="balanced"` or `"strict"` (`symmetric_debiasing=True`)** — always cancel prior token bias |
586
+ | **Multi-Part Rubrics** | Single rubric or `ChoiceGate` | **Atomic rubrics via `evaluate_batch(candidate, rubrics)`** (shared-prefix KV-cache reuse, avoids compound dilution) |
587
+ | **Layer 2 (`JudgeGate`) Trigger** | Omit `JudgeGate`, or `trigger="on_ambiguous_only"` | **`trigger="on_ambiguous_only"` + `save_on_fail=True`** (0 CoT tokens on decisive pass *or* decisive fail; only invokes `JudgeGate` to adjudicate ambiguous borderline cases) |
588
+
589
+ ```python
590
+ from logitgate import ASTGate, LogitGate, JudgeGate, OllamaBackend
591
+
592
+ # Pure CPU CI Runner configuration (0 GPU, ~3.2 GB RAM for 3B models / ~9.4 GB RAM for gemma4:e4b)
593
+ backend = OllamaBackend(
594
+ model="gemma4:e4b",
595
+ options={"num_gpu": 0, "num_thread": 4},
596
+ keep_alive="5m",
597
+ )
598
+
599
+ # Correctness-first CI Merge Gate:
600
+ # - Layer 0 catches syntax/import errors in <0.1ms (no LLM call)
601
+ # - Layer 1 runs full 2-pass symmetric debiasing (no CoT tokens on clear pass OR clear fail)
602
+ # - Layer 2 ONLY fires when Layer 1 is ambiguous (0.20 < P < 0.85)
603
+ ci_pipeline = (
604
+ ASTGate(syntax=True, forbidden_imports=["pickle", "subprocess"])
605
+ >> LogitGate(
606
+ rubric="Candidate code must be clean, secure, and handle edge cases.",
607
+ preset="balanced", # Full 2-pass symmetric log-odds debiasing for CI correctness
608
+ save_on_fail=True, # Saves .logitgate/failures/*.json on fail for local `logitgate explain`
609
+ backend=backend,
610
+ )
611
+ >> JudgeGate(
612
+ max_tokens=80,
613
+ trigger="on_ambiguous_only", # Skip generative essays on non-ambiguous verdicts
614
+ backend=backend,
615
+ )
616
+ )
617
+
618
+ candidate_code = "def add_numbers(a: int, b: int) -> int:\n return a + b\n"
619
+ verdict = ci_pipeline.evaluate(candidate_code)
620
+ assert verdict.passed, f"CI Gate Failed at {verdict.triggered_layer}: {verdict.reason}"
621
+ ```
622
+ - **Resource Footprint**: Runs in ~2.2–3.2 GB System RAM (`qwen2.5:3b` / `llama3.2:3b`) or ~9.4 GB System RAM (`gemma4:e4b`) with 0 VRAM overhead—fitting comfortably inside a standard 16 GB GitHub Actions (`ubuntu-latest`) VM.
623
+ - **Cost Savings**: Runs on standard CPU CI runners without requiring \$0.50–\$2.00/hr GPU instances.
624
+
625
+ #### Reproducing Non-Deterministic App Failures Locally (`VerdictSnapshot` & `logitgate explain`)
626
+
627
+ When testing non-deterministic LLM applications in CI using `trigger="on_ambiguous_only"` or `@check`, clear failures fail immediately at Layer 1 without generating a long critique in CI. However, if a developer re-runs their non-deterministic application locally to debug, the LLM may generate a different output, making reproduction difficult.
628
+
629
+ LogitGate solves this with deterministic **Verdict Snapshots**:
630
+ 1. When a test fails in CI (with `LOGITGATE_SAVE_FAILURES=1` or `@check(save_snapshot=True)`), LogitGate freezes the exact candidate output, rubric, and telemetry to `.logitgate/failures/fail_<timestamp>_<test>_<id>.json` (and updates `.logitgate/failures/latest.json`).
631
+ 2. Developers can replay and diagnose the exact failure locally with a single CLI command without re-running their non-deterministic application:
632
+
633
+ ```bash
634
+ # Replay and explain the latest failure with full System-2 reasoning
635
+ logitgate explain
636
+
637
+ # Or explain a specific failure snapshot with custom tokens
638
+ logitgate explain .logitgate/failures/fail_20261102_150648_test_rag_a1b2c3d4.json --max-tokens 150
639
+ ```
640
+
641
+ Programmatic replay and inspection via Python:
642
+ ```python
643
+ from logitgate import VerdictSnapshot
644
+
645
+ # Load frozen snapshot from CI
646
+ snapshot = VerdictSnapshot.load(".logitgate/failures/latest.json")
647
+
648
+ # Re-run fast Layer-1 logit evaluation on the frozen candidate
649
+ replay_verdict = snapshot.replay()
650
+
651
+ # Or generate a deep Layer-2 diagnostic critique with reasoning enabled
652
+ explanation = snapshot.explain(model="qwen2.5-coder:14b", think=True)
653
+ print(explanation.reason)
654
+ ```
655
+
656
+ ---
657
+
658
+ ### 2. RAG & Chatbot Engineers (Hallucination & Groundedness Gating)
659
+ Detect hallucinations and verify factual groundedness before streaming an answer to the end user:
660
+ ```python
661
+ from logitgate import ContractGate, LogitGate
662
+
663
+ retrieved_docs = "LogitGate v0.1.0 requires Python 3.10 or higher and supports Ollama, vLLM, and OpenAI."
664
+ generated_response = "LogitGate v0.1.0 supports Python 3.10+ and runs on Ollama, vLLM, and OpenAI."
665
+
666
+ # Layer 0 ensures reasonable length bounds in 0ms; Layer 1 verifies grounding in ~45ms
667
+ rag_gate = (
668
+ ContractGate(min_length=20, max_length=2000)
669
+ >> LogitGate(
670
+ rubric="Does the candidate answer strictly contain only facts asserted in the context snippet?",
671
+ preset="balanced",
672
+ )
673
+ )
674
+
675
+ context_payload = f"[CONTEXT]\n{retrieved_docs}\n\n[ANSWER]\n{generated_response}"
676
+ verdict = rag_gate.evaluate(context_payload)
677
+
678
+ if not verdict.passed:
679
+ # Trigger fallback or retrieve secondary sources
680
+ generated_response = "I cannot verify that from the documentation. Let me connect you with an agent."
681
+ ```
682
+
683
+ ---
684
+
685
+ ### 3. AI Agent & LangGraph Builders (Fast Guardrails & Routing)
686
+ Enforce structured JSON output contracts in **<0.1ms** and perform ~40–90ms conditional routing:
687
+ ```python
688
+ from pydantic import BaseModel
689
+ from logitgate import ContractGate, ChoiceGate
690
+
691
+ class ToolCallPayload(BaseModel):
692
+ tool_name: str
693
+ arguments: dict
694
+ confirm_action: bool
695
+
696
+ # Layer 0 validates JSON schema in <0.1ms; Layer 1 routes intent in ~40-90ms
697
+ agent_router = (
698
+ ContractGate(json_schema=ToolCallPayload)
699
+ >> ChoiceGate(
700
+ question="Select the appropriate downstream handler for this user intent:",
701
+ options={
702
+ "A": "Database Query Execution (read-only safe queries)",
703
+ "B": "Account Management & Authentication changes",
704
+ "C": "General Customer Q&A Response",
705
+ },
706
+ )
707
+ )
708
+
709
+ agent_raw_json = '{"tool_name": "run_sql", "arguments": {"query": "SELECT count(*) FROM users"}, "confirm_action": false}'
710
+ verdict = agent_router.evaluate(agent_raw_json)
711
+ next_node = {"A": "db_node", "B": "auth_node", "C": "qa_node"}[verdict.choice]
712
+ ```
713
+
714
+ ---
715
+
716
+ ### 4. QA & Evaluation Engineers (Pytest & Multi-Criteria Rubrics)
717
+ Auto-calibrate model temperatures and execute multi-criteria rubrics with shared KV-cache:
718
+ ```bash
719
+ # Calibrate your model's temperature on an 8-item micro-dataset
720
+ logitgate calibrate --backend "ollama://localhost:11434" --model "qwen2.5:14b"
721
+ ```
722
+
723
+ ```python
724
+ from logitgate import LogitGate
725
+
726
+ evaluator = LogitGate(
727
+ rubric="Base rubric",
728
+ logit_temperature="auto", # Automatically uses cached calibrated temperature
729
+ )
730
+
731
+ rubrics = [
732
+ "Is the customer support reply polite and professional?",
733
+ "Does the assistant enforce multi-factor authentication before updating credentials?",
734
+ "Does the response adhere to the company return and refund policy?",
735
+ ]
736
+
737
+ support_transcript = (
738
+ "Customer: Please update my account email and process a refund for order #402.\n"
739
+ "Agent: I would be happy to help! Before I can update your email, please complete "
740
+ "the 2FA verification sent to your phone. Your refund for order #402 has been initiated "
741
+ "per our 30-day return policy."
742
+ )
743
+
744
+ # Evaluates all 3 rubrics in a single batch reusing the shared prompt prefix in KV-cache
745
+ verdicts = evaluator.evaluate_batch(support_transcript, rubrics)
746
+ for r, v in zip(rubrics, verdicts):
747
+ print(f"[{'PASS' if v.passed else 'FAIL'}] P={v.probability:.2f} | {r}")
748
+ ```
749
+
750
+ ---
751
+
752
+ ## Best Practices: Prompting, Context Length, & Model Sizing
753
+
754
+ ### 1. Document Context Length & When to Chunk
755
+ - **Zero-Chunking Sweet Spot (Up to 16,000–32,000 Tokens)**: As shown in our [Needle-in-a-Haystack benchmarks](#2-context-length-scaling--needle-in-a-haystack-boundary-200-to-16000-tokens), modern causal transformers (`gemma4`, `qwen2.5`) maintain strong probability separation ($\Delta P > 0.993$) up to **16,000+ tokens** without manual chunking, and sliding-window/MoE architectures scale cleanly to **32k–64k tokens** in VRAM.
756
+ - **When to Chunk (50,000+ Token Codebases or Books)**: If a document exceeds your model's configured context window (`num_ctx`) or exceeds 32k–50k tokens on a dense attention model, split the document into logical sections or files and call `gate.evaluate(chunk)` on each section independently.
757
+ - **Multi-Rubric KV Sharing (`evaluate_batch`)**: `gate.evaluate_batch(candidate, rubrics)` is designed for evaluating **multiple atomic rubrics against a single candidate artifact** (sharing the `[CANDIDATE ARTIFACT]` root prefix across all $K$ rubrics in the KV-cache), rather than evaluating multiple documents against one rubric.
758
+
759
+ ### 2. Best Practice vs. Anti-Pattern: Candidate-Prefix Isolated Batching (`evaluate_batch`)
760
+
761
+ When evaluating complex systems, users often wonder whether to write one large prompt or multiple smaller ones, and how to execute them efficiently:
762
+
763
+ #### The Anti-Patterns
764
+ 1. **Monolithic Compound Rubrics**: Cramming multiple orthogonal requirements into a single giant rubric prompt (e.g. *"Ensure valid syntax, Google docstrings, full type hints, no mutable defaults, and SQL safety"*). When a candidate complies with 4 of 5 requirements but subtly violates 1 (e.g. an omitted return type annotation on a typed function), first-token logits experience signal dilution, resulting in $P \approx 0.82–0.89$ which can either slip through as an uninspected false pass or trigger inconsistent escalation.
765
+ 2. **Monolithic Prompt-Prefix Concatenation**: Concatenating all $K$ rubrics together into a single shared prompt block (`[EVALUATION RUBRICS]\nRubric #1...\nRubric #K...`) preceding the candidate. When evaluating 50 to 500 rubrics, this injects thousands of rubric tokens before the candidate artifact, blowing the context window on lightweight models and causing severe **cross-rubric attention contamination** (attention heads judging Rubric #1 become distracted by text in Rubric #47).
766
+
767
+ #### The Best Practice: Candidate-Prefix Isolated Batching
768
+ LogitGate solves both problems via **Candidate-Prefix Isolated Batching** (`compile_batch_binary_prompt(..., query_first=False)`):
769
+
770
+ ```
771
+ ┌─────────────────────────────────────────────────────────────┐
772
+ │ Token 0: Shared Static Prefix (95–99% of prompt tokens) │
773
+ │ [CANDIDATE ARTIFACT] │
774
+ │ {candidate} │ ◄── KV-Cached ONCE
775
+ └──────────────────────────────┬──────────────────────────────┘
776
+ │
777
+ ┌───────────────────────┼───────────────────────┐
778
+ ▼ ▼ ▼
779
+ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐
780
+ │ Isolated │ │ Isolated │ │ Isolated │
781
+ │ Suffix #1 │ │ Suffix #2 │ │ Suffix #K │
782
+ │ Rubric #1 │ │ Rubric #2 │ │ Rubric #K │
783
+ │ Mapping P1/P2│ │ Mapping P1/P2│ │ Mapping P1/P2│
784
+ └──────────────┘ └──────────────┘ └──────────────┘
785
+ ```
786
+
787
+ - **Candidate Anchored at Token 0**: The candidate artifact (500 to 10,000+ tokens) forms the shared static root prefix across all $K$ rubrics and both forward/reverse debiasing passes ($2K$ forward passes total).
788
+ - **100% Suffix Rubric Isolation**: Each rubric is appended in complete isolation at the very end of the prompt. It never sees or attends to any other rubric.
789
+ - **Zero Cross-Rubric Attention Contamination**: Because causal attention is strictly unidirectional, the candidate context cannot attend forward to future tokens. The candidate representation is computed and KV-cached once. Each isolated rubric query suffix only attends back to the candidate document.
790
+ - **Zero Context Bloat & Linear Scalability**: Evaluating 2 rubrics or 500 rubrics requires the exact same context window length ($|\text{candidate}| + |\text{rubric}_k| + |\text{mapping}|$).
791
+ - **Near-Instant Execution**: Across all $2K$ forward passes, inference engines (vLLM, Ollama, llama.cpp) hit the prefix cache for 95–99% of total tokens, dropping per-rubric warm latency to ~20–40ms.
792
+
793
+ ### 3. Defense-in-Depth: Combining Temperature Calibration with Strict Operational Thresholds
794
+
795
+ A common question in production gating is whether temperature calibration makes strict confidence thresholds redundant, or vice versa. In LogitGate, they serve two distinct, complementary functions:
796
+
797
+ 1. **Temperature Calibration ($T$) Repairs Intrinsic Model Distortion**:
798
+ Different model families have distinct confidence distributions. An uncalibrated model might output a raw probability of $0.93$ when its actual empirical precision on that task is only $75\%$, or conversely remain underconfident ($P=0.79$) on unambiguous passes. Post-hoc temperature scaling ($\bar{L} / T$) rescales the symmetric log-odds so that a reported $P=0.85$ mathematically corresponds to an empirical 85% probability of correctness. Calibration normalizes the meaning of confidence across diverse models (`gemma4:e4b`, `qwen2.5:14b`, `llama3`).
799
+ 2. **Operational Thresholds (`pass_threshold`, `fail_threshold`) Enforce Risk Tolerance**:
800
+ Operational thresholds govern the system's escalation policy (the width of the ambiguity/escalation band):
801
+ - **`preset="fast_triage"` (`pass_threshold=0.80`, `fail_threshold=0.20`)**: Maximizes short-circuiting speed for local developer loops, agent routing, and high-throughput classification.
802
+ - **`preset="strict"` (`pass_threshold=0.90`, `fail_threshold=0.25`)**: Enforces defense-in-depth for mission-critical CI merge gates, financial transactions, or automated security reviews. Any candidate with less than 90% calibrated confidence is classified as `AMBIGUOUS` and escalated to Layer 2 (`JudgeGate`) for full step-by-step System-2 diagnostic critique.
803
+
804
+ **Conclusion**: Temperature calibration ensures that $P=0.90$ actually means 90% certainty; strict operational thresholds ensure that your pipeline never bypasses System-2 reasoning on anything less than 90% certainty.
805
+
806
+ ### 4. Escalation Mechanics: How Symmetric Log-Odds Handle Model Uncertainty
807
+ - **Decisive Signal**: When a model is confident that an artifact passes, both forward ($L_1 = s + b$) and reverse ($L_2 = s - b$) log-odds are positive, yielding calibrated probability $P \ge 0.85$ (fast-path pass, no Layer 2 critique).
808
+ - **Decisive Failure**: When an artifact clearly violates the rubric, both forward and reverse log-odds are negative, yielding $P \le 0.20$ (decisive failure).
809
+ - **Ambiguity & Escalation**: When small models (e.g. 3B–4B) or complex edge cases yield borderline log-odds (between 0.20 and 0.85), LogitGate flags the item as `AMBIGUOUS` and triggers Layer 2 (`JudgeGate`) to generate an autoregressive critique.
810
+
811
+ ---
812
+
813
+ ## Research Foundations & Academic Citations
814
+
815
+ LogitGate builds upon established methods in calibration, logit debiasing, and LLM evaluation:
816
+
817
+ ### Key Design Decisions in `LogitGate`
818
+ 1. **Shared-Model 3-Layer Cascade**: Uses the existing generator model instance for both gating and diagnostics without loading a dedicated secondary judge model into VRAM.
819
+ 2. **Candidate-Prefix Isolated KV Compilation (`compile_batch_binary_prompt`)**: Anchors the candidate artifact at token 0 as the shared static root prefix across all $K$ rubrics, evaluating each rubric in 100% isolation as a query suffix without cross-rubric attention contamination or context bloat.
820
+ 3. **Log-Odds Space Symmetric Inversion**: Cancels additive prior token bias in log-odds space ($\bar{L} = \frac{L_1 + L_2}{2T}$) rather than probability averaging.
821
+ 4. **Missing-Token Dynamic Floor**: Bounds unobserved token logprobs using residual probability mass $\min(\min_i \text{logprob}_i, \ln(1 - \sum P_i))$, avoiding distortion from arbitrary $-99.0$ constants.
822
+ 5. **Elastic Recurrent Latent Reasoning**: Integrates latent recurrent layer-looping architectures (`RecurrentPyTorchBackend`), recirculating hidden states through recurrent blocks (`num_loops`) to expand circuit depth before emitting first-token logits.
823
+
824
+ ### Foundational Literature Credited
825
+
826
+ 1. **Pretraining Token Prior Bias & Calibration**:
827
+ - Zhao, T. Z., Wallace, E., Feng, S., Klein, D., & Singh, S. (2021). *"Calibrate Before Use: Improving Few-Shot Performance of Language Models"*. **ICML 2021**. [arXiv:2102.09690](https://arxiv.org/abs/2102.09690).
828
+ - *Contribution to LogitGate*: Demonstrates that large language models suffer from severe majority-label, recency, and surface-form token priors (such as inherently favoring token `'A'` over `'B'`).
829
+
830
+ 2. **Positional & Label Permutation Bias in LLM Judges**:
831
+ - Zheng, L., Chiang, W.-L., Sheng, Y., Zhuang, S., Wu, Z., Zhuang, Y., Lin, Z., Li, Z., Li, D., Xing, E. P., Zhang, H., Gonzalez, J. E., & Stoica, I. (2023). *"Judging LLM-as-a-Judge with MT-Bench and Chatbot Arena"*. **NeurIPS 2023**. [arXiv:2306.05685](https://arxiv.org/abs/2306.05685).
832
+ - *Contribution to LogitGate*: Establishes the necessity of symmetric permutation testing to cancel order bias and label preference in LLM evaluations.
833
+
834
+ 3. **Probability-Weighted Continuous Expected Scoring ($\mathbb{E}[S] = \sum s \cdot P(s)$)**:
835
+ - Liu, Y., Iter, D., Xu, Y., Wang, S., Xu, R., & Zhu, C. (2023). *"G-Eval: NLG Evaluation using GPT-4 with Better Human Alignment"*. **EMNLP 2023**. [arXiv:2303.16634](https://arxiv.org/abs/2303.16634).
836
+ - *Contribution to LogitGate*: Provides the mathematical foundation for `ScoreGate`, translating discrete first-token probability distributions over score tokens into smooth, continuous expected value metrics.
837
+
838
+ 4. **Post-Hoc Temperature Scaling & Expected Calibration Error (ECE)**:
839
+ - Guo, C., Pleiss, G., Sun, Y., & Weinberger, K. Q. (2017). *"On Calibration of Modern Neural Networks"*. **ICML 2017**. [arXiv:1706.04599](https://arxiv.org/abs/1706.04599).
840
+ - *Contribution to LogitGate*: Forms the theoretical basis of `fit_calibration()`, using temperature scaling to align logit confidence with true empirical accuracy and minimize Brier score.
841
+
842
+ 5. **System-1 Single-Token Decision Benchmarking**:
843
+ - Deußer, T., Sparrenberg, L., & Sifa, R. (2026). *"Evaluating and Benchmarking the System One Model Jev"*. [arXiv:2609.37647](https://arxiv.org/abs/2609.37647).
844
+ - *Contribution to LogitGate*: Benchmarks fast, single-token System-1 evaluation pipelines against heavy System-2 generative reasoning judges.
845
+
846
+ 6. **Recurrent Depth & Universal Transformers**:
847
+ - Dehghani, M., Gouws, S., Vinyals, O., Uszkoreit, J., & Kaiser, Ł. (2019). *"Universal Transformers"*. **ICLR 2019**. [arXiv:1807.03819](https://arxiv.org/abs/1807.03819).
848
+ - *Contribution to LogitGate*: Establishes the theoretical foundation for elastic layer-looping (`num_loops`), enabling iterative latent computation in hidden-state space prior to vocabulary projection.
849
+
850
+ ### BibTeX Citation
851
+
852
+ ```bibtex
853
+ @software{logitgate2026,
854
+ author = {Jason Bradley},
855
+ title = {LogitGate: Calibrated First-Token Logit Evaluation and Cascaded Routing for LLMs},
856
+ year = {2026},
857
+ version = {0.1.0},
858
+ url = {https://github.com/jasonbdly/LogitGate},
859
+ license = {Apache-2.0}
860
+ }
861
+ ```
862
+
863
+ ---
864
+
865
+ ## Mathematical Foundations
866
+
867
+ ### 1. Symmetric Log-Odds Permutation Debiasing
868
+
869
+ Suppose token `'A'` has an extreme pretraining prior bias $+b$, and the true underlying signal is $s$:
870
+
871
+ - **Pass 1** ($A=\text{Pass}, B=\text{Fail}$):
872
+ $$L_1 = \text{logit}(A) - \text{logit}(B) = s + b$$
873
+
874
+ - **Pass 2** ($B=\text{Pass}, A=\text{Fail}$):
875
+ $$L_2 = \text{logit}(B) - \text{logit}(A) = s - b$$
876
+
877
+ LogitGate combines the forward and reverse passes in **log-odds space**:
878
+ $$\bar{L} = \frac{L_1 + L_2}{2 \cdot T} = \frac{(s + b) + (s - b)}{2 \cdot T} = \frac{s}{T}$$
879
+
880
+ The prior bias $b$ cancels out completely:
881
+ $$P(\text{Pass}) = \sigma(\bar{L}) = \frac{1}{1 + e^{-\bar{L}}}$$
882
+
883
+ #### Empirical Contrast
884
+ For a true signal $s = +2.0$ ($\sigma(2.0) \approx 0.8808$) contaminated by an extreme prior bias $b = +5.0$:
885
+ - **Naive Probability Averaging**:
886
+ $$P_1 = \sigma(7.0) \approx 0.9991, \quad P_2 = \sigma(-3.0) \approx 0.0474 \implies \bar{P} = 0.5233 \quad (\text{Coin Flip / Failed})$$
887
+ - **LogitGate Log-Odds Debiasing**:
888
+ $$\bar{L} = \frac{7.0 + (-3.0)}{2} = 2.0 \implies \sigma(2.0) = \mathbf{0.8808} \quad (\text{Exact True Signal Recovered!})$$
889
+
890
+ ---
891
+
892
+ ### 2. Prefix-Preserving Attention Inversion
893
+
894
+ Causal transformer attention requires the candidate artifact to attend to the evaluation rubric. LogitGate places the rubric and candidate document first, isolating the label mapping to the very end:
895
+
896
+ ```
897
+ [EVALUATION RUBRIC]
898
+ {rubric}
899
+
900
+ [CANDIDATE ARTIFACT]
901
+ {candidate}
902
+
903
+ [DECISION MAPPING]
904
+ A: The candidate artifact complies fully with the rubric.
905
+ B: The candidate artifact violates the rubric or has defects.
906
+ Respond with a single character (A or B).
907
+ Verdict:
908
+ ```
909
+
910
+ Because Pass 1 and Pass 2 share an identical prefix up to `[DECISION MAPPING]`, the rubric and candidate context remain in the GPU KV-cache so Pass 2 only evaluates the short `[DECISION MAPPING]` suffix.
911
+
912
+ ---
913
+
914
+ ### 3. Missing-Token Bounded Floor
915
+
916
+ When target tokens (e.g. `'B'`) do not appear in the top-$K$ logprobs returned by an API, assigning arbitrary $-99.0$ cliffs distorts the symmetric mean. LogitGate dynamically computes the theoretical probability ceiling:
917
+
918
+ $$\text{floor} = \min\left(\min_{i} \text{logprob}_i, \, \ln\max\left(1.0 - \sum_{i} P_i, \, 10^{-6}\right)\right)$$
919
+
920
+ This bounds missing tokens strictly to the residual unobserved probability mass.
921
+
922
+ ---
923
+
924
+ ## 3-Layer Cascaded Router Architecture
925
+
926
+ ```
927
+ Candidate Artifact
928
+ │
929
+ ▼
930
+ ┌──────────────────────────────────────────────────┐
931
+ │ Layer 0: │ Syntax / DAG Cycle / Forbidden Import
932
+ │ ASTGate ├─────────────────────────────────────────► [FAIL: no LLM call, ~0.04ms]
933
+ └────────────────────────┬─────────────────────────┘
934
+ │ Passed
935
+ ▼
936
+ ┌──────────────────────────────────────────────────┐ P >= pass_threshold (>= 0.85)
937
+ │ Layer 1: ├─────────────────────────────────────────► [PASS: 0 CoT tokens, ~40–120ms]
938
+ │ LogitGate │
939
+ └────────────────────────┬─────────────────────────┘ P <= fail_threshold (<= 0.20)
940
+ │ Ambiguous └─────────────────────────────────────► [FAIL: 0 CoT tokens, ~40–120ms]
941
+ ▼
942
+ ┌──────────────────────────────────────────────────┐
943
+ │ Layer 2: │ Escalated Generative Critique
944
+ │ JudgeGate ├─────────────────────────────────────────► [Actionable Diagnostic Report]
945
+ └──────────────────────────────────────────────────┘
946
+ ```
947
+
948
+ ---
949
+
950
+ ## Installation
951
+
952
+ ```bash
953
+ # Core package (offline-ready, zero dependencies except pydantic & httpx)
954
+ pip install logitgate
955
+
956
+ # With all optional integrations (OpenAI, DeepEval, LangGraph, Pytest)
957
+ pip install "logitgate[all]"
958
+
959
+ # With PyTorch elastic recurrent layer-looping (NVIDIA Dory & Universal Transformers)
960
+ pip install "logitgate[recurrent]"
961
+ ```
962
+
963
+ ---
964
+
965
+ ## Complete Copy-Pasteable Examples
966
+
967
+ ### 1. Universal Configuration & Environment Variables
968
+
969
+ Switch backends or thresholds across your entire application or test suite globally without hardcoding parameters in individual gates:
970
+
971
+ ```python
972
+ import logitgate
973
+
974
+ # Configure defaults globally across all gates:
975
+ logitgate.configure(
976
+ backend="ollama://localhost:11434/gemma4:e4b",
977
+ pass_threshold=0.85,
978
+ fail_threshold=0.20,
979
+ logit_temperature=1.0,
980
+ )
981
+
982
+ # Any gate instantiated without explicit backend/thresholds inherits these defaults:
983
+ from logitgate import LogitGate
984
+ gate = LogitGate("Candidate response must follow security best practices.")
985
+
986
+ # Or control your entire evaluation pipeline via environment variables (zero code changes):
987
+ # export LOGITGATE_BACKEND="ollama://localhost:11434/gemma4:e4b"
988
+ # export LOGITGATE_PASS_THRESHOLD="0.85"
989
+ # export LOGITGATE_FAIL_THRESHOLD="0.20"
990
+
991
+ # Reset anytime to defaults (offline stub://default):
992
+ logitgate.reset_config()
993
+ ```
994
+
995
+ ---
996
+
997
+ ### 2. 30-Second Quickstart (3-Layer Cascade)
998
+
999
+ ```python
1000
+ from logitgate import ASTGate, LogitGate, JudgeGate
1001
+
1002
+ # Compose the 3-layer pipeline using the >> operator
1003
+ pipeline = (
1004
+ ASTGate(syntax=True, forbidden_imports=["subprocess", "os.system"])
1005
+ >> LogitGate(
1006
+ rubric="Candidate code must be strictly typed and include clear docstrings.",
1007
+ pass_threshold=0.85,
1008
+ fail_threshold=0.20,
1009
+ backend="ollama://localhost:11434/qwen2.5-coder:14b",
1010
+ )
1011
+ >> JudgeGate(trigger="on_ambiguous_or_fail")
1012
+ )
1013
+
1014
+ candidate_code = """
1015
+ def calculate_velocity(distance: float, time_elapsed: float) -> float:
1016
+ \"\"\"Calculates average velocity in meters per second.\"\"\"
1017
+ if time_elapsed <= 0:
1018
+ raise ValueError("time_elapsed must be positive")
1019
+ return distance / time_elapsed
1020
+ """
1021
+
1022
+ verdict = pipeline.evaluate(candidate_code)
1023
+
1024
+ if verdict:
1025
+ print(f"Passed at {verdict.triggered_layer}! Latency: {verdict.total_latency_ms:.1f}ms (Tokens: {verdict.total_tokens_generated})")
1026
+ else:
1027
+ print(f"Failed at {verdict.triggered_layer}: {verdict.reason}")
1028
+ ```
1029
+
1030
+ ---
1031
+
1032
+ ### 3. Multi-Rubric Batch Evaluation with Shared-Prefix KV Caching
1033
+
1034
+ Evaluate multiple rubrics against the same candidate artifact while sharing the `[EVALUATION RUBRICS] + [CANDIDATE ARTIFACT]` prefix in the KV-cache:
1035
+
1036
+ ```python
1037
+ from logitgate import LogitGate
1038
+
1039
+ gate = LogitGate(
1040
+ rubric="Shared context evaluator",
1041
+ backend="ollama://localhost:11434/qwen2.5-coder:14b",
1042
+ )
1043
+
1044
+ rubrics = [
1045
+ "1. Code contains comprehensive type hints.",
1046
+ "2. All exceptions are handled explicitly.",
1047
+ "3. No security vulnerabilities or unsafe shell invocations.",
1048
+ "4. Functions include concise, accurate docstrings.",
1049
+ ]
1050
+
1051
+ candidate = """
1052
+ def fetch_user_record(user_id: str) -> dict:
1053
+ \"\"\"Fetches user metadata from the storage engine.\"\"\"
1054
+ if not user_id.isalnum():
1055
+ raise ValueError("Invalid user_id format")
1056
+ return {"id": user_id, "active": True}
1057
+ """
1058
+
1059
+ # Evaluates all 4 rubrics with forward/reverse debiasing using 1 shared prefix
1060
+ verdicts = gate.evaluate_batch(candidate, rubrics)
1061
+
1062
+ for idx, v in enumerate(verdicts, 1):
1063
+ status = "PASS" if v.passed else "FAIL"
1064
+ print(f"Rubric #{idx}: [{status}] (P={v.probability:.4f})")
1065
+ ```
1066
+
1067
+ ---
1068
+
1069
+ ### 4. Discrete Routing (`ChoiceGate`) & Continuous Scoring (`ScoreGate`)
1070
+
1071
+ #### Discrete K-ary Routing (`ChoiceGate`)
1072
+ ```python
1073
+ from logitgate import ChoiceGate
1074
+
1075
+ router = ChoiceGate(
1076
+ question="Select the optimal storage architecture for high-throughput write-heavy workloads:",
1077
+ options={
1078
+ "A": "Append-only LSM-Tree with SSTables (Log-Structured Merge-Tree)",
1079
+ "B": "In-memory B-Tree with periodic synchronous disk checkpoints",
1080
+ "C": "Relational table with unindexed foreign key cascades",
1081
+ },
1082
+ backend="ollama://localhost:11434/qwen2.5-coder:14b",
1083
+ )
1084
+
1085
+ verdict = router.evaluate("Workload profile: 100,000 ingest events/sec, append-heavy, rare point reads.")
1086
+ print(f"Selected Architecture: {verdict.choice} (P={verdict.probability:.4f})")
1087
+ print(f"All Option Probabilities: {verdict.choice_probabilities}")
1088
+ ```
1089
+
1090
+ #### Continuous Rubric Scoring (`ScoreGate`)
1091
+ Computes continuous expected score $\mathbb{E}[S] = \sum_{s=1}^5 s \cdot P(s)$ with symmetric scale inversion:
1092
+ ```python
1093
+ from logitgate import ScoreGate
1094
+
1095
+ scorer = ScoreGate(
1096
+ rubric="Score API architectural documentation quality from 1 (unusable) to 5 (production-grade).",
1097
+ min_score=1,
1098
+ max_score=5,
1099
+ threshold=4.0,
1100
+ symmetric_debiasing=True, # Evaluates both 1..5 and 5..1 to cancel anchoring bias
1101
+ backend="ollama://localhost:11434/qwen2.5-coder:14b",
1102
+ )
1103
+
1104
+ candidate_documentation = """
1105
+ # Authentication API (v2)
1106
+ - **Endpoint**: `POST /v2/auth/token`
1107
+ - **Request Body**: `{"client_id": "string", "client_secret": "string"}`
1108
+ - **Responses**: `200 OK` (returns JWT + expiry), `401 Unauthorized`, `429 Too Many Requests`.
1109
+ """
1110
+
1111
+ verdict = scorer.evaluate(candidate_documentation)
1112
+ print(f"Continuous Expected Score: {verdict.score:.2f} / 5.0 (Passed: {verdict.passed})")
1113
+ ```
1114
+
1115
+ ---
1116
+
1117
+ ### 5. Post-Hoc Temperature Calibration (`fit_calibration`)
1118
+
1119
+ Optimize post-hoc temperature $T^*$ on validation samples to minimize Brier score and Expected Calibration Error (ECE):
1120
+
1121
+ ```python
1122
+ from logitgate import fit_calibration
1123
+
1124
+ # Validation dataset: (forward_log_odds, reverse_log_odds, ground_truth_label)
1125
+ validation_samples = [
1126
+ (+2.1, +1.8, 1),
1127
+ (-1.5, -1.9, 0),
1128
+ (+0.4, +0.2, 1),
1129
+ (-0.8, -0.6, 0),
1130
+ ]
1131
+
1132
+ result = fit_calibration(validation_samples, min_temp=0.1, max_temp=5.0)
1133
+
1134
+ print(f"Optimal Temperature: T* = {result.optimal_temperature:.3f}")
1135
+ print(f"Brier Score: {result.brier_score_before:.4f} -> {result.brier_score_after:.4f}")
1136
+ print(f"Expected Calibration Error (ECE): {result.ece_before:.4f} -> {result.ece_after:.4f}")
1137
+ ```
1138
+
1139
+ ---
1140
+
1141
+ ### 6. Command-Line Interface (CLI)
1142
+
1143
+ ```bash
1144
+ # Evaluate a candidate text directly against a rubric
1145
+ logitgate eval \
1146
+ --rubric "Response must not contain toxic or harmful instructions" \
1147
+ --candidate "To reset your password, visit account settings." \
1148
+ --threshold 0.85
1149
+
1150
+ # Evaluate candidate from a file with Layer 0 AST syntax check and JSON output
1151
+ logitgate eval \
1152
+ --rubric "Code must be production-ready and fully typed" \
1153
+ --file ./src/app.py \
1154
+ --ast-syntax \
1155
+ --backend "ollama://localhost:11434/qwen2.5-coder:14b" \
1156
+ --json
1157
+
1158
+ # Pipe candidate directly via standard input
1159
+ cat schema.json | logitgate eval --rubric "Must be valid JSON schema"
1160
+ ```
1161
+
1162
+ ---
1163
+
1164
+ ### 7. Framework Integrations
1165
+
1166
+ #### Pytest Integration (`@check`)
1167
+ ```python
1168
+ import pytest
1169
+ from logitgate import check
1170
+
1171
+ @check(rubric="Function output must be valid JSON with key 'status' equal to 'success'", threshold=0.90)
1172
+ def test_user_creation_api():
1173
+ return '{"status": "success", "user_id": "usr_99823"}'
1174
+ ```
1175
+
1176
+ #### DeepEval Integration (`LogitGateSystemOneModel` & `LogitGateMetric`)
1177
+ ```python
1178
+ from deepeval.metrics import JevEval
1179
+ from deepeval.test_case import LLMTestCase
1180
+ from logitgate.integrations.deepeval import LogitGateSystemOneModel, LogitGateMetric
1181
+
1182
+ # 1. Use as a fast System-1 judge model for JevEval
1183
+ system_one = LogitGateSystemOneModel(
1184
+ model_name="qwen2.5-coder:14b",
1185
+ api_base="http://localhost:11434",
1186
+ )
1187
+
1188
+ metric = JevEval(
1189
+ name="Security Baseline Check",
1190
+ questions=[{"statement": "Artifact does not invoke raw shell commands"}],
1191
+ system_one_model=system_one,
1192
+ )
1193
+
1194
+ # 2. Or use directly as a standalone DeepEval metric
1195
+ fast_metric = LogitGateMetric(
1196
+ rubric="Summary accurately reflects source text without hallucinations",
1197
+ threshold=0.85,
1198
+ )
1199
+ ```
1200
+
1201
+ #### LangGraph Integration (`as_conditional_edge`)
1202
+ ```python
1203
+ from typing import TypedDict
1204
+ from langgraph.graph import StateGraph
1205
+ from logitgate import LogitGate
1206
+ from logitgate.integrations.langgraph import as_conditional_edge
1207
+
1208
+ class AgentState(TypedDict):
1209
+ content: str
1210
+
1211
+ gate = LogitGate(rubric="Is the generated response safe and helpful?")
1212
+
1213
+ # Creates a fast routing function extracting 'content' from graph state
1214
+ route_verdict = as_conditional_edge(gate, pass_node="publish_response", fail_node="human_escalation")
1215
+
1216
+ workflow = StateGraph(AgentState)
1217
+ workflow.add_conditional_edges("generator", route_verdict)
1218
+ ```
1219
+
1220
+ ---
1221
+
1222
+ ## Contributing
1223
+
1224
+ We welcome contributions! Please see [CONTRIBUTING.md](CONTRIBUTING.md) for local development setup, coding standards, and testing procedures.
1225
+
1226
+ ---
1227
+
1228
+ ## Changelog
1229
+
1230
+ See [CHANGELOG.md](CHANGELOG.md) for release history and version notes.
1231
+
1232
+ ---
1233
+
1234
+ ## License
1235
+
1236
+ LogitGate is licensed under the [Apache License 2.0](LICENSE).