# 07 - Estado del pipeline (actualizado 8-11-2026)

Foto del proyecto a día de hoy. El detalle operativo está en `../AGENTS.md`; el
diseño del Eje A, en `../docs/superpowers/specs/`. Este archivo es el "dónde
estamos y qué falta".

## Resumen

Dos pipelines conviven:

1. **Pipeline de bloques WD14** (origen): imágenes de referencia → tagger → bloques
   de prompt → se prueban sobre personajes → pool curado. Es el que alimenta
   poses/estados/ropa.
2. **Eje A (metadatos Danbooru)** (nuevo): seeds de Danbooru → bloques, pools y
   **temas** curados/auto → `pack_builder` compone **packs** por tema y stage
   (sugerente → spicy1 → spicy2 → explicit1 → explicit2) usando el **banco de poses**.

El personaje base ya está curado (216/216 desnudos, solo identidad en la cabeza).
Lo que se construye ahora es **contenido**: packs temáticos listos para auditar.

## Flujo canónico del Eje A

```
danbooru_seeds.txt (129 seeds)
      ↓  danbooru_harvest.py --refresh --limit 100      (API Danbooru, cacheada)
bloques_{sfw,spicy,explicit}.txt + themes.json + snapshot.json + validacion.txt
      ↓  pack_builder.py
pose_bank (poses validadas) ─→ compose_stage_jobs (5 stages; legacy: compose_jobs)
      ↓  PromptBuilder + assemble_prompt (MASTER + LoRAs + BREAK)
Forge Neo txt2img (832x1216, 28 steps, DPM++ 2M Karras, clip_skip 2)
      ↓  auditoría visual humana
Output/pilots/<stamp>/  ·  Output/packs/<char>_<tema>/
```

Un **pack** = N imágenes objetivo (por defecto 45: 9 sugerente / 9 spicy1 /
9 spicy2 / 9 explicit1 / 9 explicit2), con un outfit base por pack y
modificadores por stage, escena + props + luz del tema, y poses del banco
reusadas como máximo 2 veces.

Un **batch de personajes** (`batch_poses_chars.py`) es otra cosa: N personajes ×
3 niveles, **una pose distinta por imagen** (reparto manual sin reemplazo,
fijado con `bank_ids`) y **un tema por personaje**. Sirve para medir el banco,
no para producir un pack. Las imágenes sueltas se corrigen con
`regen_batch_items.py` (mismo job, semilla nueva) y las hojas de auditoría con
`audit_batch_sheets.py`.

## Números actuales

| Métrica | Valor |
|---|---|
| Personajes en catálogo | 216 (`Archivos/personajes.txt`) |
| LoRAs en disco | 389 (`models/Lora/`) |
| Seeds Danbooru | 129 |
| Bloques | 124 (52 sfw / 36 spicy / 36 explicit) |
| Temas | 27 (19 curados + 8 auto) |
| Etiquetas en snapshot | 31.175 (3.854 aceptadas) |
| Poses en banco | **72** (23 sugerente / 28 spicy / 21 explícito); `pb0005` y `pb0012` siguen en blacklist. +16 el 2-nov (`pb0057`–`pb0072`, `provenance: danbooru_harvest_v3`) |
| Piloto por tema | 17 temas × 3 niveles = 51 imágenes |
| Pack real actual | 45/45 (`Makima_v2_oficina`: 36 banco + 9 explore). **Velina Airgid `playa` (7-nov): 45/45 generadas pero descartado** — vestuario inconsistente (ver decisiones 8-11) |
| Batch personajes × poses | 12 personajes × 3 niveles = 36 imágenes, 36 poses únicas |

## Avance

