# Carril verde: dejarlo listo para lanzar de un tirón

> **Ejecutado el 16 de agosto de 2026.** Este fichero se deja como estaba, que es
> el registro de lo que se planeó. Lo que pasó al ejecutarlo —incluidos dos topes
> que el plan no anticipaba, el suelo de 64k de Hermes y el directorio de trabajo
> en `$HOME`— está en `NOTAS.md`. Y una parte del plan quedó desmentida por los
> hechos: la escalera de contexto de `arrancar.sh` (24576 → 20480 → 16384) buscaba
> el número equivocado, porque por debajo de 64.000 Hermes no arranca.

## Contexto

El verde está instalado y configurado, pero **sin estrenar**. El primer arranque
quedó aplazado por dos motivos, uno técnico y uno de agenda:

1. **El prompt fijo de Hermes no cabe.** Medido con `hermes prompt-size` desde el
   directorio real de arranque: 26.281 B de sistema + 55.978 B de esquemas de 19
   herramientas = **82.259 B ≈ 20.500 tokens**, contra los **4.096** de `num_ctx`
   de `qwen3.5:4b-jarvis`. Y un segundo tope escondido, `num_predict 300`, que el
   naranja hereda del modelo *base* y que cortaría el JSON de una tool call por
   la mitad. Ya existe `qwen3.5:4b-verde` para resolverlo, pero a 32k de contexto
   da `cudaMalloc failed: out of memory` y falta encontrar el techo real.
2. **La gráfica está ocupada** por `entrena/dataset.py`, un trabajo tuyo de 7-10
   horas que va por `100/2261` fragmentos.

**Objetivo de este plan:** que cuando el dataset termine, arrancar y probar el
verde sea **un comando**, sin re-derivar nada de lo anterior ni recordar en qué
orden iba. Todo lo que una máquina puede decidir sola, automatizado; lo que
necesita tu oído y tu criterio, escrito en una escalera con huecos para anotar.

## Paso 0 — Guardar esto en el repo (primero, y son dos segundos)

Este plan vive en `~/.claude/plans/`, fuera del repo. Lo primero es copiarlo a
**`verde/PLAN-ARRANQUE.md`** y enlazarlo desde `verde/README.md`, para que esté
donde está todo lo demás y sobreviva a cerrar la terminal.

Ya está a salvo en el repo, y no hace falta rehacerlo: `NOTAS.md` (17 KB, con el
bloqueo del contexto, la variante del modelo, las trampas del `config.yaml` y los
pasos para retomar), `README.md`, `config.yaml`, `env.ejemplo`,
`qwen3.5-4b-verde.Modelfile`, `instalar.sh`, `verde-launcher.sh`, `voz-verde.sh`,
`jarvis-verde.svg` y `boveda/README.md`. La configuración aplicada en
`~/.hermes/` y el modelo `qwen3.5:4b-verde` en ollama también persisten.

`model.default` sigue apuntando a `qwen3.5:4b-jarvis` **a propósito**: cambiarlo
al verde sin fijar antes `context_length` sería peor que dejarlo, porque Hermes
se creería los 262.144 que reporta `/api/show`. Lo cambia `arrancar.sh` cuando
haya medido el techo real.

## Lo que se construye

### 1. `verde/arrancar.sh` — el comando único

Hace en orden lo que hoy habría que hacer a mano, y **se planta en cuanto algo
no cuadra** en vez de seguir y dar un fallo confuso más adelante.

```bash
./verde/arrancar.sh              # medir, configurar y dictaminar
./verde/arrancar.sh --solo-medir # sin tocar la configuracion
```

Pasos:

- **Guarda de entrada.** Si `entrena/dataset.py` sigue vivo, se para y lo dice:
  competir con él por la tarjeta estropea las dos cosas. `--igual` lo salta.
  También cierra los restos del naranja (`nucleo/jarvis.py`, `whisper-server`) y
  hace `ollama stop qwen3.5:4b-jarvis`, comprobando que la VRAM baja a ~140 MiB.

- **Busca el techo de contexto, midiendo.** Recrea `qwen3.5:4b-verde` bajando
  `num_ctx` hasta que cargue de verdad, y anota la VRAM de cada intento:

  | Intento | `num_ctx` | Nota |
  |---|---|---|
  | 1 | 24576 | el objetivo |
  | 2 | 20480 | |
  | 3 | 16384 | **suelo**: por debajo no cabe el prompt fijo con holgura |
  | 4 | 16384 con `num_gpu 24` | si ni así |

  Si ninguno entra, se para y propone `OLLAMA_FLASH_ATTENTION=1` +
  `OLLAMA_KV_CACHE_TYPE=q8_0` **sin aplicarlo**: es del servicio, no del modelo,
  y afectaría también al naranja. Esa decisión es tuya.

