# Quick Reference: Klaus File Categorization & Policies
**Uso rápido:** Consulta esta tabla para validación de archivos sin leer documentación completa.
---
## Matriz de Decisión: ¿Indexar este archivo?
### Paso 1: Detectar extensión
| Extensión | Categoría | Indexar | Chunking | Prioridad |
|---|---|---|---|---|
| **.py** | CODE_PYTHON | ✓ SÍ | AST (func/class) | ⭐⭐⭐ |
| **.ts, .tsx** | CODE_TYPESCRIPT | ✓ SÍ | Fixed 500c | ⭐⭐⭐ |
| **.js, .jsx** | CODE_JAVASCRIPT | ✓ SÍ | Fixed 500c | ⭐⭐⭐ |
| **.sh, .bash** | CODE_SHELL | ✓ SÍ | Fixed 400c | ⭐⭐ |
| **.go, .rs, .sql, .java, .rb, .php** | CODE_OTHER | ✓ SÍ | Fixed 500c | ⭐⭐ |
| **.md, .rst, .txt** | DOCUMENTATION | ✓ SÍ | Heading split | ⭐⭐⭐ |
| **.json, .yaml, .yml, .toml** | CONFIG_STRUCTURED | ⚠️ FILTRADO | Semantic section | ⭐⭐ |
| **.ini, .conf, .cfg** | CONFIG_UNSTRUCTURED | ❌ NO | — | ⭐ |
| **.html, .xml, .svg** | MARKUP | ❌ NO | — | ⭐ |
| **.css, .scss, .less, .sass** | STYLES | ❌ NO | — | ⭐ |
| **.csv, .tsv, .parquet** | DATA_TABULAR | ❌ NO | — | ⭐ |
| **.png, .jpg, .gif, .webp** | BINARY_IMAGES | ❌ NO | — | ⭐⭐ SKIP |
| **.mp4, .mp3, .wav, .pdf, .docx** | BINARY_MEDIA | ❌ NO | — | ⭐⭐ SKIP |
| **.zip, .tar, .gz, .7z, .rar** | BINARY_ARCHIVES | ❌ NO | — | ⭐⭐ SKIP |
| **.log, .out** | GENERATED_LOGS | ❌ NO | — | ⭐⭐ SKIP |
### Paso 2: Aplicar heurísticos de directorio
Si la extensión no está clara, revisar el directorio:
| Patrón en Ruta | Categoría | Indexar |
|---|---|---|
| `.git/`, `node_modules/`, `vendor/`, `venv/`, `dist/`, `build/` | VENDORED | ❌ NO |
| `tests/`, `fixtures/`, `__tests__`, `spec/`, `specs/` | TEST_FIXTURES | ❌ NO |
| Archivos `.test.`, `.spec.` | TEST_FIXTURES | ❌ NO |
| Archivos `.sample`, `.example`, `.template` | CONFIG_STRUCTURED (pero filtrado) | ⚠️ SKIP |
### Paso 3: Aplicar heurísticos de nombre archivo
| Patrón en Nombre | Categoría | Indexar |
|---|---|---|
| Contiene `log`, `debug`, `.out` | GENERATED_LOGS | ❌ NO |
| Contiene `mock`, `fixture` | TEST_FIXTURES | ❌ NO |
| Archivo vacío o < 40 chars | — | ❌ NO |
| Detecta `is_llm_response()` en contenido | — | ❌ NO |
| Archivo > 50 MB | — | ❌ NO |
---
## Parámetros de Chunking por Categoría
```
┌─────────────────────────────────────────────────────────────────────────┐
│ CÓDIGO PYTHON │
├─────────────────────────────────────────────────────────────────────────┤
│ Estrategia: AST parsing (function/class per chunk) │
│ Chunk size: 500 chars max (unbounded for single def) │
│ Overlap: 0 (AST boundaries) │
│ Min chunk: 40 chars │
│ Extract symbols: ✓ (function/class names) │
│ Fallback: Fixed-size if SyntaxError │
│ Ejemplo: def my_func():\n ... = 1 chunk │
└─────────────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────────────┐
│ CÓDIGO TYPESCRIPT / JAVASCRIPT │
├─────────────────────────────────────────────────────────────────────────┤
│ Estrategia: Symbol extraction + fixed-size │
│ Chunk size: 500 chars │
│ Overlap: 100 chars │
│ Min chunk: 40 chars │
│ Extract symbols: ✓ (function/class/export names) │
│ Ejemplo: export function foo() { ... } │
└─────────────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────────────┐
│ SHELL SCRIPTS │
├─────────────────────────────────────────────────────────────────────────┤
│ Estrategia: Function-aware + fixed-size │
│ Chunk size: 400 chars │
│ Overlap: 80 chars │
│ Min chunk: 40 chars │
│ Extract symbols: ✓ (function names) │
│ Preserve shebang: ✓ │
│ Ejemplo: function deploy() { ... } │
└─────────────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────────────┐
│ DOCUMENTACIÓN (MARKDOWN) │
├─────────────────────────────────────────────────────────────────────────┤
│ Estrategia: Split by H2/H3 headings │
│ Chunk size: 800 chars per subsection │
│ Overlap: 120 chars (preserve context) │
│ Min chunk: 40 chars │
│ Extract symbols: ✓ (heading text) │
│ Preserve struct: ✓ (no split mid-paragraph) │
│ Ejemplo: ## Installation\n...\n### Step 1\n... │
└─────────────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────────────┐
│ CONFIG (JSON/YAML/TOML) │
├─────────────────────────────────────────────────────────────────────────┤
│ Estrategia: Semantic section (top-level keys) │
│ Chunk size: 1000 chars │
│ Overlap: 0 (preserve JSON structure) │
│ Min chunk: 40 chars │
│ Extract symbols: ✓ (key paths: db.connection.host) │
│ Preserve struct: ✓ (don't break JSON objects) │
│ Ejemplo: database: { connection: { host: ... } } │
└─────────────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────────────┐
│ OTROS LENGUAJES (GO, RUST, SQL) │
├─────────────────────────────────────────────────────────────────────────┤
│ Estrategia: Symbol extraction + fixed │
│ Chunk size: 500 chars │
│ Overlap: 100 chars │
│ Min chunk: 40 chars │
│ Extract symbols: ✓ (language-specific: func, type, struct) │
│ Ejemplo (Go): func MyFunc() { ... } │
│ Ejemplo (Rust): fn my_func() { ... } │
│ Ejemplo (SQL): CREATE TABLE users { ... } │
└─────────────────────────────────────────────────────────────────────────┘
```
---
## Embedding & Search Thresholds
| Concepto | Valor | Uso |
|---|---|---|
| **Embedding model** | text-embedding-3-small (1536d) | Dense vectors |
| **BM25 vocabulary** | 30,000 tokens | Sparse vectors |
| **Search strategy** | RRF fusion (dense + sparse) | Hybrid search |
| **KB similarity threshold** | 0.75 | General search (permisivo) |
| **Symbol query threshold** | 0.638 (0.75 * 0.85) | Reduced for variants |
| **Duplicate detection threshold** | 0.92 | Estricto, solo duplicados reales |
| **Prefix semantic enrichment** | `{path}: {symbol_type} {name} —` | Cierra semantic gap |
---
## Decision Tree: ¿Indexar este archivo?
```
┌─ ¿Extensión reconocida?
│ ├─ .py, .ts, .jsx, .md, .yaml, .json
│ │ └─ ✓ Probablemente sí → ver paso 2
│ │
│ └─ .log, .png, .csv, etc.
│ └─ ❌ Probablemente no → ver exclusiones
│
├─ ¿Está en directorio excluido?
│ ├─ node_modules/, tests/, .git/, venv/
│ │ └─ ❌ NO INDEXAR (VENDORED / TEST_FIXTURES)
│ │
│ └─ proxy/, src/, docs/
│ └─ ✓ Continuar
│
├─ ¿Categoría es CODE o DOCUMENTATION?
│ ├─ ✓ SÍ
│ │ └─ INDEXAR (high semantic value)
│ │
│ └─ ❌ NO → ver paso 4
│
├─ ¿Categoría es CONFIG_STRUCTURED?
│ ├─ ¿Archivo es .sample, .example, .template?
│ │ ├─ ✓ SÍ → NO INDEXAR
│ │ └─ ❌ NO → ¿Contiene is_llm_response?
│ │ ├─ ✓ SÍ → NO INDEXAR
│ │ └─ ❌ NO → INDEXAR
│ │
│ └─ ❌ NO → ver paso 5
│
├─ ¿Categoría es CONFIG_UNSTRUCTURED, MARKUP, STYLES?
│ ├─ ✓ SÍ → NO INDEXAR (noise, low semantic value)
│ └─ ❌ NO → ver paso 6
│
├─ ¿Categoría es BINARY, LOGS, TEST_FIXTURES?
│ ├─ ✓ SÍ → NO INDEXAR (bloat, volatile, mocks)
│ └─ ❌ NO → continuación
│
└─ ¿Archivo > 50 MB?
├─ ✓ SÍ → NO INDEXAR (bloat)
└─ ❌ NO → INDEXAR ✓
```
---
## Tabla de Distribución Esperada (9K files)
Para validar que tu validación está funcionando correctamente:
```
INDEXADOS (~4000 files, 43%):
code_python ~219 ✓ Alta prioridad
code_typescript ~54 ✓ Alta prioridad
code_javascript ~54 ✓ Alta prioridad
code_shell ~75 ✓ Media prioridad
code_other ~60 ✓ Media prioridad
documentation ~742 ✓ Alta prioridad
config_structured ~2854 ⚠️ Filtrado (sin .sample)
─────────────────────────────
SUBTOTAL INDEXADOS 4058
SKIPPED (~5300 files, 57%):
test_fixtures ~300 ❌ Mocks
vendored ~3500 ❌ node_modules, etc.
binary_images ~130 ❌ No-textual
generated_logs ~100+ ❌ Volatile
markup ~52 ❌ Tag noise
styles ~54+ ❌ Low semantics
config_unstructured ~50 ❌ Noise
build_artifacts ~50+ ❌ Compiled
─────────────────────────────
SUBTOTAL SKIPPED 4286
```
**Si tu distribución es muy diferente:** Revisar políticas en `should_index_file()`
---
## Ejemplos: Validación en UNA PASADA
### Ejemplo 1: Archivo Python
```python
file_path = "proxy/knowledge.py"
category = detect_file_category(file_path)
# → FileCategory.CODE_PYTHON
should_index, reason = should_index_file(file_path, category)
# → (True, "category_code_python_index")
policy = ChunkingPolicy.for_category(category)
# → ChunkingPolicy(strategy='ast', chunk_size=500, overlap=0, ...)
# Acción: INDEXAR con AST parsing
```
### Ejemplo 2: Archivo Template Config
```python
file_path = "config/app.yaml.example"
category = detect_file_category(file_path)
# → FileCategory.CONFIG_STRUCTURED
should_index, reason = should_index_file(file_path, category)
# → (False, "config_sample_skip")
# Acción: SKIP (es template, no config real)
```
### Ejemplo 3: Imagen en Tests
```python
file_path = "tests/fixtures/logo.png"
category = detect_file_category(file_path)
# → FileCategory.BINARY_IMAGES
should_index, reason = should_index_file(file_path, category)
# → (False, "category_binary_images_skip")
# Acción: SKIP (es binario)
```
### Ejemplo 4: Markdown Documentation
```python
file_path = "docs/API.md"
category = detect_file_category(file_path)
# → FileCategory.DOCUMENTATION
should_index, reason = should_index_file(file_path, category)
# → (True, "category_documentation_index")
policy = ChunkingPolicy.for_category(category)
# → ChunkingPolicy(strategy='heading', chunk_size=800, overlap=120, ...)
# Acción: INDEXAR con heading-split
```
---
## Debug: Líneas de Código Clave
Si necesitas entender qué está pasando:
```python
# Detectar categoría:
from proxy.file_validator import detect_file_category
cat = detect_file_category("proxy/knowledge.py")
print(f"Categoría: {cat.value}")
# Validar indexación:
from proxy.file_validator import should_index_file
ok, reason = should_index_file("proxy/knowledge.py", cat)
print(f"Indexar: {ok}, Razón: {reason}")
# Obtener política:
from proxy.file_validator import ChunkingPolicy
policy = ChunkingPolicy.for_category(cat)
print(f"Estrategia: {policy.strategy}, Chunk size: {policy.chunk_size}")
# Ejecutar validación completa:
python scripts/ingest_all_with_validation.py --report-only
```
---
## Cambios Rápidos
### Aumentar indexación (incluir más archivos)
1. Cambiar en `should_index_file()`:
```python
# Antes:
if category == FileCategory.STYLES:
return False, "category_styles_skip"
# Después:
if category == FileCategory.STYLES:
return True, "category_styles_index"
```
2. Re-ingestionar:
```bash
python scripts/ingest_all_with_validation.py --flush
```
### Reducir indexación (excluir más archivos)
1. Cambiar en `should_index_file()`:
```python
# Antes:
if category == FileCategory.CONFIG_STRUCTURED:
return True, "category_config_structured_index"
# Después:
if category == FileCategory.CONFIG_STRUCTURED:
return False, "category_config_structured_skip"
```
2. Re-ingestionar:
```bash
python scripts/ingest_all_with_validation.py --flush
```
### Cambiar tamaño de chunk
1. Modificar en `ChunkingPolicy.for_category()`:
```python
FileCategory.CODE_PYTHON: ChunkingPolicy(
strategy='ast',
chunk_size=1000, # ← Cambiar de 500
...
)
```
2. Re-ingestionar
---
## Métricas a Monitorear
Después de ingestión, validar:
```json
{
"indexation_rate": 0.89, // Esperado: 0.75-0.95
"total_files": 9368, // ~9K files
"indexed": 8328, // ~8-9K
"skipped": 1040, // Resto
"avg_chunks_per_file": 4.5 // Esperado: 3-8
}
```
**Si indexation_rate < 0.75:** Revisar skip_reasons
**Si avg_chunks_per_file > 15:** Posible over-chunking
**Si avg_chunks_per_file < 1:** Posible under-chunking
---
## Referencias
- **Documentación completa:** `docs/MATRIZ_POLITICAS_INDEXACION.md`
- **Runbook:** `docs/RUNBOOK_VALIDACION_INDEXACION.md`
- **Código:** `proxy/file_validator.py`, `scripts/ingest_all_with_validation.py`
---
**Última actualización:** 2026-07-28