>>`,
+ `|||FIN`, o cualquier resto de las marcas del prompt.
+4. **Sin alfabetos ajenos**: ningún carácter árabe/cirílico/CJK en el resultado (residuo
+ típico de generación que se cuela cuando el modelo "piensa" en otro idioma).
+5. **Mismo nº de párrafos** que el ES (contar apariciones de ``** que el ES — **es el check que más falla y el más
+ importante**: en la carta 739, el italiano perdió 15 de 39 enlaces en uno de los trozos
+ troceados mientras EN/FR salieron bien, y nada posterior lo detecta si no lo comprobáis
+ aquí. Si hay menos enlaces en la traducción que en el ES, **no la deis por buena**.
+7. **Referencias bíblicas equivalentes**: extraer patrones tipo `capítulo,versículo` de
+ ambos textos y comparar solo capítulo:versículo, **no la abreviatura del libro completa**
+ (el inglés cambia la coma por dos puntos y traduce el nombre: `Mt 15,21-28` en ES pasa a
+ `Matthew 15:21-28` en EN — comparar literal daría un falso positivo de "referencia
+ perdida").
+8. **Título distinto del ES** (salvo portugués, donde algunos nombres propios/citas
+ coinciden de forma legítima).
+
+Capa editorial adicional si tenéis acceso a un modelo capaz de juzgar fidelidad (vuestro
+Claude/Haiku local sirve para esto): pedidle que lea origen y traducción y devuelva un
+veredicto `approve` / `needs_review` / `rewrite` con la cita exacta del problema — descartad
+cualquier hallazgo cuya cita no aparezca literal en el texto (evita ediciones basadas en
+alucinaciones del propio revisor).
+
+## 5. Excepciones que no lleváis por la vía automática
+
+- **Autores que aportan su propia traducción humana** (hoy, Pagola: 4 DOCX por carta,
+ adjuntos en el issue de la semana) — nunca generéis fallback automático para ellos aunque
+ falte alguno de los 4 idiomas.
+- **Textos litúrgicos enlazados desde la carta** (evangelio, lecturas) — confirmar con Rafa
+ si entran en el alcance de "todo lo de la carta" o se dejan fuera; ha habido confusión
+ antes sobre esto (no dar por hecho que "ya deben estar traducidos").
+
+## 6. Cómo leer la cuota de MiniMax
+
+Con el mismo token que ya tenéis para el audio:
+
+```bash
+curl -s https://api.minimax.io/v1/token_plan/remains \
+ -H "Authorization: Bearer " -H "Content-Type: application/json"
+```
+
+Del JSON de respuesta:
+- `base_resp.status_code` debe ser `0` (cualquier otro valor es error de cuenta/plan, ver
+ `base_resp.status_msg`).
+- `model_remains` es una lista por modelo. El de texto/traducción es el que tiene
+ `model_name == "general"`; los de audio son los `speech-2.8-*` que ya usáis para TTS.
+- De cada entrada: `current_interval_remaining_percent` (cuánto queda de la ventana de 5h
+ que se resetea sola — `end_time` es cuándo) y `current_weekly_remaining_percent` /
+ `weekly_end_time` (la ventana semanal, más amplia). Restad a 100 para saber "cuánto habéis
+ gastado" si preferís verlo así.
+
+Igual que con el audio: un HTTP 200 no es garantía de cuota — cuando `t2a_v2` o el endpoint
+de traducción devuelvan `base_resp.status_code=2056` (plan agotado) o `1039` (límite de
+ritmo), parad y reintentad más tarde, no machaquéis la API.
+
+## 7. Qué falta para que esto sea autoservicio de verdad
+
+- **Bloqueante (§0):** endpoint o mecanismo para fijar idioma + enlazar grupo Polylang de
+ cada traducción — sin esto podéis generar el texto pero no "engancharlo" al sitio como
+ traducción real, igual que pasaba con el audio antes del #222.
+- Decisión pendiente de Rafa (no la resuelvo yo aquí): si vuestro agente de traducción va a
+ tener acceso de shell/SSH al WordPress (como tenía Hermes) o va a ser puramente REST como
+ el resto de vuestro trabajo — cambia bastante el diseño del endpoint que haría falta.
diff --git a/docs/guia-tts-traduccion-inma.md b/docs/guia-tts-traduccion-inma.md
index d06ed3e..f6b686e 100644
--- a/docs/guia-tts-traduccion-inma.md
+++ b/docs/guia-tts-traduccion-inma.md
@@ -14,8 +14,13 @@
> token de MiniMax. La §4 de abajo describe el flujo viejo (Hermes ejecutando
> `scripts/tts_produce.py` en el PC de Rafa); para el flujo nuevo de autoservicio, con la receta
> exacta de preparación de texto y pausas, usar
-> **`docs/guia-tts-audio-autoservicio-inma-mixbot.md`**. Las **traducciones** siguen por ahora
-> como se describe en §3 de este documento — no incluidas todavía en el traspaso.
+> **`docs/guia-tts-audio-autoservicio-inma-mixbot.md`**. Rafa confirmó el mismo día que las
+> **traducciones** van también hacia autoservicio (agente local con Haiku desde el Claude de
+> Inma, o MiniMax con el mismo token) aunque todavía sin un issue como el #222 que lo dispare
+> — ver **`docs/guia-traduccion-autoservicio-inma-mixbot.md`** para las reglas, el QA y el
+> hueco de infraestructura equivalente (falta enlazar idioma/grupo Polylang por REST). La §3
+> de abajo sigue describiendo el flujo viejo vía Hermes, todavía válido mientras no se cierre
+> ese hueco.
---
From 8b016844d929e3afa3a1f65a1f53edb46aa6b6f9 Mon Sep 17 00:00:00 2001
From: rafa
Date: Mon, 31 Aug 2026 07:38:22 -0400
Subject: [PATCH 3/4] =?UTF-8?q?docs:=20cerrar=20el=20bloqueante=20del=20#2?=
=?UTF-8?q?22=20=E2=80=94=20endpoint=20subir-audio=20ya=20desplegado?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Actualiza la guía de autoservicio TTS con la llamada real a
fea/v1/subir-audio (#224, ya en producción), verificada de extremo a
extremo por Claudix con una subida real y limpieza posterior.
---
...guia-tts-audio-autoservicio-inma-mixbot.md | 60 +++++++++++++------
1 file changed, 41 insertions(+), 19 deletions(-)
diff --git a/docs/guia-tts-audio-autoservicio-inma-mixbot.md b/docs/guia-tts-audio-autoservicio-inma-mixbot.md
index e512da0..56538a2 100644
--- a/docs/guia-tts-audio-autoservicio-inma-mixbot.md
+++ b/docs/guia-tts-audio-autoservicio-inma-mixbot.md
@@ -4,11 +4,10 @@
> Rafa (issue [#222](https://gitea.feadulta.com/rafa/feadulta/issues/222)): dejar de pedirle
> el audio a Hermes y generarlo y subirlo vosotros mismos, con vuestro propio token de MiniMax.
>
-> **Estado a 2026-08-31:** el proceso de generación (este documento) está completo y probado.
-> **Subir el resultado al artículo sigue bloqueado** — falta un endpoint REST (`fea/v1/subir-audio`)
-> para enganchar el mp3 al post, tal como pedía el punto 1 del #222. Ese endpoint lo está
-> construyendo Codix (ver aviso al final). Hasta que esté desplegado podéis generar y guardar
-> los mp3, pero no publicarlos en el sitio.
+> **Estado a 2026-08-31:** completo y **desplegado en producción**. El endpoint
+> `fea/v1/subir-audio` (PR [#224](https://gitea.feadulta.com/rafa/feadulta/pulls/224)) ya está
+> en prod y verificado de extremo a extremo por Claudix con una subida real. El punto 1 del
+> #222 queda cerrado — ver §6 para la llamada real.
>
> Este documento sustituye, para el caso de uso "Inma/Mixbot generan directamente", a la
> sección 4 de `docs/guia-tts-traduccion-inma.md` (que describe el flujo antiguo vía Hermes
@@ -198,23 +197,46 @@ este paso y avisad a Rafa/Claudix — es preferible subir un audio sin el acabad
nada, pero que quede constancia de que ese paso se saltó (para que quien revise sepa por qué
suena ligeramente distinto al resto).
-## 6. Subir el resultado al artículo — BLOQUEADO hoy
+## 6. Subir el resultado al artículo
-Aquí es donde entra el hueco real que reportó el #222: **no hay forma de enganchar el mp3 al
-post por REST todavía.** Los campos que necesita el sitio para reproducir el audio
-(`fea_audio_url`, `fea_audio_done`, más `fea_audio_voice` para saber qué voz sonó) no están
-expuestos en `/wp/v2/posts/{id}`, y el namespace `fea/v1` no tiene endpoint de audio.
+El endpoint que faltaba ya está desplegado en producción (#224), con el mismo patrón que
+`fea/v1/subir-avatar` (#175) que ya usáis:
-**Esto se resuelve con un endpoint `fea/v1/subir-audio`**, con el mismo patrón que
-`fea/v1/subir-avatar` (#175) que ya usáis: multipart con `post_id` + fichero `audio` (mp3),
-autenticación igual que el resto de endpoints `fea/v1` (vuestro usuario Editor/Administrator),
-y como respuesta el valor anterior de esos metas para poder deshacer si algo suena mal.
-**Codix lo está construyendo** a partir de esta misma información — en cuanto esté
-desplegado, se actualiza este documento con el ejemplo de llamada real y se cierra el punto 1
-del #222.
+```
+POST https://www.feadulta.com/wp-json/fea/v1/subir-audio
+Authorization: Basic (o el header equivalente que useis)
+Content-Type: multipart/form-data
-Mientras tanto: generad y guardad los mp3 con normalidad (pasos 1-5), pero no hay manera de
-publicarlos todavía — no es un fallo vuestro, es infraestructura pendiente.
+post_id=
+audio=
+voice_id=
+```
+
+Respuesta (`201`):
+
+```json
+{
+ "post_id": 56785,
+ "audio_url": "https://www.feadulta.com/wp-content/uploads/tts/56785.mp3",
+ "voice_id": "NicoFeadulta2026",
+ "sha256": "",
+ "previous_audio": {"url": null, "voice": null, "done": null, "sha256": null, "error": null}
+}
+```
+
+`previous_audio` trae el estado de antes de vuestra subida (o todo `null` si el post no tenía
+audio) — guardadlo si vais a reemplazar un audio ya publicado, por si hay que deshacer.
+
+**Límite real: 25 MiB por fichero** (`upload_max_filesize`/`post_max_size` del servidor, y el
+propio endpoint valida lo mismo con un mensaje claro). Los audios de la carta semanal rondan
+5-6 MB, así que hay margen — pero si algún artículo muy largo genera un mp3 más grande,
+avisad en vez de forzarlo: el límite se fijó a propósito en 25 MiB (no en los 256 MiB que se
+había propuesto al principio) porque el caso de 198 MB del #212/#190 era un error de
+generación a corregir, no un tamaño a soportar.
+
+Solo admite `.mp3`/`audio/mpeg` — mismo nivel de permiso que el resto de endpoints `fea/v1`
+de escritura (vuestro usuario Editor/Administrator). Verificado por Claudix el 2026-08-31 con
+una subida real de extremo a extremo contra prod (post desechable, borrado después).
## 7. Lo que NO cambia con este traspaso
From 2f207a5515db71cba3906c22139de91ba79fd3f7 Mon Sep 17 00:00:00 2001
From: rafa
Date: Mon, 31 Aug 2026 07:38:52 -0400
Subject: [PATCH 4/4] =?UTF-8?q?docs:=20a=C3=B1adir=20lectura=20de=20cuota?=
=?UTF-8?q?=20MiniMax=20a=20la=20gu=C3=ADa=20de=20audio?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Rafa confirmó que el backlog historico del #188 se queda con Inma/Mixbot
(su equipo está 24/7, aprovecha mejor las ventanas de 5h de MiniMax) y
pidió documentarles cómo leer la cuota antes de lanzar tandas grandes.
---
docs/guia-tts-audio-autoservicio-inma-mixbot.md | 16 ++++++++++++++++
1 file changed, 16 insertions(+)
diff --git a/docs/guia-tts-audio-autoservicio-inma-mixbot.md b/docs/guia-tts-audio-autoservicio-inma-mixbot.md
index 56538a2..3b20a08 100644
--- a/docs/guia-tts-audio-autoservicio-inma-mixbot.md
+++ b/docs/guia-tts-audio-autoservicio-inma-mixbot.md
@@ -168,6 +168,22 @@ Un HTTP 200 **no significa que haya audio** — hay que mirar siempre el `base_r
cuerpo. Ante cualquiera de estos dos códigos: **parad y reintentad más tarde**, no
machaquéis la API en bucle esperando que cambie.
+**Cómo comprobar la cuota disponible antes de lanzar una tanda** (importante si vais a
+procesar el backlog histórico del #188 además de la carta semanal, para repartir bien las
+ventanas de 5h):
+
+```bash
+curl -s https://api.minimax.io/v1/token_plan/remains \
+ -H "Authorization: Bearer " -H "Content-Type: application/json"
+```
+
+Buscad en `model_remains` la entrada cuyo `model_name` sea el modelo que vayáis a usar
+(`speech-2.8-hd`/`speech-2.8-turbo`). Cada entrada trae
+`current_interval_remaining_percent` (lo que queda de la ventana de 5h, y `end_time` de
+cuándo se resetea) y `current_weekly_remaining_percent`/`weekly_end_time` (la ventana
+semanal). Con eso podéis calcular cuántos audios caben antes de la próxima ventana y
+programar el resto para la siguiente, en vez de descubrirlo con un `2056` a mitad de tanda.
+
## 5. Acabado del audio (opcional pero es lo que suena en producción)
El pipeline actual aplica dos retoques más al mp3 antes de darlo por bueno — no son