Wiki: producción Hetzner, trampas del entorno y mapa del conocimiento heredado
Tres páginas nuevas escritas por Opix, verificadas contra el servidor el 2026-08-12 en solo lectura: - Produccion-Hetzner-acceso: clave SSH correcta (id_ed25519, no feadulta_ed25519), contenedor de Coolify, y el hecho de que no hay WP-CLI (se usa php -r con wp-load.php). - Trampas-del-entorno: las cuatro limitaciones del jail de CDMON que ya no aplican, más las que siguen vigentes, marcando qué está verificado. - Conocimiento-heredado: mapa de las skills de Hermes, la memoria de Claude Code y los scripts, con su estado de vigencia. Home actualizado con aviso de vigencia y enlaces al Gitea vivo (apuntaba a localhost:3000). Ninguna credencial en el contenido.
@@ -0,0 +1,99 @@
|
|||||||
|
# Conocimiento heredado — dónde está todo
|
||||||
|
|
||||||
|
> Levantado por Opix el **2026-08-12**. Mapa de lo que Hermes sabía hacer como
|
||||||
|
> webmaster de feadulta, con el estado de vigencia de cada fuente.
|
||||||
|
|
||||||
|
**Ninguna de estas fuentes es autoritativa por sí sola.** Varias describen el
|
||||||
|
servidor cPanel/CDMON, retirado en el cutover del 2026-08-03. Verifica contra la
|
||||||
|
máquina antes de operar. Ver [[Produccion-Hetzner-acceso]] y [[Trampas-del-entorno]].
|
||||||
|
|
||||||
|
## 1. Skills de Hermes — `~/.hermes/skills/` (WSL)
|
||||||
|
|
||||||
|
Lo más denso y lo más cercano a runbook. ~2.200 líneas.
|
||||||
|
|
||||||
|
### `feadulta/feadulta-webmaster/` — la principal (192 líneas + 10 referencias)
|
||||||
|
Principio operativo: **diagnóstico + preparación + dry-run**; no tocar producción sin
|
||||||
|
instrucción explícita. Cubre:
|
||||||
|
- Endpoints REST acotados para operaciones editoriales (avatar de autor).
|
||||||
|
- Hotfix de contenido con TTS accidental: despublicación reversible del audio.
|
||||||
|
- Cron diario de feedback `fea_feedback` y su diagnóstico.
|
||||||
|
- Triage y contención de incidentes de seguridad (backdoors en mu-plugins).
|
||||||
|
- Retirada segura de bases de datos.
|
||||||
|
- Releases de contenido con carta ya publicada: serialización con lock, snapshot del
|
||||||
|
cluster Polylang completo, doble verificador draft/publish, rollback.
|
||||||
|
|
||||||
|
Referencias: `translation-hotfixes`, `wordpress-compromise-first-response`,
|
||||||
|
`local-docx-carta-preview`, `feedback-beta`, `mysql-three-connection-release-gate`,
|
||||||
|
`rest-editorial-endpoints`, `guarded-release-handoff`,
|
||||||
|
`release-serialization-and-verification`, `access-log-forensics`,
|
||||||
|
`guarded-production-content-releases`, `production-mu-plugin-deploy`,
|
||||||
|
`feedback-cron-dedup`, `wordpress-author-avatar-api`.
|
||||||
|
|
||||||
|
### `feadulta/webmaster/` — skill anterior (71 líneas + 3 referencias)
|
||||||
|
Más concreta y más obsoleta. `references/gotchas.md` y `references/procedures.md`
|
||||||
|
siguen siendo buenos resúmenes; `references/environment.md` describe el prod
|
||||||
|
**anterior**. Su contenido vigente está volcado en [[Trampas-del-entorno]].
|
||||||
|
|
||||||
|
### `feadulta/feadulta-carta-derivados/` (477 líneas + 7 referencias)
|
||||||
|
Traducción + TTS + rotación de la carta semanal. **La skill tiene desviaciones
|
||||||
|
respecto al código** (argparse de `tts_produce.py`, flags `--allow-default-voice` y
|
||||||
|
`--remap-conflicts` que no existen). Usar la versión contrastada, no la skill.
|
||||||
|
|
||||||
|
### `feadulta/feadulta-editorial-workflows/` (100 líneas + 4 referencias)
|
||||||
|
Coordinación semanal con Inma/Mixbot, DOCX omitidos, evangelio diario A/B/C.
|
||||||
|
|
||||||
|
### `feadulta-analytics/` (117 líneas + 1 referencia)
|
||||||
|
GA4: informes y renovación de OAuth. Scripts en `~/.hermes/scripts/feadulta_ga4_*.py`.
|
||||||
|
|
||||||
|
### Fuera de feadulta pero aplicables
|
||||||
|
`devops/self-hosted-service-exposure/`, `devops/caddy-routing-recipes/`,
|
||||||
|
`devops/self-hosted-saas-operations/`.
|
||||||
|
|
||||||
|
## 2. Wiki del servidor — `rafa/server`
|
||||||
|
|
||||||
|
4 páginas. `Backups` es **la mejor escrita y la más actual** de las dos wikis:
|
||||||
|
diseño pull en dos capas, `~/backup-hetzner/pull-hetzner.sh`, verificación real de
|
||||||
|
restauración del 2026-08-01, y trampas de NTFS/rsync/Coolify.
|
||||||
|
|
||||||
|
## 3. Memoria de Claude Code (WSL)
|
||||||
|
|
||||||
|
`~/.claude/projects/-mnt-c-Users-Chia/memory/` — 88 ficheros, índice en `MEMORY.md`.
|
||||||
|
|
||||||
|
| Fichero | Contenido |
|
||||||
|
|---|---|
|
||||||
|
| `master-feadulta.md` (20 KB) | Arquitectura WP, term_ids, Polylang, carta, EFFA, avatares, scripts delta |
|
||||||
|
| `master-infra.md` (17 KB) | Hardware, Tailscale, Docker, LLMs locales, Hetzner, APIs |
|
||||||
|
| `master-gitea.md` (8,7 KB) | Setup, quirks de la wiki, convenciones, comandos API |
|
||||||
|
| `feadulta-migracion-cdmon-hetzner-202607.md` (39 KB) | **El cutover del 2026-08-03** — fuente real del estado actual de prod |
|
||||||
|
|
||||||
|
Y ~35 ficheros `feadulta-*.md` de incidentes y proyectos concretos.
|
||||||
|
|
||||||
|
## 4. Scripts y perfiles
|
||||||
|
|
||||||
|
- `~/.hermes/scripts/` — `fea_feedback_last24h.py`, `fea_tts_backlog_report.py`,
|
||||||
|
`feadulta_ga4_daily.py`, `feadulta_ga4_weekly.py`, `cron_scan.py`.
|
||||||
|
- `~/.hermes/profiles/feadulta/.env` — credenciales de producción.
|
||||||
|
- `~/.env` (permisos 600) — tokens de Gitea.
|
||||||
|
- `~/backup-hetzner/` — pull de backups + alerta Telegram + systemd.
|
||||||
|
- `~/.hermes/SOUL.md` — personalidad general de Hermes ("Luigi"). Sin contenido
|
||||||
|
operativo de feadulta; no hace falta migrarlo.
|
||||||
|
|
||||||
|
## 5. Política de secretos
|
||||||
|
|
||||||
|
**Ninguna credencial en esta wiki.** Solo punteros a los `.env` y a `~/.ssh/`.
|
||||||
|
Decisión de Rafa, 2026-08-12.
|
||||||
|
|
||||||
|
⚠️ La página [[Credenciales-y-accesos]] (junio 2026) **contiene contraseñas en
|
||||||
|
claro** y contradice esta política. Pendiente de decidir su limpieza — ten en cuenta
|
||||||
|
que borrarlas del texto no las quita del historial git de la wiki.
|
||||||
|
|
||||||
|
## 6. Estado de la migración de este conocimiento
|
||||||
|
|
||||||
|
| Bloque | Estado |
|
||||||
|
|---|---|
|
||||||
|
| Acceso a producción | ✅ [[Produccion-Hetzner-acceso]] |
|
||||||
|
| Trampas del entorno | ✅ [[Trampas-del-entorno]] |
|
||||||
|
| Ciclo de la carta (traducción + TTS) | ✅ contrastado con el código, fuera de la wiki |
|
||||||
|
| Áreas funcionales (portada, Polylang, autores, EFFA, buscador) | ⏳ en la wiki desde junio, sin re-verificar contra el código |
|
||||||
|
| Seguridad e incidentes | ⏳ sigue solo en la skill de Hermes |
|
||||||
|
| Despliegue de mu-plugins, backups y rollback | ⏳ pendiente de consolidar |
|
||||||
+25
-10
@@ -1,22 +1,37 @@
|
|||||||
> **Este es el repo activo** — migrado desde el Gitea local de Tailscale el 2026-06-28.
|
> **Este es el repo activo** — migrado desde el Gitea local de Tailscale el 2026-06-28.
|
||||||
> Servidor: **gitea.feadulta.com** (Hetzner FSN1)
|
> Servidor: **gitea.feadulta.com** (Hetzner FSN1)
|
||||||
|
|
||||||
# feadulta.org — Wiki del proyecto
|
# feadulta.com — Wiki del proyecto
|
||||||
|
|
||||||
Portal cristiano español de renovación de la fe. Documentación operativa del proyecto de migración Joomla → WordPress y de su operación.
|
Portal cristiano español de renovación de la fe. Documentación operativa del proyecto
|
||||||
|
de migración Joomla → WordPress y de su operación.
|
||||||
|
|
||||||
**Estado:** migración completa, web protegida con HTTP Basic, cutover DNS previsto ~junio 2026.
|
**Estado:** migración completa. Cutover Joomla→WordPress cerrado el 2026-07-07/08 y
|
||||||
|
cutover de servidor CDMON→Hetzner cerrado el 2026-08-03.
|
||||||
|
|
||||||
|
> ⚠️ **Aviso de vigencia.** Las páginas de operación y arquitectura se escribieron en
|
||||||
|
> junio de 2026, antes del cambio de servidor. Donde describan cPanel/CDMON
|
||||||
|
> (`134.0.10.170`, `/web/wp-nuevo`, `wp-nuevo.feadulta.com`) o el Gitea en
|
||||||
|
> `localhost:3000`, están **obsoletas**. Empieza por
|
||||||
|
> [[Produccion-Hetzner-acceso]] y [[Trampas-del-entorno]].
|
||||||
|
>
|
||||||
|
> **Ninguna credencial debe vivir en esta wiki** (decisión de Rafa, 2026-08-12).
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Índice
|
## Índice
|
||||||
|
|
||||||
### Operación
|
### Operación — empieza por aquí
|
||||||
- [Credenciales y accesos](Credenciales-y-accesos)
|
- [Producción Hetzner: acceso y ejecución](Produccion-Hetzner-acceso) ✅ *verificado 2026-08-12*
|
||||||
- [Infraestructura](Infraestructura)
|
- [Trampas del entorno](Trampas-del-entorno) ✅ *verificado 2026-08-12*
|
||||||
- [Limitaciones del servidor de producción](Limitaciones-servidor-prod)
|
- [Conocimiento heredado: dónde está todo](Conocimiento-heredado)
|
||||||
- [Sincronización local → producción](Sincronizacion-local-prod)
|
- [Sincronización local → producción](Sincronizacion-local-prod)
|
||||||
|
|
||||||
|
### Operación — anterior al cutover de servidor ⚠️
|
||||||
|
- [Infraestructura](Infraestructura) — la sección de producción describe CDMON
|
||||||
|
- [Limitaciones del servidor de producción](Limitaciones-servidor-prod) — **ya no aplican**
|
||||||
|
- [Credenciales y accesos](Credenciales-y-accesos) — ⚠️ contiene contraseñas, pendiente de limpiar
|
||||||
|
|
||||||
### Arquitectura WordPress
|
### Arquitectura WordPress
|
||||||
- [Arquitectura WordPress](Arquitectura-WordPress)
|
- [Arquitectura WordPress](Arquitectura-WordPress)
|
||||||
- [Portada y shortcodes](Portada-y-shortcodes)
|
- [Portada y shortcodes](Portada-y-shortcodes)
|
||||||
@@ -45,7 +60,7 @@ Portal cristiano español de renovación de la fe. Documentación operativa del
|
|||||||
|
|
||||||
## Repo
|
## Repo
|
||||||
|
|
||||||
- **Código:** http://localhost:3000/rafa/feadulta · https://farmer.taild3aaf6.ts.net/git/rafa/feadulta
|
- **Código:** https://gitea.feadulta.com/rafa/feadulta
|
||||||
|
- **Issues:** https://gitea.feadulta.com/rafa/feadulta/issues
|
||||||
- **Directorio local:** `/home/rafa/joomla-migration/`
|
- **Directorio local:** `/home/rafa/joomla-migration/`
|
||||||
- **Issues:** http://localhost:3000/rafa/feadulta/issues
|
- **Wiki del servidor:** https://gitea.feadulta.com/rafa/server/wiki
|
||||||
- **Milestones:** `v1: Pre-cutover` · `v2: Post-launch`
|
|
||||||
|
|||||||
@@ -0,0 +1,105 @@
|
|||||||
|
# Producción (Hetzner + Coolify) — acceso y ejecución
|
||||||
|
|
||||||
|
> Verificado contra el servidor el **2026-08-12** en solo lectura. — Opix
|
||||||
|
>
|
||||||
|
> Esta página **sustituye** a lo que dicen [[Infraestructura]] y
|
||||||
|
> [[Limitaciones-servidor-prod]] sobre producción: ambas describen el servidor
|
||||||
|
> anterior (cPanel/CDMON, `134.0.10.170`, `/web/wp-nuevo`), retirado en el cutover
|
||||||
|
> a Hetzner del **2026-08-03**.
|
||||||
|
|
||||||
|
## SSH
|
||||||
|
|
||||||
|
```bash
|
||||||
|
ssh -i ~/.ssh/id_ed25519 rafa@188.40.120.157
|
||||||
|
# también por Tailscale:
|
||||||
|
ssh rafa@srv1.taild3aaf6.ts.net
|
||||||
|
```
|
||||||
|
|
||||||
|
⚠️ **La clave es `~/.ssh/id_ed25519`** (comentario `claude-code@feadulta`).
|
||||||
|
La otra clave del directorio, `~/.ssh/feadulta_ed25519`
|
||||||
|
(`claude-code@wsl-feadulta-deploy`, mayo 2026), **da `Permission denied`**: es de la
|
||||||
|
etapa CDMON. Es un error fácil de cometer porque el nombre parece el correcto.
|
||||||
|
|
||||||
|
`FEA_PROD_SSH_PASS` en el perfil de Hermes está **vacío a propósito**: la
|
||||||
|
autenticación es por clave. Los scripts `sync_*_to_prod.py` caen a `ssh` normal
|
||||||
|
(sin `sshpass`) cuando esa variable está vacía. No es un valor que falte por rellenar.
|
||||||
|
|
||||||
|
## El contenedor de WordPress
|
||||||
|
|
||||||
|
| | |
|
||||||
|
|---|---|
|
||||||
|
| Contenedor | `wordpress-r2ssjifwj0r0ghyoqd528uaa` |
|
||||||
|
| Imagen | `wordpress:latest` — WordPress **7.0.3** |
|
||||||
|
| PHP | 8.3.31 (CLI) en `/usr/local/bin/php` |
|
||||||
|
| Docroot | `/var/www/html` (volumen persistente `r2ssjifwj0r0ghyoqd528uaa_wordpress-files`) |
|
||||||
|
| BD | contenedor `mysql-r2ssjifwj0r0ghyoqd528uaa` (MySQL 8) |
|
||||||
|
| Servicio Coolify | `feadulta-wp`, uuid `r2ssjifwj0r0ghyoqd528uaa` |
|
||||||
|
|
||||||
|
En el mismo host conviven **tres WordPress** (feadulta, summaraise, aqtalent), el
|
||||||
|
relay de Buzz, el CRM Relaticle, Beszel y el mirror estático de Joomla. Comprueba
|
||||||
|
siempre el nombre completo del contenedor antes de un `docker exec`.
|
||||||
|
|
||||||
|
## ⚠️ No hay WP-CLI en el contenedor
|
||||||
|
|
||||||
|
`command -v wp` → nada. La imagen oficial `wordpress:latest` no lo incluye; no es un
|
||||||
|
fallo de configuración ni algo que se haya perdido.
|
||||||
|
|
||||||
|
**La vía correcta es `php -r` cargando `wp-load.php`** — es lo que describe
|
||||||
|
`FEA_PROD_WPLOAD` del perfil de Hermes.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
ssh -i ~/.ssh/id_ed25519 rafa@188.40.120.157 \
|
||||||
|
"docker exec wordpress-r2ssjifwj0r0ghyoqd528uaa php -r \
|
||||||
|
'require \"/var/www/html/wp-load.php\"; echo home_url(),\"|\",get_bloginfo(\"version\"),\"|\",wp_count_posts()->publish;'"
|
||||||
|
```
|
||||||
|
|
||||||
|
Salida real del 2026-08-12:
|
||||||
|
|
||||||
|
```
|
||||||
|
https://www.feadulta.com|7.0.3|29435
|
||||||
|
```
|
||||||
|
|
||||||
|
### Scripts largos
|
||||||
|
|
||||||
|
```bash
|
||||||
|
scp -i ~/.ssh/id_ed25519 script.php rafa@188.40.120.157:/tmp/script.php
|
||||||
|
ssh -i ~/.ssh/id_ed25519 rafa@188.40.120.157 \
|
||||||
|
'docker cp /tmp/script.php wordpress-r2ssjifwj0r0ghyoqd528uaa:/tmp/script.php && \
|
||||||
|
docker exec wordpress-r2ssjifwj0r0ghyoqd528uaa php /tmp/script.php'
|
||||||
|
```
|
||||||
|
|
||||||
|
⚠️ Para copiar **directorios**, usa `docker cp origen/. <c>:/destino/` con el `/.`
|
||||||
|
final. Sin él, si el destino ya existe, Docker crea `destino/origen` anidado — y
|
||||||
|
WordPress no carga mu-plugins desde subdirectorios, así que el despliegue queda
|
||||||
|
silenciosamente inactivo. Ver [[Trampas-del-entorno]].
|
||||||
|
|
||||||
|
## Verificación: Cloudflare sigue delante
|
||||||
|
|
||||||
|
`curl -sI https://www.feadulta.com` devuelve **403** con `cf-mitigated: challenge`,
|
||||||
|
incluso desde el propio servidor. No se puede certificar nada con curl, Playwright,
|
||||||
|
headless ni `wp_remote_get`. La verificación de producción es **server-side**
|
||||||
|
(`docker exec … php -r`) o navegación humana real.
|
||||||
|
|
||||||
|
Desde dentro del servidor, `curl -H 'Host: www.feadulta.com' http://127.0.0.1/`
|
||||||
|
sí llega al origen (302), saltándose Cloudflare.
|
||||||
|
|
||||||
|
## Credenciales
|
||||||
|
|
||||||
|
**No están en esta wiki y no deben estarlo.** Viven en:
|
||||||
|
|
||||||
|
- `~/.hermes/profiles/feadulta/.env` (WSL) — host SSH, contenedor, wp-load.
|
||||||
|
- `~/.env` (WSL, permisos 600) — tokens de Gitea.
|
||||||
|
- `~/.ssh/id_ed25519` — clave de acceso al servidor.
|
||||||
|
|
||||||
|
## Local, para contraste
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker exec wordpress-web php -r 'require "/var/www/html/wp-load.php"; echo home_url();'
|
||||||
|
docker cp /tmp/x.php wordpress-web:/tmp/x.php && \
|
||||||
|
docker exec wordpress-web wp eval-file /tmp/x.php --allow-root --path=/var/www/html
|
||||||
|
```
|
||||||
|
|
||||||
|
El local **sí** tiene wp-cli pero **no** cliente `mysql`: `wp db query` falla, hay que
|
||||||
|
usar `wp eval-file`. QA visual siempre contra `https://farmer.taild3aaf6.ts.net/fea/`,
|
||||||
|
que es el `siteurl` real — `localhost:8081` sirve desde la raíz y las `@font-face`
|
||||||
|
caen por CORS.
|
||||||
@@ -0,0 +1,110 @@
|
|||||||
|
# Trampas del entorno
|
||||||
|
|
||||||
|
> Consolidado por Opix el **2026-08-12** desde las skills de Hermes, filtrado contra
|
||||||
|
> el estado real del servidor tras el cutover a Hetzner del 2026-08-03.
|
||||||
|
>
|
||||||
|
> Lo marcado **[verificado]** se comprobó contra la máquina ese día. El resto es
|
||||||
|
> documentación heredada **sin re-verificar**: trátalo como pista, no como hecho.
|
||||||
|
|
||||||
|
## Ya NO aplican — eran del jail de CDMON [verificado]
|
||||||
|
|
||||||
|
Estas cuatro condicionaban buena parte de los procedimientos antiguos y **hoy son
|
||||||
|
falsas**. Si las lees en [[Limitaciones-servidor-prod]] o en las skills de Hermes,
|
||||||
|
están obsoletas.
|
||||||
|
|
||||||
|
| Trampa vieja | Realidad en Hetzner |
|
||||||
|
|---|---|
|
||||||
|
| `proc_open()` deshabilitado | `disable_functions` vacío, funciona |
|
||||||
|
| No hay `mysqldump` ni `stat` | `stat` en el contenedor WP; `mysqldump 8.4.10` en el de MySQL |
|
||||||
|
| `php` y `grep` rotos (GLIBC) | PHP 8.3.31 y `grep` correctos |
|
||||||
|
| `scp`/`sftp` no funcionan | `scp` y `docker cp` normales |
|
||||||
|
|
||||||
|
Importa más de lo que parece: varios procedimientos daban rodeos (subir ficheros con
|
||||||
|
`ssh 'cat > ruta'`, backups selectivos post a post, usar `wp` para todo porque `php`
|
||||||
|
estaba roto) que hoy son innecesarios. Copiarlos tal cual hereda los rodeos.
|
||||||
|
|
||||||
|
Lo que **sí** falta hoy dentro del contenedor de WordPress: `wp`, `mysql`,
|
||||||
|
`mysqldump`, `git`, `python3`. Sí hay: `php`, `curl`, `grep`, `stat`, `tar`.
|
||||||
|
|
||||||
|
## Siguen vigentes
|
||||||
|
|
||||||
|
### Cloudflare bloquea curl y headless [verificado]
|
||||||
|
403 con `cf-mitigated: challenge`, también desde el propio servidor. Verificación
|
||||||
|
de prod siempre server-side. Ver [[Produccion-Hetzner-acceso]].
|
||||||
|
|
||||||
|
### `docker cp` anida directorios en silencio [verificado]
|
||||||
|
Si el destino ya existe como directorio, `docker cp origen <c>:/ruta/destino` crea
|
||||||
|
`destino/origen`. Pasó desplegando mu-plugins el 2026-08-12: acabaron en
|
||||||
|
`wp-content/mu-plugins/mu-plugins/` y el lint posterior los dio por desaparecidos,
|
||||||
|
con la conclusión equivocada de que el volumen no persistía.
|
||||||
|
|
||||||
|
Dos consecuencias:
|
||||||
|
1. **WordPress no carga mu-plugins desde subdirectorios** — solo los `.php` del
|
||||||
|
primer nivel. Un despliegue anidado no falla: queda inactivo sin avisar.
|
||||||
|
2. Antes de concluir "no persiste", mira el mount real:
|
||||||
|
```bash
|
||||||
|
docker inspect --format '{{range .Mounts}}{{.Type}} {{.Destination}} <- {{.Source}}{{println}}{{end}}' <container>
|
||||||
|
docker inspect --format 'Created={{.Created}} StartedAt={{.State.StartedAt}} RestartCount={{.RestartCount}}' <container>
|
||||||
|
```
|
||||||
|
En feadulta, `/var/www/html` es el volumen `r2ssjifwj0r0ghyoqd528uaa_wordpress-files`
|
||||||
|
y el contenedor no se recrea desde el 2026-08-03 (`RestartCount=0`).
|
||||||
|
|
||||||
|
Usa `docker cp origen/. <c>:/destino/` para volcar contenido sin anidar.
|
||||||
|
|
||||||
|
### hub-proxy nunca devuelve 404
|
||||||
|
El nginx del hub responde la portada del Hub con **200 + text/html (20.597 bytes)**
|
||||||
|
para cualquier ruta desconocida. Comprueba `content_type` y tamaño, no solo el código.
|
||||||
|
|
||||||
|
### Charset: el CLI de MySQL conecta en latin1
|
||||||
|
Columnas en utf8mb4. Siempre `mysql --default-character-set=utf8mb4`, o corrompe acentos.
|
||||||
|
|
||||||
|
### La categoría de la carta está partida en tres
|
||||||
|
6 `cartasemana` → 22 `carta-semana-pasada` → 21 `cartas-de-otras-semanas`.
|
||||||
|
Buscar siempre en las tres. Ver [[Carta-de-la-semana]].
|
||||||
|
|
||||||
|
### Heredadas, sin re-verificar
|
||||||
|
- **wp-cli y categorías**: `wp post term set <ID> category 28` asigna el término *de
|
||||||
|
nombre* "28", no el term_id. Usar el slug.
|
||||||
|
- **WP_Tax_Query + Polylang**: `get_posts(['lang'=>$x,'category__in'=>[$c]])` genera
|
||||||
|
`AND 0=1`. No pasar `lang` explícito. `get_term_by('slug',…)` en idioma ≠ ES
|
||||||
|
devuelve `false`: usar `$wpdb->get_var()`.
|
||||||
|
- **Títulos en MAYÚSCULAS** en la BD (legacy Joomla); `fea_title()` los normaliza en
|
||||||
|
el front. Es intencional.
|
||||||
|
- **Single posts usan template FSE** (Twenty Twenty-Five, post 42359), no Astra.
|
||||||
|
- **Páginas desde CLI**: HTML plano con shortcodes, nunca bloques Gutenberg.
|
||||||
|
- **URLs entre entornos**: local cuelga de `/fea`, prod de la raíz. No copiar
|
||||||
|
`post_content` sin reescribir.
|
||||||
|
- **IDs**: los de posts ES coinciden local↔prod; los de attachments y user_meta **no**.
|
||||||
|
|
||||||
|
## Trampas de herramienta (agentes en WSL)
|
||||||
|
|
||||||
|
### `wsl -d Ubuntu -- bash -lc '…'` rompe bucles y rutas
|
||||||
|
Las variables se pierden, los `for … in *.md` se comen los argumentos y las rutas
|
||||||
|
`/tmp/x.sh` se traducen a rutas de Windows. Escribe el `.sh` por UNC
|
||||||
|
(`\\wsl.localhost\Ubuntu\tmp\…`) y lánzalo con `bash -lc 'cd /tmp; bash x.sh'`.
|
||||||
|
|
||||||
|
### `wp eval-file` y las globales
|
||||||
|
Dentro de una función, `global $X` **no** ve las variables del script: pásalas con `use`.
|
||||||
|
|
||||||
|
### Regex en PHP sobre texto español: siempre `/u`
|
||||||
|
`m[áa]s` o `eucarist[ií]as` **sin** el modificador `u` no casan: las vocales
|
||||||
|
acentuadas ocupan 2 bytes y la clase de caracteres parte el UTF-8. Costó un
|
||||||
|
diagnóstico entero equivocado el 2026-08-12.
|
||||||
|
|
||||||
|
### La API de wiki de Gitea
|
||||||
|
Devuelve `content_base64`, no `content`, y da **404 con títulos acentuados** aunque
|
||||||
|
el `sub_url` sea el que ella misma publica. Clona `<repo>.wiki.git` en su lugar.
|
||||||
|
(La wiki vive en el branch `main`; documentación antigua dice `master`.)
|
||||||
|
|
||||||
|
## Trampas de método
|
||||||
|
|
||||||
|
- **Contar en la BD antes de proponer un comando que muta.** No extrapolar el alcance
|
||||||
|
de un fix desde una página renderizada.
|
||||||
|
- **Seguir el camino completo del dato** antes de gritar "fuga a producción".
|
||||||
|
- **"El dato no existe" solo vale tras seguir los enlaces**, no solo los metas.
|
||||||
|
- **Antes de agrupar por un meta de origen, comprobar que no haya varios**: conviven
|
||||||
|
`_fgj2wp_old_k2_id` (K2, 18.121) y `_fgj2wp_old_id` (Joomla core, 9.022).
|
||||||
|
- **Verificar las dos mitades de una rotación**: que la carta nueva entre *y* que la
|
||||||
|
anterior salga.
|
||||||
|
- **Un issue no es un diario.** Si te retractas, se reescribe entero; el rastro va al
|
||||||
|
canal, no al ticket.
|
||||||
Reference in New Issue
Block a user