---
name: wiki-conocimiento
description: >
  Gestión de conocimiento del proyecto con grafo de conocimiento y búsqueda semántica.
  Integra patrones de LightRAG (grafo + vectores) para indexar aprendizajes, ADRs,
  sesiones y documentación del proyecto. Cargar cuando se use /swl:wiki o se necesite
  recuperar conocimiento acumulado del proyecto de forma semántica.
version: "1.0.0"
herramientasPermitidas: [Read, Glob, Grep]
user-invocable: false
exclusiones:
  - "No cargar para búsqueda simple de aprendizajes o sesiones anteriores — `memoria-busqueda` cubre esa necesidad con 3 capas de progressive disclosure a menor costo; este skill añade el grafo de conocimiento semántico que solo compensa para consultas relacionales complejas."
  - "No cargar si el proyecto tiene menos de 20 entradas en APRENDIZAJES.md o menos de 10 sesiones — el grafo de conocimiento no tiene suficiente masa crítica para ser útil con tan pocos datos; usar `memoria-busqueda` directamente."
  - "No cargar para indexar o buscar en código fuente del codebase — el grafo indexa decisiones, aprendizajes, ADRs y sesiones, no código; para búsqueda en código usar Grep o `swl-revisar-impacto`."
  - "No cargar para persistir aprendizajes nuevos de la sesión — eso es `extractor-de-aprendizajes`; este skill lee y consulta el grafo existente, no lo actualiza directamente."
evolvable: true  # default para skill estandar
---
# Wiki de Conocimiento del Proyecto

Sistema de gestión de conocimiento que combina grafo de conocimiento con búsqueda
semántica para recuperar información acumulada del proyecto.

## Cuándo cargar

- `/swl:wiki query "..."` necesita buscar conocimiento del proyecto
- Un agente SWL necesita contexto de decisiones previas antes de implementar
- Se quiere indexar nuevos aprendizajes o ADRs
- Se necesita trazar relaciones entre decisiones, bugs y soluciones

## Arquitectura de referencia

```
Fuentes de conocimiento:
  .planning/APRENDIZAJES.md    → Aprendizajes curados
  .planning/adrs/              → Decisiones de arquitectura (ADRs)
  .planning/sessions/          → Historial de sesiones
  .planning/COMPACTACION.md    → Contexto compactado
  docs/                        → Documentación del proyecto

     ↓ Ingestión

  Chunking → Extracción de entidades/relaciones → Grafo de conocimiento
                                                        ↓
                                          Embeddings → Vector store
                                                        ↓
  Consulta → Keyword extraction → Retrieval híbrido → Respuesta contextual
```

## Modos de búsqueda (patrón LightRAG)

Basado en los 5 modos de retrieval de LightRAG:

### 1. Local — Preguntas específicas
- Extrae keywords de bajo nivel de la consulta
- Recupera entidades cercanas en el grafo
- Sigue relaciones para contexto adicional
- **Usar para:** "¿Qué decidimos sobre el manejo de errores en el módulo de pagos?"

### 2. Global — Preguntas amplias
- Extrae keywords de alto nivel
- Recupera relaciones agregadas y resúmenes de comunidades
- **Usar para:** "¿Cuáles son los patrones arquitectónicos principales del proyecto?"

### 3. Híbrido — Combina local + global
- Ejecuta ambas estrategias y fusiona resultados
- **Usar para:** Preguntas que necesitan tanto detalle como panorama general

### 4. Naive — Búsqueda directa por similaridad
- Sin grafo, solo embeddings de chunks
- Más rápido pero menos contexto
- **Usar para:** Búsquedas rápidas cuando se conoce el texto aproximado

### 5. Mix — Recomendado (grafo + vectores)
- Combina knowledge graph + chunk embeddings
- Con reranking adaptativo
- **Default para /swl:wiki query**

## Modelo de entidades

### Ontología tipada (patrón Zep)

Define tipos de entidades y relaciones válidas entre ellas.
Una ontología formal previene incoherencias en el grafo.

### Tipos de entidades en el grafo
| Tipo | Descripción | Fuente típica |
|------|-------------|---------------|
| `Decisión` | Decisión arquitectónica o técnica | ADRs, COMPACTACION.md |
| `Patrón` | Patrón de diseño adoptado | APRENDIZAJES.md |
| `AntiPatrón` | Práctica a evitar | APRENDIZAJES.md |
| `Componente` | Módulo, servicio o librería | Código fuente |
| `Bug` | Bug conocido y su solución | Sessions, APRENDIZAJES.md |
| `Tecnología` | Framework, librería o herramienta | package.json, pyproject.toml |
| `Persona` | Desarrollador o stakeholder | Git blame, sessions |
| `Requisito` | Requisito funcional o no-funcional | PRD, ADRs |
| `Preferencia` | Preferencia técnica del usuario/equipo | Feedback, sessions |
| `Evento` | Incidente, release, migración | Historial, COMPACTACION.md |

### Combinaciones válidas de relaciones (ontología)

