---
name: context-builder
description: >
  Ensamblador de contexto con presupuesto de tokens para inyección automática
  entre sesiones SWL. Cargar cuando se configure la inyección de contexto,
  se depure el hook inyeccion-contexto.js, o se necesite entender cómo SWL
  prioriza información entre sesiones. Budget default recalibrado a 2500 por
  el tokenizer de Opus 4.7 (+15-30% tokens vs 4.6).
version: "1.1.0"
herramientasPermitidas: [Read]
exclusiones:
  - "No cargar para depurar hooks que no sean `inyeccion-contexto.js` — la lógica de ensamblado es específica de ese hook."
  - "No cargar para buscar en el historial de sesiones; para búsqueda semántica usar `memoria-busqueda`."
  - "No cargar si `tokenBudget` ya fue configurado en la sesión y no hay cambios de modelo o proyecto — re-configurarlo mid-session no tiene efecto."
  - "No cargar para ajustar la compactación del contexto activo; para eso usar `compactacion-contexto`."
evolvable: true  # default para skill estandar
---
# Context Builder

## Qué es y por qué importa

El Context Builder (`hooks/lib/context-builder.js`) ensambla el bloque de contexto
que se inyecta al inicio de cada sesión nueva. Su trabajo es responder en pocos
tokens la pregunta: *"¿Dónde estaba yo?"*

Sin el Context Builder, cada sesión parte de cero. Con él, el modelo recibe en
los primeros mensajes: el proyecto activo, los patrones aprendidos, el resumen de
la sesión anterior y los aprendizajes recientes. Todo dentro de un presupuesto
controlado que no satura el contexto.

---

## Las 5 secciones en orden de prioridad

El ensamblado es secuencial con prioridad decreciente. Si el presupuesto se agota,
las secciones de mayor número se omiten primero.

| Prioridad | Sección | Fuente |
|-----------|---------|--------|
| 1 (siempre) | Header | `path.basename(baseDir)` + `.planning/CONTEXTO.md` |
| 2 | Instintos activos | `instintos/proyecto.yaml` (confidence >= 0.7) |
| 3 | Sesión anterior | `.planning/sessions/latest.json` |
| 4 | Aprendizajes recientes | `.planning/APRENDIZAJES.md` (últimos N bloques H2) |
| 5 | Footer de truncamiento | Generado automáticamente si se omitió algo |

### Sección 1 — Header

Siempre incluida. Formato:
```
[SWL Context] Proyecto: nombre-proyecto | Modo: dev
```

El modo se lee de `**Modo**: valor` en `.planning/CONTEXTO.md`. Fallback: `dev`.

### Sección 2 — Instintos activos

Instintos del archivo `instintos/proyecto.yaml` que cumplen:
- `status: active`
- `confidence >= 0.7`

Se ordenan por confianza descendente y se limitan a `maxInstintos` (default: 5).

### Sección 3 — Sesión anterior

Lee `.planning/sessions/latest.json` para localizar el JSON de la sesión.
No se incluye si:
- La sesión tiene `status: active` (es la sesión actual)
- La sesión tiene menos de 3 tool calls (demasiado corta para aportar contexto)

Incluye: `id`, `summary` (max 200 chars), `filesChanged` (max 5 archivos).

### Sección 4 — Aprendizajes recientes

Lee los últimos N bloques `## título` de `.planning/APRENDIZAJES.md`.
Solo incluye el título de cada bloque (no el contenido completo).
Respeta el budget restante de forma estricta: deja de agregar si se agotaría.

### Sección 5 — Footer de truncamiento

Solo aparece si alguna sección fue omitida por presupuesto agotado:
```
[Contexto truncado — secciones omitidas: instintos, aprendizajes. Budget: 2000 tokens]
```

---

## Token budget: por qué 2500 es el default óptimo (Opus 4.7)

El presupuesto controla cuántos tokens puede ocupar el bloque de contexto inyectado.

| Budget | Resultado |
|--------|-----------|
| < 1200 tokens | Contexto insuficiente. El header y poco más. Pierde continuidad. |
| 1200-2500 tokens | Zona óptima. Header + instintos + sesión anterior caben completos. |
| 2500-6000 tokens | Aceptable para proyectos con muchos instintos o aprendizajes. |
| > 6000 tokens | Contexto saturado. Diluye información útil. Penaliza el rendimiento. |

El default de 2500 tokens (~10,000 caracteres en español) cubre los 3 niveles de
contexto más valiosos sin consumir más del 1.25% de la ventana de un modelo sonnet.