| Fase | Estado |
|---|---|
| Catálogo de personajes + LoRAs | Cerrado (216 líneas, 0 colisiones) |
| Curación "base desnudo" (accesorios/ropa de cuerpo) | **Cerrada** (0 pendientes, 73 curados, 5 excepciones de identidad) |
| WD14 tagger (`wd-swinv2-tagger-v3`) | Operativo (ONNX CPU, ~1,5-1,9 s/img) |
| WD14 harvest / bloques | Operativo; wildcards sin regenerar tras arreglos de regex |
| Eje A T1-T9 (`danbooru_client`/`harvest`/`pack_builder`) | **Completo** (T9/GAP B = props, aprobado) |
| Catálogo de temas + semillas | Ampliado (129 seeds, 27 temas) |
| Banco de poses | **72**: 13 base + 21 de `explore` (fase 1) + 5 de calibración (fase 2) + 17 del corpus Danbooru (fase 3) + **16 (`pb0057`–`pb0072`, 2-nov, `danbooru_harvest_v3`: 7 sugerente / 9 spicy)** |
| Fase 2 de poses (calibración) | **+5 al banco**: 3 sugerente / 0 spicy / 2 explícito (`pb0035`–`pb0039`) |
| Fase 3 de poses (corpus Danbooru) | **+17 al banco** (`pb0040`–`pb0056`); 24 candidatas, 7 descartadas sin blacklistear |
| Batch personajes × poses × entornos | **`batch_poses_chars.py`** operativo: 12×3 = 36 imágenes, 36 poses y 36 semillas únicas |
| Regeneración selectiva de un lote | **`regen_batch_items.py`** operativo (job exacto + semilla nueva) |
| Pilotos por tema | 17 temas validados (entorno 17/17) |
| Packs reales | 1 generado y aceptado a 45 (`Makima_v2_oficina`: 36 banco + 9 explore) |
| Auditoría automática | **No existe**: se audita a ojo |

## Decisiones del 20-10-2026 (medidas)

- **`on_bed` no se clasifica como escena** (solo `^bed$`): imponía una cama en
  cualquier tema. Se quita del banco (`clean_bank_lines.py`).
- **La blacklist del banco es por línea normalizada**, no por id: editar una línea
  blacklisted la devuelve al pool. Re-aplicar tras tocar líneas.
- **Seed fija + pose reutilizada = imagen idéntica.** Decisión: **seed aleatoria
  por imagen**; fija solo para corregir una imagen concreta.
- **Packs por stage, no por nivel.** 45 imágenes = 9/9/9/9/9; un outfit base por
  pack + modificadores por stage; cámaras por stage y `from side` no se fuerza.
- **`spicy2` es explícito para X**; `explicit1` bloquea cum/orgasm y `explicit2`
  lo permite. Los warnings pose↔escena no añaden props.
- **`pb0012` (`standing_sex`) dibuja dos hombres** con un solo `1boy`; en blacklist
  hasta regen con seed nueva.
- **`looking_at_another`** implicaba una segunda persona en escenas de pareja; fuera.
- **Fiesta**: el vestido de cóctel necesita personaje con canon de vestido
  (Chizuru) y refuerzo `(cocktail dress:1.3)`, no solo el tag.
- **Fase 1 de poses (20-10-2026): +21 al banco.** Se revisaron 32 candidatas de
  80 manifests `explore`; 21 pasaron (5/10/6) y 11 se descartaron por clones,
  línea que no coincide o contenido explícito en spicy. Cobertura del pack:
  44/55 del banco (antes 22/55; target actual: 45). No se blacklisteó ninguna candidata.
- **Dedupe de `pose_harvest.py` por `signature()` + Jaccard ≥0.7**, no por texto
  exacto: el mismo conjunto de tags en otro orden no crea una pose nueva.

## Decisiones del 26-10-2026 (medidas)

- **Fase 3 de poses: +17 al banco (`pb0040`–`pb0056`)** desde el corpus Danbooru
  offline (8.834 posts cacheados → 675 tags de pose). 24 candidatas calibradas
  con **una semilla distinta por pose**; 7 descartadas y **movidas, no
  blacklisteadas** (`Output/pose_calibrate/20261026_165945/descartadas/`).
- **El banco es ahora 56 / 54 útiles (16 sugerente / 19 spicy / 21 explícito).**
  El cuello de botella de un lote sin repetir pose es **sugerente = 16**.
- **El reparto de poses de un lote es manual y sin reemplazo.** El contador de
  reutilización de `pack_builder` es por personaje, no global; el driver fija
  cada pose con `bank_ids`.