| Relación | Source válido | Target válido |
|----------|-------------|---------------|
| `causado_por` | Bug | Patrón, AntiPatrón, Componente |
| `resuelto_con` | Bug | Decisión, Patrón |
| `depende_de` | Componente | Componente, Tecnología |
| `reemplaza` | Patrón, Decisión | AntiPatrón, Decisión |
| `usa` | Componente | Tecnología |
| `decidido_en` | Decisión | Evento |
| `confirmado_por` | Patrón, Decisión | Evento |
| `prefiere` | Persona | Tecnología, Patrón, Preferencia |
| `requiere` | Requisito | Componente, Tecnología |

### Grafo temporal (patrón Zep)

Cada entidad y relación tiene timestamps de vigencia:

```
{
  "id": "decision-001",
  "tipo": "Decisión",
  "nombre": "Usar SQLAlchemy async en FastAPI",
  "valid_at": "2026-04-10",     // Cuándo empezó a ser válido
  "invalid_at": null,           // null = vigente actualmente
  "created_at": "2026-04-10",   // Cuándo se registró
  "fuente": "sesión-2026-04-10"
}
```

**Reglas de vigencia:**
- `valid_at` obligatorio en toda entidad/relación
- `invalid_at = null` → entidad vigente (incluir en consultas normales)
- `invalid_at = fecha` → entidad obsoleta (excluir de consultas, incluir en historial)
- Al crear una entidad que contradice otra → marcar la anterior con `invalid_at` = hoy
- Nunca borrar entidades obsoletas — solo marcar como inválidas para trazabilidad

### Clasificación de hechos por impacto (fact rating, patrón Zep)

Cada hecho extraído se clasifica automáticamente por impacto:

| Rating | Criterio | Ejemplo |
|--------|----------|---------|
| **HIGH** | Decisión arquitectónica irreversible, bug crítico, cambio de patrón | "Se migró de REST a GraphQL por requisitos de rendimiento" |
| **MEDIUM** | Preferencia técnica, gotcha documentado, patrón confirmado | "SQLAlchemy async requiere selectinload() obligatorio" |
| **LOW** | Información contextual, observación menor | "El build tarda 3 minutos en promedio" |

**Mapeo a modelo 4-tier de swl-ses:**
- HIGH → Tipo A (verdad estructural)
- MEDIUM → Tipo B (gotcha/anti-patrón operativo)
- LOW → Tipo C (preferencia/configuración)

### Tipos de relaciones
| Relación | Ejemplo |
|----------|---------|
| `causado_por` | Bug X fue causado_por Patrón Y |
| `resuelto_con` | Bug X fue resuelto_con Decisión Z |
| `depende_de` | Componente A depende_de Componente B |
| `reemplaza` | Patrón X reemplaza AntiPatrón Y |
| `usa` | Componente A usa Tecnología B |
| `decidido_en` | Decisión X decidido_en ADR-001 |
| `confirmado_por` | Patrón X confirmado_por sesión 2026-04-10 |

## Patrón Compiled Truth (v5.6.0)

Cada entidad del grafo sigue el patrón Compiled Truth:

```markdown
## [Nombre de la entidad]

### Compiled Truth (síntesis curada)
- Resumen en 2-3 oraciones
- Estado actual: vigente/obsoleto/en_revisión

### Timeline (evidencia cronológica)
- [2026-04-01] [F:APRENDIZAJES] — Primera mención
- [2026-04-10] [F:sesión] — Confirmado en implementación
- [2026-04-12] [F:ADR-005] — Formalizado como decisión
```

## Integración con LightRAG

### Implementación recomendada (servicio auxiliar)

```python
# scripts/lightrag-wiki.py — Servicio local de conocimiento del proyecto
from lightrag import LightRAG, QueryParam

async def inicializar_wiki(directorio_proyecto: str) -> LightRAG:
    """Inicializa LightRAG con almacenamiento local para el proyecto."""
    rag = LightRAG(
        working_dir=f"{directorio_proyecto}/.planning/wiki-index",
        llm_model_func=llm_completar,      # Wrapper para Claude
        embedding_func=embedding_generar,   # Wrapper para embeddings
        chunk_token_size=1200,
        chunk_overlap_token_size=100,
        enable_llm_cache=True,              # Caché para operaciones repetitivas
    )
    await rag.initialize_storages()
    return rag

async def indexar_fuentes(rag: LightRAG, directorio_proyecto: str):
    """Indexa todas las fuentes de conocimiento del proyecto."""
    fuentes = [
        f"{directorio_proyecto}/.planning/APRENDIZAJES.md",
        f"{directorio_proyecto}/.planning/COMPACTACION.md",
    ]
    # Agregar ADRs si existen
    import glob
    fuentes += glob.glob(f"{directorio_proyecto}/.planning/adrs/*.md")
    # Agregar sesiones recientes (últimas 10)
    sesiones = sorted(glob.glob(f"{directorio_proyecto}/.planning/sessions/*.md"))[-10:]
    fuentes += sesiones

    for fuente in fuentes:
        with open(fuente, 'r', encoding='utf-8') as f:
            contenido = f.read()
        await rag.ainsert(contenido, file_paths=[fuente])

async def consultar(rag: LightRAG, pregunta: str, modo: str = "mix") -> str:
    """Consulta el grafo de conocimiento del proyecto."""
    resultado = await rag.aquery(
        pregunta,
        param=QueryParam(
            mode=modo,
            top_k=20,
            chunk_top_k=10,
            max_total_tokens=15000,
            enable_rerank=True,
        ),
    )
    return resultado.response
```