- **Configura Hermes con el número que salió.** En `~/.hermes/config.yaml`:
  `model.default` (línea 53) y `context_length` (línea 113, ya está escrita y
  comentada — la propia documentación del fichero dice que es justo para *"a
  local server with a custom num_ctx"*). Copia de seguridad antes, y verificación
  **parseando** después, nunca leyendo:

  ```bash
  python3 -c "import yaml;print(yaml.safe_load(open('$HOME/.hermes/config.yaml'))['model'])"
  ```

  Dos trampas ya conocidas que el script evita: las **claves duplicadas** dentro
  de `model:` (`provider` y `base_url` aparecen dos veces y en YAML gana la
  última — por eso hoy casi sale el tráfico por OpenRouter), y que la línea 122
  `# max_tokens: 8192` **está sin indentar**, así que descomentarla tal cual la
  dejaría fuera del bloque.

- **La prueba decisiva**, antes de abrir nada: `curl` al endpoint con un `tools`
  dentro. Separa dos preguntas que juntas se contestan mal — *¿sabe el modelo
  emitir una llamada?* y *¿funciona Hermes?*. Dictamen explícito:
  `tool_calls` válido → seguir; prosa o JSON roto → parar y decidir modelo mayor
  por CPU (hay 49 GB y 8 núcleos) o recortar herramientas.

- **Resumen final** con lo medido y el comando siguiente.

### 2. `verde/pruebas/` — la suite, con tu convención

Misma forma que `pruebas/` del naranja: scripts numerados y un `ejecutar.sh` que
los pasa y resume. Ninguna abre el TUI.

| | Comprueba |
|---|---|
| `01_gpu.sh` | tarjeta libre, sin naranja ni dataset compitiendo |
| `02_modelo.sh` | `4b-verde` existe con sus parámetros **y `4b-jarvis` sigue intacto** |
| `03_config.sh` | parseado: modelo, `context_length`, `base_url` en loopback, **cero URLs de nube** |
| `04_tool_calling.sh` | **la decisiva**: el modelo emite `tool_calls` bien formado |
| `05_cabe.sh` | `hermes prompt-size` < `context_length`, con margen |
| `06_privacidad.sh` | 0 credenciales, 0 tokens de mensajería, nada fuera de loopback |
| `07_voz.sh` | `voz-verde.sh` genera WAV a 22050 Hz (hoy: 0,34 s para 3,2 s) |

La 04 y la 05 son las que hoy no se pudieron pasar. La 06 replica el espíritu de
tu `pruebas/06_privacidad.sh`.

### 3. `verde/ESCALERA.md` — lo que solo puedes juzgar tú

El guion del primer arranque interactivo, con huecos para anotar tiempo y
resultado. De trivial a real, y **se para en el primer escalón que falle**,
que es el que informa:

| # | Prueba | Qué contesta |
|---|---|---|
| 1 | "hola, ¿quién eres?" | el endpoint responde y el prompt cabe |
| 2 | "¿cuánto espacio libre queda?" | **una** herramienta, terminal |
| 3 | "lee verde/README.md y resúmelo en una línea" | herramienta de ficheros |
| 4 | "dime cuál de los .md de verde/ es el más largo" | **varias vueltas encadenadas** |
| 5 | algo que dispare una skill | el paso 6 del vídeo |
| 6 | que hable | debe sonar **igual que el naranja** |
| 7 | que escuche | **el último**: 839 MiB de pico contra la tarjeta casi llena |

El escalón 4 es el que separa un chatbot de un agente: encadenar llamadas y
razonar sobre el resultado de la anterior.

El 7 puede dar `CUDA error: out of memory`, y **no sería un fallo nuevo**: es el
mismo reparto que documenta tu README. Salidas por orden: bajar a `base`, fiarse
de `unload_after_idle_seconds: 300`, o probar la escucha con el modelo
descargado.

### 4. Notas al día

`verde/NOTAS.md` y `verde/README.md` ya recogen el bloqueo, la variante del
modelo y las trampas. Se actualizan para apuntar a `arrancar.sh` como la puerta
de entrada, y `NOTAS.md` recibe la tabla de VRAM por intento cuando se mida.

## Lo que sigue sin hacerse

- **No se toca `qwen3.5:4b-jarvis`**, ni `nucleo/`, `config/`, `voz/` o
  `newelle/`. El naranja se cierra como proceso y se reabre igual.
- **No se mata `dataset.py`.** El script se planta si lo encuentra vivo.
- **No se ponen claves** ni se activa ningún canal de mensajería.
- **No se cambia nada del servicio de ollama** sin decírtelo: `OLLAMA_KV_CACHE_TYPE`
  se propone, no se aplica.

## Verificación

Con `dataset.py` ya terminado:

```bash
./verde/arrancar.sh                  # mide, configura y dictamina
./verde/pruebas/ejecutar.sh          # las 7, ninguna abre el TUI
./verde/verde-launcher.sh            # el TUI en verde fosforo -> ESCALERA.md
```

Y devolver la máquina a su sitio al acabar: `ollama stop qwen3.5:4b-verde`, y
comprobar que el naranja vuelve a arrancar con su VRAM de siempre. Sigue
pendiente, para cuando pares de desarrollar:

```bash
cd pruebas && ./ejecutar.sh          # las 104 del naranja
```

Hoy no se corrieron a propósito: abren la app y cargan el modelo.

## Y antes de comparar los dos carriles

El naranja tiene **121 acciones rápidas que se saltan el modelo**; Hermes no
tiene ese atajo y toda orden le pasa por el cerebro. **El verde va a medir más
lento y no será culpa del modelo.** Para comparar hay que usar solo frases que
en el naranja también acaben en el cerebro: están en
`config/jarvis-sin-accion.jsonl`.
