# 02 — La estructura de prompt

Es la pieza central. Todo lo que se genere a partir de aquí usa esto.

## Regla general

El prompt se parte en tramos separados por `BREAK`. El orden importa: primero
**quiénes** están en la escena, después **qué** están haciendo. El `BREAK`
aisla la pose de la identidad, que es lo que hace que la postura no se pierda
contra los tags de pelo y ropa del personaje.


## Prompt maestro

```
masterpiece, best quality, highly detailed, sharp focus, very aesthetic, very awa,
detailed background, <lora:IFL_v1.0_IL:0.7> <lora:add-detail-xl:0.5>
<lora:blackwhiplash(bwl)-guy90-Illust-Lorav3:0.6> blaash, <lora:scara2b_ill_v1.00:0.7> scara2b-style,
<lora:Add_color_ILXLv1:3>,
```

## Patrón de desnudez (canónico)

- **Explicit (gancho principal): `half naked`.** El cosplay/fantasía es lo que busca la audiencia; el outfit se conserva y la escena se da a entender.
- **Tramo final (explicit2): `nude, completely_nude, naked`.** Solo como cierre de la serie.
- `nude, completely_nude, naked` **no** van en el tramo general de chica; van como estado del tramo final. Si el bloque no trae prenda y no es tramo final, basta `half naked`.
- **Color del outfit:** cada prenda lleva su color asignado (`<color>_<prenda>`) y se mantiene en todos los prompts del núcleo del pack. La variación de tono entre personajes es del LoRA; la variación entre imágenes del mismo personaje es fallo de prompt.

## Pareja (dos personas)

```
<MASTER + LoRAs>
BREAK
1girl, <línea del personaje>, half naked
BREAK
1boy, (faceless male:1.4), muscular body, taller male
BREAK
<bloque de pose>
```

## Solo (una persona)

```
<MASTER + LoRAs>
BREAK
1girl, <línea del personaje>, half naked
BREAK
<bloque de pose>
```

> La escena va **dentro** del bloque de pose (ver "La escena va dentro del bloque" más abajo). `batch_progression_v3.py` separa cámara/escena en su propio `BREAK`; es una alternativa de ese script, no la estructura canónica.

## Reglas dentro de cada tramo

### El bloque va sub-agrupado por categoría

Adoptado el 07-10-2026. Dentro del tramo de pose, los tags se ordenan por
categoría y no en el orden de confianza del tagger. El orden de un prompt de
Danbooru **sí** influye, y agrupar da un resultado más coherente.

```
pose      lying, prone_bone, sex_from_behind, on_stomach
entorno   outdoors, night, tree, forest, nature
acto      sex, cum, vaginal, saliva
cuerpo    ass, penis, breasts
expresion tongue_out, open_mouth, blush
estado    hetero, nude, uncensored
camara    from side
```

- **El orden recomendado:** pose → entorno → acto → cuerpo → expresión → estado
  → cámara.
- **El ángulo va al final**, como grupo propio. Sin ángulo, el modelo usa el
  frontal por defecto y en escenas de `sex_from_behind` el hombre sale delante
  de la chica, que es incoherente. Con `from side`, `three-quarter view` u
  `over-the-shoulder shot` se respeta.
- **No se separan con `BREAK`.** Son comas dentro del mismo tramo. Promover un
  grupo a `BREAK` es un cambio posterior si algún día hace falta.
- **Antes de generar, se quitan los tags que el bloque repite** de otros tramos:
  `completely_nude` suele venir en el bloque y también se inyecta en el tramo de
  la chica.

> **No se aplica a retroactivo.** Las imágenes ya generadas se quedan como están:
> reagruparlas sería gastar GPU para comparar dos cosas que no se van a
> juxtaponer. Aplica a lo que se arme a partir de ahora.

### El hombre se describe poco

Cuanto menos se describa, menos se rompe. Se quitó toda la especificación larga
(`no face, blank face, featureless face, eyes closed, black hair, short hair,
large hands, masculine physique, nude male, larger male`) y se dejó:

`1boy, (faceless male:1.4), muscular body, taller male`

Los rasgos marcados en la cara **se aceptan**. No se persiguen.

> Nota: `assemble_prompt()` define `MALE_FULL` con `broad shoulders` incluido. La plantilla `Config/male_template.txt` conserva la especificación larga anterior (con `no face`, pelo, etc.); no usar sus variantes de pelo/cuerpo para la escena canónica.

### En POV el hombre se reduce a casi nada

```
1boy, muscular body
```

Fuera `(faceless male:1.4)`, `broad shoulders` y `taller male`. Motivo medido:
en POV `(faceless male:1.4)` llegaba a crear un segundo hombre en la escena.

### Los conteos van una sola vez

`1boy` y `1girl` como máximo una vez en todo el prompt.

> **Motivo:** el bloque del WD14 trae `1boy` y el script lo inyecta otra vez por
> la vía del hombre. `1boy, ..., 1boy, ...` lo lee como **dos hombres**. Confirmado
> por el usuario con regeneraciones.

### La desnudez va con la chica (patrón vigente)

Por defecto en explicit use `half naked` en el tramo de la chica. Para el tramo final (explicit2/cierre) use `nude, completely_nude, naked` en el tramo de estado final, no en el general de chica. Se inyectan solos cuando el bloque no trae ninguna prenda y el stage lo pide, porque algunos LoRA traen ropa horneada y sin esto la chica sale vestida (Yelan salía en bikini con un bloque que pedía desnuda).

> Nota de implementación: `assemble_prompt()` en `Engine/test_blocks.py` hoy inyecta `nude, completely_nude, naked` cuando `force_nude` o cuando el bloque no trae ropa. `half naked` aún no está implementado en `Engine/` — viene del sandbox `_sandbox_cl_tagger/` (scripts `run_momo_*`, `run_uzaki_*`). La regla de arriba es el objetivo canónico; al implementar, `stages.py` debería mapear `explicit1 → half naked` y `explicit2 → nude`.

### Fuera `age up, mature female`

No se usa. Forzaba rasgos maduros —y por tanto busto— que chocan con
personajes de complexión pequeña (Furina). Está disponible como `--age-up`
por si algún día hace falta.

### Fuera los tags de cuerpo completo

`(full body:1.2)`, `wide shot`, `whole body visible`, `both characters fully
visible`.

> **Aviso — esto contradice una medición anterior.** El freno de cámara se
> probó como solución para que el encuadre se comiera el cuerpo, y funcionó en
> Raiden y Yelan. Se descartó después porque al alejar la imagen el detalle cae
> mucho en calidad. Si algo sale mal encuadrado, la causa probable es esto.

### El `solo` desaparece en escena de pareja

El MASTER trae `1girl, solo`. Con dos personas se quita `solo` antes de
ensamblar, porque pelea con la pose y hace que el modelo ignore al hombre.

## Cómo se implementa

Todo en un sitio: `assemble_prompt()` en `Engine/test_blocks.py`. Recibe
`(master, char_line, block)` y devuelve el prompt con los `BREAK`. El
regenerador usa esa misma función, así que una regeneración y una generación
normal dan el mismo prompt por construcción.

```python
from test_blocks import assemble_prompt
prompt, tramos = assemble_prompt(master, char_line, block)
```

## La escena va dentro del bloque

Decisión: **no** se separa. Los bloques ya traen su contexto (`beach`, `onsen`,
`indoors`) y partirlo exigiría decidir qué tag es "escena" y cuál es "pose". El
`BREAK` de escena queda reservado para cuando alimentemos una escena suelta
desde los wildcards.