- **`1girl` + `from_behind` sin `solo` produce un hombre intruso.** Corregidas
  6 poses (`pb0019`, `pb0022`, `pb0023`, `pb0024`, `pb0028`, `pb0030`).
- **La pose no dicta la ropa.** `bare_shoulders` fuera de `pb0003`: el estado de
  ropa lo decide el outfit.
- **Un outfit de torso necesita su tag de manga.** `biblioteca.sweater` recibió
  `long sleeves`; sin él, `arms_up` lo convertía en suéter sin mangas y espalda
  al aire.
- **`backless` no existe como tag Danbooru**; para repelerlo:
  `bare_back, off_shoulder, sleeveless, strapless` en el negative.
- **Formato vertical ≠ horizontal.** 5 poses correctas no se leen en 832×1216 y
  `pb0009` salió sin hombre. Se **aprueban en vertical** y se mapean para un
  pase horizontal futuro; no se regeneran.

## Decisiones del 8-11-2026 (medidas)

- **Banco ampliado a 72 (23 sugerente / 28 spicy / 21 explícito).** El 2-nov se
  añadieron `pb0057`–`pb0072` (7 sugerente / 9 spicy) desde `danbooru_harvest_v3`,
  con `ref_png` en `refs/`. Sugerente pasa de 16 a 23 (objetivo ≥20 alcanzado).
- **Pack Velina Airgid `playa` (7-nov): generado y DESCARTADO.** 45/45 imágenes,
  0 fallos mecánicos, pero **no prometedor: vestuario inconsistente**. Todas las
  45 salieron con `outfit_fallback: true` (tema `playa` sin `outfit_story`):
  31 `bikini` + 5 `beach_skirt` + 9 sin outfit (explicit2). El tag `bikini`
  renderiza como bañador blanco de una pieza en unas imágenes y como bikini
  azul de tirantes en otras, y `beach_skirt` se coló en explicit1
  (`pb0032`, `pb0036`, `pb0050` y un `explicit1_new`). Conclusión: no publicar;
  **ningún pack se lanza sin `outfit_story` curado para su tema** (25 pendientes,
  Tarea 3 / D3.5). Ver `Output/packs/velina airgid_playa/pack_manifest.json`.
- **Burnice White en horizontal (3-nov).** 18 escenas explícitas `*_horiz_*`
  (1216×832) con `manifest.json` en `Output/Burnice_Horizontal_Progression/`.
  Es prueba de contenido horizontal, no el pase horizontal de las 5 poses flojas.
- **Wildcards `_harvest` creados** (`pose/scene/outfit/state/expression/camera/otros`,
  fusión deduplicada Uzaki + Momo). Originales intactos. Pendiente: revisión y
  fusión manual en los wildcards principales y decisión de integración.
- **Auditorías visuales pendientes**: `Output/test_momo/` (20 imgs, seeds 4001–4020),
  `Output/test_uzaki/` (20 imgs, seeds 5001–5020 + `2222.png` suelta) y
  `Output/test_uzaki_fix/` (7 regens, seeds 6001–6007; mapa en `_sandbox_cl_tagger/regen_uzaki_fix.py`).

## Siguiente

1. **Curar `outfit_story` de los temas** antes de cualquier pack nuevo (25 pendientes
   en D3.5); `playa` es la prueba de que sin él el vestuario se rompe.
2. Pase **horizontal** de las 5 poses flojas + `pb0009` (mapa en `AUDITORIA.md` del batch).
3. Filtro de clones/duplicados (hash perceptual) en las líneas de exploración.
4. Regenerar `Archivos/wildcards_harvest/*` (se construyó con los regex viejos) y
   fusionar los útiles de `_harvest`.
5. Decidir si `pb0012` se recupera (seed nueva) o se retira del banco.

## Referencias

- `08-diseno-stages-vestuario-camara.md` — diseño de 5 stages, outfit base, cámaras y pose↔escena
- `../docs/superpowers/specs/2026-10-18-danbooru-metadata-expansion-design.md`
- `../docs/superpowers/plans/2026-10-18-danbooru-metadata-expansion.md`
- `../AGENTS.md` — mecánica diaria y gotchas
- Ledger de ejecución: `sdd-danbooru/progress.md` (fuera del repo)
