TECHNICAL GUIDELINES
BetSmart: Fararoni G-Master Evolution — Deterministic Two-Layer Control for Local Agentic Systems
Eber Cruz — Software Engineer | C-FARARONI Project
2026 · Technical Notes
Phase: Hardened Signal Filtering · Version 1.0
1. Purpose of this Document
This document codifies the transition from preventive control to deterministic two-layer control for local agentic systems, based on the empirical evolution of the Fararoni Kernel during Phase 91.
Everything documented here was discovered, implemented, and validated with real traces on Qwen 3.5:35b running locally via Ollama. This is not theory — it is combat engineering.
2. The Law of Projective Tool Hallucination
2.1 Definition
LLMs with tool calling fine-tuning generate tool names from their training vocabulary, NOT from the tools list provided in the API request.
The API tools field acts as a probabilistic suggestion, not a hard constraint. The model can generate any tool it "remembers" from its training, regardless of what is offered.
2.2 Empirical Evidence
PRUEBA: Enviar tools=[fs_patch, fs_write] (solo 2 herramientas)
RESULT: Model genera tool_call con name="ShellCommand"
Traza real (Sesión 14, depth=2):
allowedTools=[fs_write, fs_patch] filteredCount=2
→ isToolCall=true tool=ShellCommand ← NO ESTABA EN LA LISTA2.3 Known Native Vocabularies
┌──────────────────────┬─────────────────────────────────────────────┐
│ Model │ Native Tool Vocabulary │
├──────────────────────┼─────────────────────────────────────────────┤
│ Qwen 2.5-coder │ ShellCommand, ReadFile, WriteFile, │
│ │ ListFiles, FileSearch, GitAction │
├──────────────────────┼─────────────────────────────────────────────┤
│ Qwen 3.5 │ Bash, Read, Write, Edit, Glob, Grep │
│ │ (Claude Code vocabulary) │
├──────────────────────┼─────────────────────────────────────────────┤
│ DeepSeek-R1 │ Varies — uses mixed XML/JSON formats │
└──────────────────────┴─────────────────────────────────────────────┘2.4 Mandate
DO NOT attempt to filter tools pre-generation. The model will ignore them. Instead: 1. Send ALL available tools 2. Intercept the response post-generation 3. Normalize names (ReadFile→fs_read, Bash→ShellCommand) 4. Validate against the state machine 5. Reject with feedback if illegal
3. Two-Layer Governance Architecture (Fix-G)
3.1 Overview
3.2 Layer 1: Certainty Magnet — PROTOCOL-MANDATE Injection
Principle
The last role:system message in the context window has the greatest weight in the model's decision. By injecting a precise directive just before the call, we create a "gravitational field" that attracts the model toward the correct tool.
Directives per State
POST_SHELL (after failed compilation):
PROTOCOL-MANDATE: Build failed. Read the error messages above carefully.
Use fs_read to open the file mentioned in the errors, then fix it with fs_patch.
Do NOT re-run the build without fixing something first.
POST_READ (after reading a file):
PROTOCOL-MANDATE: File analysis is complete.
You MUST now apply the fix using the 'fs_patch' tool.
Group ALL corrections (imports, methods, types) into a SINGLE fs_patch call.
Do NOT re-read the file. Do NOT compile yet. Apply the fix NOW.
POST_PATCH (after patching):
PROTOCOL-MANDATE: Your patch has been applied to disk successfully.
If there are MORE errors to fix in this or another file, use fs_patch again.
If you have fixed ALL errors, verify by running 'mvn compile' via ShellCommand.
Do NOT re-read a file you already patched.
Implementation
private void injectCertaintyDirective(ArrayNode messages, String lastToolUsed) {
String normalized = normalizeToolName(lastToolUsed);
String directive = switch (normalized) {
case "fs_read" -> "PROTOCOL-MANDATE: File analysis is complete...";
case "fs_patch", "fs_write" -> "PROTOCOL-MANDATE: Your patch has been applied...";
default -> "PROTOCOL-MANDATE: Build failed...";
};
ObjectNode sysDirective = JSON_MAPPER.createObjectNode();
sysDirective.put("role", "system");
sysDirective.put("content", directive);
messages.add(sysDirective);
}
3.3 Layer 2: Interception Wall — Agnostic Interceptor
Principle
If despite Layer 1 the model generates an illegal tool, the Interceptor:
- Normalizes the name (agnostic multi-version Qwen mapping)
- Validates against the state machine
- Rejects with explanatory
role:toolERROR - Retries (budget of 2 rejections per depth)
- Fallback if budget is exhausted
Name Normalization
private String normalizeToolName(String rawName) {
return switch (rawName.toLowerCase()) {
case "fs_read", "readfile", "read" -> "fs_read";
case "fs_write", "writefile", "write" -> "fs_write";
case "fs_patch", "edit" -> "fs_patch";
case "shellcommand", "bash", "shell_execute" -> "ShellCommand";
default -> rawName;
};
}
4. The Relaxed State Machine (One-Shot Flow)
4.1 State Machine Evolution
STRICT VERSION (Fix F — FAILED):
POST_PATCH → [ShellCommand] ← Forced compilation after EACH patch
RESULT: 6+ rejections, 10+ min wasted, multi-patch blocked
RELAXED VERSION (Fix G — VALIDATED):
POST_PATCH → [ShellCommand, fs_patch, fs_write, fs_read]
RESULT: 0 rejections, multi-patch fluido, ciclos completos4.2 Transition Table
┌───────────────────┬──────────────────────────────────┬────────────────────────┐
│ State │ Valid Tools │ Reason │
├───────────────────┼──────────────────────────────────┼────────────────────────┤
│ POST_READ │ fs_patch, fs_write │ MUST patch. │
│ (after reading) │ │ Cannot re-read. │
│ │ │ Cannot compile. │
├───────────────────┼──────────────────────────────────┼────────────────────────┤
│ POST_PATCH │ ShellCommand, fs_patch, │ Can patch MORE │
│ (después de │ fs_write, fs_read │ errors (multi-patch) │
│ parchear) │ │ OR verify compilation│
│ │ │ La Layer 1 guides la │
│ │ │ correct decision. │
├───────────────────┼──────────────────────────────────┼────────────────────────┤
│ POST_COMPILE │ fs_read, fs_patch, │ If failed → restart │
│ (después de │ fs_write, ShellCommand │ cycle with │
│ compilar) │ │ distilled data. │
│ │ │ If success → END. │
└───────────────────┴──────────────────────────────────┴────────────────────────┘4.3 POST_READ: Infinite Read Loop Prevention
Problem discovered in Session 10: With tool_choice="required", the model chose fs_read 9 out of 10 times (1 hour 20 minutes). Reading is the "safe action" that modifies nothing.
Solution: POST_READ solo permite fs_patch y fs_write. El modelo DEBE hacer algo productivo after reading. No puede re-leer como escape.
4.4 POST_PATCH: Legitimate Multi-Patch
Problem discovered in Session 14: A file with 5 errors needs 5 patches (or N consolidated patches). Forcing compilation after EACH patch wastes iterations:
Ciclo estricto (Fix F): read → patch → compile → read → patch → compile (6 depths)
Ciclo relajado (Fix G): read → patch → patch → patch → compile (5 depths)Solution: POST_PATCH permite fs_patch (más patches) O ShellCommand (compilar cuando esté listo). La Capa 1 (Certainty Injection) guía al modelo: _"Si hay más errores, usa fs_patch. Si ya corregiste todo, verifica con mvn compile."_
4.5 POST_COMPILE: Cycle with Distilled Data
Critical component: BuildOutputDistiller reduces ~1MB of build output to ~2000 chars of actionable errors. Without this, accumulated context causes "cognitive saturation" and the model responds with explanatory text instead of tool calls.
// BuildOutputDistiller — Extracts only critical intelligence
// 1. Filters lines with [ERROR], BUILD FAILURE, COMPILATION ERROR
// 2. Captures last 20 lines (build summary)
// 3. Combines errors + summary, no duplicates
// 4. Truncates to max 3000 chars keeping the end
// 5. Wraps with metadata: "[DISTILLED BUILD OUTPUT] Original: 850K → Distilled: 2K"4.6 Complete One-Shot Flow
5. Graph Topology and Control Algorithms
5.1 The Directed State Graph (FSM-Graph)
5.2 Governance Algorithms (Evolution G)
The three algorithms operating on the graph form a coordinated system: each acts in a different phase of a transition's lifecycle (pre-generation, post-generation, and entropy reduction).
Algorithm 1: Graph Normalization — normalizeToolName()
Algorithmic complexity: O(1) — a switch expression on the lowercase name. The cost is negligible (~0 tokens, ~0ms latency).
Algorithm 2: TFI Injection — injectCertaintyDirective()
Measured impact: 0 rejections in 8 depths (100% One-Shot Success). Without injection (Fix F), there were 6+ rejections in 5 depths (~30% success rate).
Algorithm 3: Heuristic Distillation — BuildOutputDistiller.distill()
Function: Reduces the entropy of the POST_COMPILE node. When a build fails, it generates ~1MB of logs. Sending this to the LLM causes "cognitive saturation" — the model cannot find the signal in the noise and responds with generic text.
5.3 Convergence Guarantee
6. Military-Grade Success Metrics
6.1 Insubordination Rejection Reduction
6.2 Latency Penalty Elimination
6 rejections eliminated (average per test) = ~12 minutes + ~18,000 tokens
In 100 compilations/day: ~20 hours + ~1.8M tokens saved
7. Evolution Archaeology (Fixes A-G)
7.1 Discovery Timeline
SESSION │ FIX │ STRATEGY │ RESULT
───────┼───────┼──────────────────────────────────┼──────────────────────────
7-8 │ - │ Surgical tracing │ Identified: cognitive saturation
9 │ A+B+C │ Extractor + Distiller + Hints │ Partial: depth 4 still fails
10 │ D │ tool_choice=required global │ ❌ Infinite loop of fs_read
10 │ E │ Pre-generation filter │ ❌ Model ignora lista de tools
11 │ - │ Discovery FASE33.2 │ Qwen has hardcoded vocabulary
12 │ - │ Findings documentation │ "Projective Tool Hallucination"
13 │ F │ Post-generation interceptor │ ⚠️ Works but EXPENSIVE (120s/rechazo)
14 │ - │ Real Fix F test │ 6+ rejections, estado demasiado estricto
15 │ G │ Certainty Injection + Relax │ ✅ 0 rejections, 100% One-Shot Success
│ │ state + Interceptor safety net │7.2 The Three Control Strategies (and why only one works)
8. Implementation Rules for Future Systems
8.1 Rule 1: Never Filter Tools
FORBIDDEN:
tools = filterByState(allTools, lastAction); // The model ignores it
CORRECT:
tools = allTools; // Send all
response = llm.generate(messages, tools);
validate(response.toolCall(), stateMachine); // Validate AFTER8.2 Rule 2: Always Inject Before Generating
FORBIDDEN:
response = llm.generate(messages, tools); // Without guidance
CORRECT:
injectDirective(messages, currentState); // Deterministic guidance
response = llm.generate(messages, tools); // The model "knows" what to do8.3 Rule 3: Always Normalize
FORBIDDEN:
if (toolName.equals("fs_read")) { ... } // Only one name
CORRECT:
String normalized = normalizeToolName(toolName); // ReadFile, Read, fs_read → "fs_read"
if ("fs_read".equals(normalized)) { ... }8.4 Regla 4: States Relaxeds > States Estrictos
FORBIDDEN:
POST_PATCH → [ShellCommand] // Too strict, blocks multi-patch
CORRECT:
POST_PATCH → [ShellCommand, fs_patch, fs_write, fs_read] // Relaxed
// La Layer 1 guides al modelo a la decisión correcta8.5 Rule 5: The Interceptor is Insurance, Not the Engine
El Interceptor (Capa 2) debe existir pero NUNCA debería activarse.
Si se activa frecuentemente, la Capa 1 (Certainty Injection) necesita
mejores directivas. El Interceptor es el Anillo 3 — última línea de
defensa, no la primera.9. Glossary
| Term | Definition |
|---|---|
| Projective Hallucination | LLM generates tools from its training vocabulary, ignores API list |
| Certainty Injection | role:system message injected before each LLM call with exact directive |
| One-Shot Success | The model selects the correct tool on its first attempt |
| Multi-Patch | Multiple consecutive patches before compiling (legitimate for multi-error) |
| BuildOutputDistiller | Reduces 1MB of build logs to ~2K chars of actionable errors |
| Interceptor | Post-generation safety net that rejects illegal tools with feedback |
| PROTOCOL-MANDATE | Prefix of injected certainty directives |
| Retry Budget | Maximum 2 Interceptor rejections per depth before fallback |
| Normalizer | Mapping of model native names to Fararoni canonical names |
| Relaxed State | POST_PATCH allows more patches OR compilation (vs compilation only) |
_Document generated as a BetSmart technical guideline for the G-Master Evolution of the Fararoni Kernel. Based on empirical evidence from 8 debug sessions, 7 iterative fixes, and production traces on local Qwen 3.5:35b._
About the Author
Eber Cruz is a software engineer with a decade of experience designing backend infrastructure and distributed systems. This document reflects the design work behind C-FARARONI, an experimental ecosystem focused on technological sovereignty and secure execution of local AI models.
Repository: github.com/ebercruzf/fararoni-ecosystem
Notes and contact: ebercruz.com