### Flujo de actualización incremental

```
1. /swl:aprender extrae aprendizajes → guarda en APRENDIZAJES.md
2. Hook post-aprender indexa nuevo contenido en LightRAG
3. Próxima consulta /swl:wiki incluye aprendizajes recientes
4. Consolidación periódica: re-indexar todo para mantener coherencia del grafo
```

## Implementación actual (sin LightRAG — búsqueda textual)

Mientras LightRAG no esté instalado, `/swl:wiki query` usa:

1. `session-fts.js` (BM25) para búsqueda en sesiones
2. `memory-search.js` (TF-IDF) para búsqueda en memoria
3. Grep directo en `.planning/` para ADRs y aprendizajes

La migración a LightRAG es incremental: agregar el servicio como MCP server
sin romper la funcionalidad existente.

## Evaluación de calidad (patrón RAGAS)

Para evaluar la calidad de las respuestas del wiki:

| Métrica | Descripción | Umbral aceptable |
|---------|-------------|-------------------|
| Faithfulness | ¿La respuesta se basa en las fuentes recuperadas? | ≥ 0.85 |
| Answer relevancy | ¿La respuesta es relevante a la pregunta? | ≥ 0.80 |
| Context precision | ¿Los chunks recuperados son precisos? | ≥ 0.75 |
| Context recall | ¿Se recuperaron todos los chunks relevantes? | ≥ 0.70 |

## Cuándo NO cargar

- La búsqueda es sobre aprendizajes o sesiones anteriores con una query de texto directa — `memoria-busqueda` tiene 3 capas de progressive disclosure y cuesta menos; el grafo de wiki compensa solo cuando la consulta requiere traversal de relaciones entre entidades.
- El proyecto tiene menos de 20 entradas en APRENDIZAJES.md y menos de 10 sesiones — sin masa crítica de datos, el grafo no tiene suficientes nodos para que las relaciones aporten valor sobre una búsqueda textual simple.
- Se busca en código fuente (funciones, patrones, implementaciones) — el grafo indexa decisiones, aprendizajes y ADRs, no código; para búsqueda de código usar Grep directamente o `swl-revisar-impacto` para análisis estructural.
- El objetivo es registrar un aprendizaje nuevo de la sesión actual — eso es `extractor-de-aprendizajes`; este skill lee el grafo existente, no persiste nuevo conocimiento directamente.

## Gotchas / Errores comunes no obvios

- **Entidades con `invalid_at` no excluidas de consultas normales**: el wiki devuelve decisiones obsoletas como vigentes porque la query no filtra por `invalid_at = null`. Causa: LightRAG indexa el contenido textual de los documentos pero no ejecuta filtros por campo del grafo automáticamente. Solución: al consultar decisiones vigentes, agregar `invalid_at = null` como filtro en la capa de post-procesamiento del resultado — o en el modo de implementación sin LightRAG, verificar el campo en el JSON antes de incluir la entidad.
- **Indexación masiva con `rag.ainsert()` llamado para cada archivo en un loop sin batching**: el proceso de ingestión tarda 45 minutos en indexar 50 sesiones porque cada llamada espera la finalización de la anterior. Causa: `ainsert()` es async pero se llama con `await` secuencial en lugar de `asyncio.gather()`. Solución: usar `asyncio.gather(*[rag.ainsert(c) for c in contenidos])` para indexar en paralelo — LightRAG soporta ingestión concurrente.
- **Consulta en modo `global` devuelve respuesta genérica sin usar datos del proyecto**: el agente usa modo `mix` pero el grafo no tiene suficientes entidades indexadas para el reasoning global. Causa: el modo `global` de LightRAG requiere suficiente masa de entidades para hacer inferencias; con pocos documentos, el modo `local` o `naive` da mejores resultados. Solución: para proyectos pequeños usar modo `local` (top_k sobre chunks cercanos); reservar modo `global` o `mix` para proyectos con 50+ fuentes indexadas.
- **`valid_at` ausente en entidades del grafo generadas automáticamente**: las entidades creadas por el extractor de hechos de LightRAG no incluyen el timestamp de vigencia requerido por el patrón Compiled Truth. Causa: LightRAG extrae entidades con sus propios campos; el schema de vigencia de swl-ses es una extensión custom que el extractor base no conoce. Solución: agregar un paso de enriquecimiento post-extracción que inyecte `valid_at = hoy` y `invalid_at = null` en cada entidad nueva antes de almacenarla.
