TECHNICAL GUIDELINES

BetSmart: Fararoni G-Master Evolution — Deterministic Two-Layer Control for Local Agentic Systems

BACK

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 LISTA

2.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

Two-Layer Governance — Fix-GTWO-LAYER GOVERNANCE — FIX-GLAYER 1: CERTAINTY MAGNET (GUIDE)Injection of role:system with PROTOCOL-MANDATEBEFORE each LLM call"PROTOCOL-MANDATE: File analysis is complete.You MUST now apply the fix using fs_patch..."Cost: ~50 tokensSuccess: ~90%+LLM CALLLAYER 2: INTERCEPTION WALL (SAFETY NET)1. Normalize name (ReadFile→fs_read)2. Validate against relaxed state machine3. If illegal → role:tool ERROR + retry (budget=2)4. If legal → executeCost/rejection: ~120sFrequency: <10%COMBINED RESULTLayer 1 guides → ~90% first-attempt successLayer 2 intercepts → catches the ~10% remainder

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:

  1. Normalizes the name (agnostic multi-version Qwen mapping)
  2. Validates against the state machine
  3. Rejects with explanatory role:tool ERROR
  4. Retries (budget of 2 rejections per depth)
  5. 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 completos

4.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

Complete One-Shot FlowCOMPLETE ONE-SHOT FLOWcompile(fail)[DISTILL] 1MB → 2K chars[INJECT] "Build failed. Use fs_read..."[LLM] → fs_read ✓[INJECT] "File analysis complete. Use fs_patch..."[LLM] → fs_patch ✓ (patch 1)[INJECT] "Patch applied. More? fs_patch. Done? ShellCommand."[LLM] → fs_patch ✓ (patch 2 — multi-patch)[LLM] → ShellCommand ✓ (mvn compile)exit_code=0forceDirectResponse → Summaryexit_code=1[DISTILL] → new cycle

5. Graph Topology and Control Algorithms

5.1 The Directed State Graph (FSM-Graph)

Relaxed Control State GraphSTARTPOST_COMPILE(IDLE)POST_READPOST_PATCHSUCCESSexit=0Multi-PatchRepair CycleRELAXED CONTROL STATE 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

Graph Terminal StatesGRAPH TERMINAL STATESSUCCESSCondition:exit_code = 0Action:forceDirectResponse()Summary to userMAX_DEPTHCondition:depth = 10Action:forceDirectResponse()Protects budgetTERMINATEDCondition:text without tool callAction:Returns textTimeout or context exceeded

6. Military-Grade Success Metrics

6.1 Insubordination Rejection Reduction

Fix F vs Fix G MetricsREJECTION REDUCTIONFix F (before)Fix G (now)Rejections/test6+0 ✓Fallback/test2+0 ✓One-Shot Success~30%100%Multi-patch03 ✓Complete cycles02 ✓

6.2 Latency Penalty Elimination

1 rejection eliminated = ~120 seconds + ~3000 tokens saved
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)

Three Control StrategiesTHREE CONTROL STRATEGIESSTRATEGY 1Pre-Generation (Fix D,E)"Don't show it the door"✗ FAILS: Model ignores listSTRATEGY 2Post-Gen Punishment (Fix F)"Let it fail and fine it"⚠ WORKS but EXPENSIVE120s + 3000 tokensSTRATEGY 3Deterministic Guide (Fix G)"Tell it what to do before"✓ WORKS and FREE~50 tokensFix G = Strategy 3 (primary) + Strategy 2 (safety net)

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 AFTER

8.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 do

8.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 correcta

8.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

TermDefinition
Projective HallucinationLLM generates tools from its training vocabulary, ignores API list
Certainty Injectionrole:system message injected before each LLM call with exact directive
One-Shot SuccessThe model selects the correct tool on its first attempt
Multi-PatchMultiple consecutive patches before compiling (legitimate for multi-error)
BuildOutputDistillerReduces 1MB of build logs to ~2K chars of actionable errors
InterceptorPost-generation safety net that rejects illegal tools with feedback
PROTOCOL-MANDATEPrefix of injected certainty directives
Retry BudgetMaximum 2 Interceptor rejections per depth before fallback
NormalizerMapping of model native names to Fararoni canonical names
Relaxed StatePOST_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

Secure Terminal Access

INITIALIZE_COLLABORATION

Want to join the project? Secure terminal interface for developers and technical profiles.

fararoni_secure_shell — bash
SYSTEM: WAITING FOR INPUT
System check: OK
> INITIALIZE_COLLABORATION...
root@fararoni:~$input_email
root@fararoni:~$set_sector
root@fararoni:~$set_operator
root@fararoni:~$define_mission
root@fararoni:~$Type 'help' to see available commands
root@fararoni:~$
ENCRYPTED CONNECTION ESTABLISHED via TLS 1.3