**Nota sobre el tokenizer**: Opus 4.7 cambió el tokenizer respecto a 4.6 y produce
entre 1.0× y 1.35× más tokens para el mismo contenido. El default previo de 2000
quedó corto — el mismo bloque de contexto ahora pesa 2300–2700 tokens reales.
El default de 2500 restaura el margen útil.

---

## Configuración

```js
const { buildContext } = require('./hooks/lib/context-builder');

const { contexto, tokensUsados, seccionesTruncadas } = buildContext(baseDir, {
  tokenBudget:     2500,  // default: 2500 (era 2000 pre-4.7)
  maxAprendizajes: 5,     // default: 5
  maxInstintos:    5,     // default: 5
});
```

---

## Integración con inyeccion-contexto.js

El hook `hooks/inyeccion-contexto.js` llama a `buildContext` en la primera
invocación de cada sesión nueva. El flujo completo:

```
Nueva sesión
  → inyeccion-contexto.js detecta primera invocación
  → llama buildContext(cwd, opciones)
  → escribe contexto en stdout
  → Claude lo recibe como parte del primer turno
  → marca como inyectado en bridge para no repetir
```

El Context Builder no escribe en stdout directamente — devuelve el string.
La responsabilidad de emitirlo es del hook que lo invoca.

---

## Cuándo NO cargar

- Se busca recuperar el historial de sesiones o aprendizajes anteriores; usar `memoria-busqueda` con las 3 capas (search/timeline/fetch).
- El hook `inyeccion-contexto.js` ya inyectó contexto en esta sesión — re-invocar el Context Builder no modifica el contexto en curso.
- Se necesita depurar un hook que no sea `inyeccion-contexto.js`; la lógica de este módulo es específica del ensamblado inicial.
- Se quiere cambiar el presupuesto de tokens de la sesión actual ya iniciada; el budget se configura antes de la primera invocación del hook.

## Gotchas / Errores comunes no obvios

- **`seccionesTruncadas` ignorado cuando contiene secciones críticas**: el builder omite la sección 3 (sesión anterior) por presupuesto agotado y el agente no lo detecta, iniciando la sesión sin contexto de trabajo previo. Causa: no se verificó el campo `seccionesTruncadas` tras llamar a `buildContext`. Solución: si `seccionesTruncadas` no está vacío, ajustar `tokenBudget` hacia arriba o reducir `maxAprendizajes` hasta que las secciones 1-3 quepan completas — la sesión anterior es crítica.
- **Sesión con `status: active` incluida como sesión anterior**: el builder lee `latest.json` y encuentra la sesión actual marcada como `active`, inyectando el contexto de sí mismo. Causa: el filtro de `status: active` no se aplicó. Solución: verificar que `buildContext` excluye sesiones con `status: active` antes de incluirlas en la Sección 3 — la documentación ya lo especifica pero la implementación debe verificarse.
- **Budget de 2000 tokens sin recalibrar para Opus 4.7**: el mismo archivo de configuración que usaba 2000 en Opus 4.6 ahora satura el contexto porque el tokenizer produce 1.0-1.35× más tokens para el mismo contenido. Causa: no se actualizó la configuración al migrar de modelo. Solución: usar el default de 2500 que establece este skill para Opus 4.7; no asumir que el budget previo sigue siendo válido.
- **Instintos con `confidence < 0.7` incluidos en la Sección 2**: el código no aplica el filtro de confianza y llena el budget con instintos en estado draft. Causa: el filtro `confidence >= 0.7` se omitió en la implementación. Solución: verificar que `buildContext` filtra por `status: active` Y `confidence >= 0.7` — un draft no debe consumir tokens en la inyección inicial.

## Anti-patrones

**Budget muy alto (> 5000 tokens)**
Incluir todo el APRENDIZAJES.md en cada sesión satura el contexto útil.
El modelo pierde foco cuando recibe demasiado contexto de baja relevancia.
Usar `maxAprendizajes` bajo (3-5) y `tokenBudget` moderado (2000-3000).

**Incluir todo sin priorizar**
El valor del Context Builder está en la selección, no en la exhaustividad.
Un header + 3 instintos relevantes > 50 aprendizajes sin estructura.
Las secciones de mayor prioridad deben caber siempre en el budget.

**Ignorar seccionesTruncadas**
Si `seccionesTruncadas` no está vacío y el contenido truncado es importante,
aumentar `tokenBudget` o reducir `maxAprendizajes`/`maxInstintos` para que
las secciones de mayor prioridad quepan completas.
