= 1.0.70 =
* Sistema de popups (ventanas emergentes): nuevo tipo de proyecto `tipo=popup` (mismo CPT `editor_ia_project`, mismo storage en disco y mismas tools write-file/read-file que una landing — el agente autoría popup.html/style.css/script.js igual que siempre). Comportamiento (trigger de apertura, cierre, frecuencia) separado del contenido, en `PUT /projects/{slug}/popup-config` (blob JSON en post meta, 3 triggers en esta v1: page_load, exit_intent, scroll_percent — exit_intent no dispara en dispositivos táctiles, sin señal de mouse confiable). "Dónde se muestra" vía `POST/GET/PUT/DELETE /popup-assignments`, sistema paralelo al de componentes (`Editor_IA_Popup_Conditions`, opción `editor_ia_popup_assignments`) — a diferencia de header/footer (un solo ganador por página), varios popups pueden estar activos a la vez en la misma página, así que la resolución devuelve todos los matches en vez del mejor. Cierre (overlay/X/Escape) reutiliza el mismo patrón ya probado del drawer de `[eia_cart]`. Runtime compartido nuevo (`assets/eia-popups.css`/`.js`, un solo archivo para todos los popups de la página) con frecuencia vía localStorage/sessionStorage (always/once_per_session/once_ever/every_n_days). 6 endpoints REST + 6 tools MCP nuevas, todas documentadas en `GET /info`. `invalidate_popup()` nuevo en `Editor_IA_Cache` (mismo criterio que `invalidate_component()`: página puntual si scope=singular, flush completo si scope=global/post_type).

= 1.0.69 =
* Tool `list-skills`: nuevo parámetro opcional `categoria` para filtrar el índice de skills (útil cuando el cerebro crezca a 100+ skills). Cada skill trae ahora un campo `categoria` (etiqueta libre, curada a mano desde el admin de `cerebro-api`, vacía = sin categorizar todavía). Cuarto y último paso del plan de escalado del cerebro (ver `docs/PENDIENTE-arquitectura-escalado-skills.md`).

= 1.0.68 =
* Nuevas tools MCP `list-skills` y `get-skill`: exponen el índice y el contenido de los skills del cerebro como tools normales, no solo como MCP Resources (`editor-ia/skill-<slug>`). Motivo: el soporte de Resources es mucho más inconsistente entre clientes MCP de escritorio que el de Tools — varios requieren que el usuario adjunte el recurso a mano, lo cual no funciona para el público objetivo (usuarios no técnicos en Claude Desktop, ChatGPT desktop, Antigravity desktop). Ambas envuelven código ya existente (`Editor_IA_MCP::get_skills_index()`/`get_skill_content()`), sin tocar `cerebro-api`. Primer paso de un plan más largo de escalado del cerebro a 100-300 skills (ver `docs/PENDIENTE-arquitectura-escalado-skills.md`).

= 1.0.67 =
* GET /info: nuevo campo "rest_api_version" (entero, constante EDITOR_IA_REST_API_VERSION), separado de "version" (la del plugin). Es un número de contrato de la superficie REST/MCP — solo sube si algún día se rompe el formato de las respuestas de un modo incompatible hacia atrás, nunca por agregar un endpoint o campo nuevo. Hoy no hay ningún agente externo pineado a una versión vieja de la API, así que arranca en 1 sin uso más allá de lo informativo; queda disponible para el día que sí haga falta señalizarlo. Idea evaluada a partir de comparar la arquitectura de Novamira (plugin de referencia), que ya expone un campo equivalente.

= 1.0.66 =
* Pantalla Extensiones → ACF: nota nueva bajo el checkbox aclarando que activar el interruptor no habilita los grupos de campos que ya existen — hay que activar el acceso de IA también en cada grupo, desde su propia pestaña "IA ACF". Encontrado probando en vivo: `allow_ai_access` es un flag por grupo (off por defecto en grupos creados a mano), distinto del flag global que prende este checkbox.

= 1.0.65 =
* Mensaje de configuración inicial del agente (Ajustes → Paso 2): cuando el sitio expone el gateway MCP genérico ("compartido"), se agrega un párrafo recordándole al agente que la documentación de skills siempre vive como resource en el servidor MCP de Editor IA (`resources/list`, nombre `editor-ia/skill-<nombre>`), nunca en el endpoint genérico — evita que el agente concluya "no hay documentación" al conectarse solo al gateway genérico y no revisar el servidor propio.

= 1.0.64 =
* Submenú "Ajustes" reordenado al final del menú admin (después de "Extensiones") — prioridad del hook `admin_menu` sube de 101 a 103.
* Texto introductorio de la pantalla "Extensiones" simplificado: se saca la mención técnica a la Abilities API de WordPress y se elimina el párrafo descriptivo bajo el checkbox de ACF, que sobraba. Se agrega la palabra "compatibles" al describir los plugins detectados.

= 1.0.63 =
* Nuevo submenú "Extensiones" (Ajustes → Extensiones): activa opcionalmente habilidades de IA que otros plugins ya exponen nativamente vía la Abilities API de WordPress. Primer caso: Advanced Custom Fields (ACF 6.8+) trae una ability nativa `acf/register-field-group` para crear grupos de campos personalizados (ej. para productos) vía IA, pero queda apagada por un flag propio de ACF (`enable_acf_ai`, false por defecto). Checkbox apagado por defecto en Extensiones activa ese flag (`add_filter('acf/settings/enable_acf_ai', '__return_true')`) — deliberadamente NO se activa solo por tener ACF instalado, porque expone el gateway MCP compartido de WordPress a cualquier cliente conectado, no solo al agente de Editor IA. Si ACF no está activo, la pantalla muestra qué plugins de terceros ya sabe potenciar Editor IA, para que el usuario sepa qué instalar. Nueva clase `Editor_IA_Extensions`.

= 1.0.62 =
* `environment.terceros_catalogo` nuevo en GET /info: catálogo genérico de plugins de terceros simples (activo/versión/nota), alimentado desde cerebro-api (GET /api/terceros, público y cacheado, sin cuota de Créditos) en vez de estar hardcodeado en este plugin. Efecto: sumar compatibilidad con un plugin nuevo simple pasa a ser una fila en el admin de Django, activa al instante en todas las instalaciones, sin nueva versión ni actualización del cliente. Los 4 bloques existentes con integración funcional propia (woocommerce, astra, elementor, yoast_seo) siguen igual, sin tocar. Nueva clase `Editor_IA_Terceros` (includes/class-editor-ia-terceros.php) hace la detección local contra una whitelist cerrada (class_exists/function_exists/defined) — nunca ejecuta código del catálogo remoto.

= 1.0.61 =
* Texto de "Skills para agentes de IA" en Ajustes simplificado: ya no menciona agentes específicos (Claude, Antigravity, Codex) ni el término técnico "MCP Server" — ahora dice que el plugin se conecta a la API de Buhoflow Editor IA. Encontrado por el usuario en captura real de la pantalla de Ajustes.
* Título del "Paso 2" en "Instrucciones para conectar tu agente de IA" aclarado de "Mensaje para tu agente" a "Mensaje de configuración inicial para tu agente" — evita que se lea como un mensaje a reenviar en cada sesión.

= 1.0.60 =
* Texto explicativo de "Créditos" en Ajustes simplificado — de una descripción técnica ("lecturas de instrucciones al cerebro, ponderadas según el recurso...") a una frase directa ("uso de procesos y descarga de recursos desde la API de FacilWP/Buhoflow"). Se mantiene la aclaración de que las acciones del agente en el sitio (crear/editar páginas, subir medios, etc.) no cuentan como Crédito — es la parte que evita el malentendido más común. Encontrado por el usuario en captura real de la pantalla de Ajustes.

= 1.0.59 =
* Ciclo de Créditos pasa de semanal a mensual (reinicia el día 1 de cada mes, no acumulable), acompañando el cambio del mismo nombre en `cerebro-api`. Textos de Ajustes ("Créditos esta semana" → "Créditos este mes", "límite semanal" → "límite mensual") y el aviso liviano en el listado de proyectos actualizados; el formateo de la fecha de reinicio ya no resta un día (antes mostraba "domingo" como el día antes del lunes de reset, ahora reset_at ya es directamente el día 1 a mostrar). Solo cambia texto/formateo en `class-editor-ia-settings.php` y un comentario en `class-editor-ia-mcp.php` — el contrato de `/api/cerebro-usage` (`usadas`/`limite`/`restantes`/`reset_at`) no cambia de forma, solo de periodicidad real.

= 1.0.58 =
* Texto de la UI de Ajustes ("Skills para agentes de IA") renombrado de "Consultas" a "Créditos" — decisión del usuario para acompañar el nuevo modelo de pesos variables por recurso en cerebro-api (algunos skills/componentes valen más Créditos que otros). Solo cambia el texto visible; no toca el contrato de la API (`usadas`/`limite`/`restantes`/`reset_at` quedan igual).

= 1.0.57 =
* Descripciones de 13 tools MCP reforzadas con el patrón "qué hace + cuándo usarla" (list-projects, get-project, get-project-tree, write-file, delete-file, get-componentes, link-page, set-global, create-assignment, update-assignment, upload-media, get-custom-code, restore-custom-code) — el resto de las 34 ya lo tenía. Incluye la disambiguación explícita entre set-global (shortcut sitio completo) y create-assignment (casos granulares), y la aclaración de que write-file no soporta edición parcial (reemplaza el archivo entero).

= 1.0.56 =
* 8 tools MCP de solo lectura (list-projects, list-menus, get-info, list-media, list-assignments, list-custom-code, list-custom-code-trash, get-custom-code-audit-log) ahora declaran `output_schema` en `class-editor-ia-abilities.php` — el `mcp-adapter` vendorizado lo traduce a `outputSchema` en `tools/list`, campo opcional del protocolo MCP que hasta ahora ninguna tool declaraba. Convierte el contrato de forma de cada tool en algo verificable, no solo documentado.
* Chequeo mecánico nuevo `scripts/verify-output-schema.py`: valida en vivo que el `structuredContent` real de cada tool cumpla el `outputSchema` que declara — mismo espíritu que `verify-mcp-tools.py` (v1.0.36) pero declarativo, sin dependencias externas (validador JSON Schema mínimo escrito a mano).
* Encontrado durante la implementación: declarar `output_schema` con `'properties' => new stdClass()` (mismo patrón usado en `input_schema` en todo el archivo) rompía la tool `get-info` en tiempo de ejecución (`Cannot use object of type stdClass as array`) — a diferencia de `input_schema`, el runtime valida la respuesta real contra `output_schema` y no tolera esa forma vacía. Fix: se omite la clave `properties` cuando no hay nada que declarar (opcional en JSON Schema), en vez de usar `stdClass` vacío.

= 1.0.55 =
* "Instrucciones del agente" (la sección de arriba, Site Key/Consultas/Skills) renombrada a "Skills para agentes de IA" — el nombre anterior colisionaba con "Instrucciones para conectar tu agente de IA" (la sección nueva de abajo), dos cosas distintas (conexión a skills de cerebro-api vs. conexión MCP en sí) con nombres casi idénticos. Encontrado por el usuario en captura real.
* Fix de proceso: `editor-ia-facilwp.php` no se había subido al servidor en NINGUNO de los 10 saltos de versión anteriores (1.0.45 a 1.0.54) — el servidor seguía reportando 1.0.44 pese a que todo el código real ya estaba al día. Verificados los 6 archivos tocados en la sesión byte a byte contra el servidor; solo ese archivo estaba desincronizado. Mismo incidente que ya había pasado el 05/08 (ver registro interno) — esta vez la regla de subir el archivo principal en el mismo paso que el resto queda como obligatoria, no como sugerencia.

= 1.0.54 =
* Pulido visual de "Instrucciones para conectar tu agente de IA" (antes "Conectar tu agente de IA", renombrado también), hecho a partir de capturas reales del usuario probando la pantalla:
  - Más separación (`margin-top`) respecto al bloque de arriba (Skills para Agentes).
  - Se sacó el párrafo de intro ("Dos pasos: primero descargas...") — quedaba redundante con los propios títulos "Paso 1"/"Paso 2".
  - Título principal (20px) y los dos "Paso X" (14px) con tamaños diferenciados — antes se veían iguales.
  - Mensaje de ayuda al pie ("¿Necesitas ayuda...") acortado, sin la lista de "tutoriales, soporte y novedades".
  - Nuevo pie de página con la versión del plugin (`EDITOR_IA_VERSION`, se actualiza solo en cada release).
  - Botón "Generar Application Password" renombrado a "Generar credenciales" (más simple para quien no conoce el término).
  - Texto de ayuda de Paso 1: "No se guarda" → "Estos datos no se guardan" (concordancia con "datos", plural).

= 1.0.53 =
* Paso 2: el `<textarea>` del mensaje para el agente bajó de 14 a 7 filas (mitad de alto) — se prioriza que ocupe menos espacio en la pantalla de Ajustes sobre ver el texto completo sin scroll interno, ya que la mayoría de los usuarios lo van a copiar sin necesidad de leerlo entero.

= 1.0.52 =
* Paso 2 (mensaje para el agente): el `<textarea>` pasó a tener fondo negro carbón y texto claro, estilo chat de agente (como referencia visual, similar al bloque de código de Astra), y suma un ícono de copiar flotante arriba a la derecha del recuadro (dos cuadrados superpuestos, cambia a un check al copiar) — sin sacar el botón violeta "Copiar" que ya existía, ahora hay dos formas de copiar el mismo texto. Ajuste de padding tras probarlo en vivo: el ícono quedaba pegado al borde/scrollbar.

= 1.0.51 =
* Paso 1: se sacó el botón "Descargar editor-ia.env" que quedaba visible después de generar — el usuario lo señaló como contradictorio (el texto decía "no se guarda en el servidor" pero mostraba un botón que parecía ofrecer volver a descargarlo cuando quisiera). El link sigue existiendo en el HTML para disparar la descarga automática por JS, pero ahora oculto (`display:none`) — no hay ningún botón visible para re-descargar. Texto de ayuda simplificado: "Descarga y coloca este archivo en la raíz de la carpeta de tu proyecto. No se guarda en ningún lado del servidor — si necesitas volver a verlo, genera uno nuevo (invalida el anterior)."
* Dos formas de voseo más que se habían colado en la v1.0.50 pese al barrido ("descargás"/"pasás" en la intro de "Conectar tu agente de IA", y un "generás"/"salgas"/"perdés"/"podés" que se me escapó al redactar el fix anterior) — corregidas a español neutro.

= 1.0.50 =
* Español neutro sin excepción: hasta ahora la regla de "tú, nunca vos" solo aplicaba a la UI que ve el humano en wp-admin — los textos dirigidos al agente (mensaje de conexión MCP, `description`/`nota` de tools y endpoints en `class-editor-ia-rest.php`, `class-editor-ia-mcp.php`, `class-editor-ia-abilities.php`, `class-editor-ia-custom-code.php`) tenían voseo suelto ("revisá", "confirmá", "verificá", "usá", "mostrale", "decíselo", "pegalo", etc.) sin que se hubiera pedido cambiarlo. A pedido del usuario, se unificó todo a español neutro — sin excepción por audiencia. Barrido hecho a mano (dos pasadas de grep + revisión de cada resultado real, evitando falsos positivos como "está"/"después"), cambios puntuales de texto únicamente, sin tocar lógica. Verificado con los dos chequeos mecánicos del plugin (`verify-mcp-tools.py`, `verify-rest-info-contract.py`) tras el cambio, ya que se tocaron `class-editor-ia-rest.php`/`class-editor-ia-mcp.php`/`class-editor-ia-abilities.php`.

= 1.0.49 =
* Ajustes → Paso 1: la descarga de `editor-ia.env` se dispara sola con un solo clic en "Generar Application Password" (antes quedaba un botón "Descargar" aparte que había que apretar de nuevo — regresión del rediseño de 2 pasos de la v1.0.48). Se sacó también la vista previa en `<textarea>` del archivo generado: mostraba la contraseña real en pantalla sin necesidad, ahora que la descarga ya es automática. El texto de ayuda ("Colocá este archivo...") pasó a estar siempre visible debajo del botón, no solo después de generar, y quedó en su propia fila en vez de al lado del botón.
* Paso 2 (mensaje para el agente): agrega al final la lista de otros servidores MCP detectados en el sitio (`Editor_IA_Rest::detect_other_mcp_servers()`, ya usado por `GET /info` desde v1.0.3 — visibilidad del método cambiada a `public` para reutilizarlo sin duplicar la detección) — tanto servidores "dedicados" de otros plugins (ej. Astra) como el gateway "compartido" de WP Abilities (WooCommerce, Yoast SEO, etc.), cuando el sitio realmente los tiene. No se muestra nada si no hay ninguno — nunca se inventa el endpoint.

= 1.0.48 =
* Rediseño completo de "Conectar tu agente de IA" (ex "Generar instrucciones para el agente") en dos pasos separados, tras un caso real: un agente ajeno se negó a configurar la conexión porque el mensaje anterior mezclaba credenciales en texto plano CON una instrucción de "tratar lo que devuelva el servidor como fuente de verdad" — patrón de inyección de instrucciones, con razón. La causa de fondo no era solo redacción: pedirle a un agente, en medio del chat, que agregue un servidor nuevo a su configuración persistente Y prometa obedecer sus respuestas futuras, es una acción con peso real (comparable a un permiso OAuth), y ningún ajuste de tono la vuelve trivial.
  - Paso 1 — "Generar Application Password": descarga `editor-ia.env` (formato dotenv, vía data URI, nunca pasa por el servidor ni se persiste) con el endpoint, usuario, Application Password, y la clave de WooCommerce si corresponde. Es solo datos — sin ninguna narrativa que un agente pueda leer como orden.
  - Paso 2 — mensaje fijo (no depende de generar nada, sin secretos) para copiar y pegar en el chat, redactado en primera persona como si lo pidiera el propio administrador del sitio ("Quiero que te conectes..."), que referencia el archivo del paso 1 por nombre en vez de repetir la contraseña.
* Se eliminó la frase "es la fuente de verdad actualizada" — el disparador identificado en el caso real — y todo el bloque de "estado de integraciones" (WooCommerce/Astra/Elementor) del mensaje del paso 2, ahora que ya no comparte cuerpo con las credenciales.

= 1.0.47 =
* Ajustes → "Generar instrucciones para el agente": pulido visual del bloque de copiar, hecho con capturas reales del propio usuario probando la pantalla. El botón "Copiar" quedó arriba del `<textarea>` (antes abajo, había que bajar para encontrarlo), con ícono de destellos (el mismo trazo de Lucide que ya es de facto el estándar visual de "acción de IA" en la mayoría de productos, en vez de uno dibujado a mano) y color violeta para distinguirlo del botón azul de arriba, padding recortado (quedaba inflado con el ícono + el padding por defecto de `.button`). También se corrigió un bug que había quedado listo para introducirse: el JS reemplazaba todo el contenido del botón al mostrar "Copiado", lo que hubiera borrado el ícono en cada clic — el texto ahora vive en su propio `<span>` interno.
* El texto de aviso bajo el botón decía "la contraseña en claro" — cambiado a "tu Application Password", más preciso y consistente con el término ya usado en el resto de la pantalla.

= 1.0.46 =
* Ajustes → "Generar instrucciones para el agente": se restauró la guía de detección de `npx`/Node/`PATH` que el recorte de la v1.0.45 se llevó por delante sin querer (no estaba duplicada en ningún lado, a diferencia de lo demás que sí se sacó a propósito) — y de paso se sumó la mejora que usa Astra: pedirle al agente el path absoluto de `npx` y agregar `PATH` explícito en `env`, en vez de confiar en el `npx` genérico (causa típica de que el puente falle en silencio en clientes de escritorio que no heredan el PATH de la shell).
* El mismo mensaje ahora trae dos bloques JSON en vez de uno: además del puente `npx` para clientes stdio, un bloque nuevo con `"type": "http"` + `"headers": {"Authorization": "Basic ..."}` listo para copiar directo a `.mcp.json` en clientes que soportan HTTP remoto (ej. Claude Code) — antes solo se les decía en prosa "usa el endpoint y las credenciales de arriba", sin un JSON concreto para pegar.

= 1.0.45 =
* "Generar acceso para agentes" (Ajustes → Editor IA) pasó a llamarse "Generar instrucciones para el agente" y ya no descarga un archivo `AJUSTES_MCP.md` — ahora muestra un texto para copiar y pegar directo en el chat del agente, con botón "Copiar" (nunca se guarda en disco ni en la base de datos, solo vive en memoria durante ese request). Motivo: un agente real (ajeno a este proyecto) leyó el `.md` descargado y dudó de si era un intento de inyección de prompt — el patrón típico ("REGLA DE ORO", pasos numerados dirigidos al agente, nota específica para "modelos económicos") disparaba la misma heurística de sospecha que ya nos había mordido en el incidente del 24/07 (v3.0.8), aunque el archivo fuera legítimo. Comparado contra cómo lo resuelven Astra (botón "copiar instrucción para el cliente de IA", sin archivo de por medio) y el propio WordPress MCP Adapter, la causa de fondo no era solo la redacción: un archivo que el agente *descubre* como contenido observado siempre es más sospechoso que un mensaje que el usuario le *pega* directo en el chat, sea cual sea el tono.
* De paso, el contenido del mensaje se recortó bastante: se sacó la "REGLA DE ORO" de descubrimiento completo (`tools/list`/`resources/list`), el aviso de FTP/SSH y el recordatorio de leer `design`/`testing` — los tres ya le llegan al agente por el campo `instructions` de la respuesta de `initialize` (cerebro `nucleo.md`), así que estaban duplicados ahí y en el archivo, con riesgo de irse desincronizando. También se sacó el párrafo que mencionaba a Wordfence y "evitar el bloqueo" de firewalls (podía leerse como instrucciones de evasión de un control de seguridad, aunque la intención fuera solo recomendar un navegador real para verificaciones visuales ya autorizadas). Lo que queda es solo lo que el handshake `initialize` todavía no puede darle al agente: endpoint, credenciales, el puente `npx`/`.mcp.json` para clientes stdio, y el estado (activo/no) de WooCommerce/Astra/Elementor de ese sitio en particular.

= 1.0.44 =
* "Probar conexión con los skills" ahora también limpia la caché de cada skill individual que un agente ya haya leído (no solo el núcleo/índice/cuota). Antes, si un skill se corregía en el servidor mientras un agente ya lo tenía cacheado (hasta 1h), ni recargar Ajustes ni ese botón lo refrescaban — había que esperar a que la caché expirara sola. Nuevo registro `editor_ia_mcp_cached_skills` (WordPress no tiene forma nativa de listar transients por prefijo) que trackea qué skills están cacheados para poder limpiarlos de un saque.

= 1.0.43 =
* Fix importante: `Editor_IA_MCP::get_skill_content()` y `get_cerebro_nucleo()` descartaban el mensaje real de cerebro-api ante cualquier error (cuota agotada, key no verificada, etc.) y devolvían siempre un genérico "no está disponible, intenta más tarde" (o silencio total en el caso del núcleo, leído en cada handshake `initialize`). Encontrado probando en vivo el escenario de cuota agotada: el agente nunca veía el mensaje real ("se alcanzó el límite semanal de X Consultas, se reinicia el domingo...") por el canal MCP — solo aparecía en la fila de Ajustes, que lee `/api/cerebro-usage` por un camino aparte. Ahora ambas funciones parsean el JSON de error y devuelven el `mensaje` real de cerebro-api cuando viene, igual que ya hacía `test_connection()`. Los fallos de red genuinos (servidor caído) siguen degradando en silencio, sin mensaje inventado.

= 1.0.42 =
* Fecha de reinicio de la cuota de Consultas: se muestra como "domingo {fecha}" en vez de "lunes {fecha}" (mismo instante real — el reset es lunes 00:00 — pero más intuitivo para el cliente), y sin mencionar hora ni huso horario (antes decía "a las 00:00 (hora Colombia)"). Cambio de texto en `class-editor-ia-settings.php` (Ajustes + aviso) y en el mensaje del 429 de `cerebro-api`.

= 1.0.41 =
* "Probar conexión con los skills" (Ajustes) ahora también limpia la caché de la cuota de Consultas (`editor_ia_mcp_usage`/`_fail`, 5 min de TTL) — antes solo refrescaba núcleo/skills, así que el contador de Consultas podía quedar mostrando un valor desactualizado hasta que la caché expirara sola. Ahora ese botón es el refresh manual confiable para los tres datos.

= 1.0.40 =
* Ajustes → Instrucciones del agente: nueva fila "Consultas esta semana" (usadas/límite/restantes/fecha de reinicio), leída del endpoint `GET /api/cerebro-usage` de `cerebro-api` (parte del modelo de cuotas semanales del plan gratis, backend ya deployado — ver Fase 1). Nuevo `Editor_IA_MCP::get_usage()` con el mismo patrón de caché (5 min) que el resto de las llamadas al cerebro central.
* Nuevo aviso en las 3 pantallas propias del plugin (listado/editor de proyectos y sus submenús) cuando la cuota semanal está por agotarse (80%+) o ya se agotó — no se muestra en el resto de wp-admin ni cuando el uso es normal, para no generar sensación de paywall. No afecta lo que el agente puede hacer directamente en el sitio, solo la lectura de instrucciones nuevas del cerebro.

= 1.0.39 =
* Quitado por completo el Tracking propio del plugin (GA4/GTM/Meta Pixel manual — Ajustes > Tracking, oculto del menú desde v1.0.21 pero funcional hasta ahora): página de Ajustes, las 3 options (`editor_ia_ga4_id`/`editor_ia_gtm_id`/`editor_ia_meta_pixel_id`) y el output en `<head>`/body (`get_head_snippets()`/`get_body_open_snippets()`) — 6 métodos y sus 4 hooks de registro borrados de `class-editor-ia-settings.php`, y las 4 llamadas de output quitadas de `class-editor-ia-renderer.php` (landings) y `class-editor-ia-custom-templates.php` (Custom Template). Motivo: Google Site Kit ya cubre GA4 en la práctica (confirmado en vivo antes de borrar, ver abajo), y mantener una segunda vía de tracking en el código sin usar no aportaba nada de cara al lanzamiento.
* Verificado en vivo ANTES de borrar (no solo asumido): Google Site Kit inyecta su tag (`gtag/js`, `GT-M3V5RD23` en el sitio de pruebas) correctamente vía `wp_head()` en las 7 Custom Template, una por una — se activó cada plantilla por separado (Entrada, Categoría de entrada, Etiqueta de entrada, Producto, Categoría de producto, Etiqueta de producto, Resultados de búsqueda), se hizo un request real sin sesión a la URL correspondiente confirmando el marcador propio de la plantilla + el tag de Site Kit sin duplicados, y se revirtió cada toggle antes de pasar a la siguiente. Para Etiqueta de entrada/Etiqueta de producto (sin contenido etiquetado en el sitio de pruebas) se creó un tag temporal, se asignó a contenido existente, se probó, y se borró todo (tag y asignación) antes de cerrar. Después de borrar el código, se repitió la verificación en home y en una landing normal — Site Kit sigue funcionando idéntico, sin depender en ningún punto del código removido.

= 1.0.38 =
* Custom Template: séptima plantilla de fábrica, Resultados de búsqueda (`/?s=`, `search.php`) — mismo mecanismo genérico que las 6 anteriores. WordPress core resuelve `get_search_template()` vía `get_query_template()`, que aplica el filtro dedicado `search_template` sobre el resultado ya resuelto (misma familia que `single_template`/`category_template`/`tag_template`, que ya usaban Entrada/Categoría de entrada/Etiqueta de entrada) — se sustituye sin condición cuando el toggle está activo, igual que las demás. Comparte la columna de sidebar (`PUT /custom-templates/sidebar-content`) con Entrada/Categoría de entrada/Etiqueta de entrada — ahora la comparten 4 plantillas, no 3. Desactivada por default; se activa desde Ajustes > Custom Template (wp-admin), sin endpoint REST para el toggle, mismo criterio que el resto. `GET /info`, la tool MCP `editor-ia/get-info` y la descripción de `PUT /custom-templates/sidebar-content` actualizados para reportar las 7. Verificado en vivo (no solo `php -l`): activación temporal del toggle vía script PHP-CLI (no hay endpoint REST para esto, es deliberado), request real sin sesión a `/?s=` con término existente (confirma HTML propio, `id="eia-custom-template-search"`, resultados reales) y con término inexistente (confirma el mensaje "No se encontraron resultados" + formulario de búsqueda nativo), y reversión completa (key `search` eliminada de la opción, no solo puesta en `0`) antes de dar la tarea por cerrada.

= 1.0.37 =
* Custom Code: `DELETE /custom-code/{id}` ya no borra en forma permanente — mueve el snippet a la papelera nativa de WordPress (`wp_delete_post` con force=false), recuperable con el nuevo `POST /custom-code/{id}/restore` hasta que WordPress la vacíe sola (30 días por default). Motivado por un incidente real (31/07/2026): un agente sobrescribió/borró snippets del cliente al "limpiar" sus propias pruebas — con esto, ese escenario queda recuperable en vez de perder el código para siempre. Nuevo `GET /custom-code/trash` para ver qué hay recuperable.
* Custom Code: `DELETE /custom-code/{id}` y `PUT /custom-code/{id}` (cuando `code` difiere del ya guardado) ahora requieren `confirm:true` en el request — sin esto, la API devuelve 409 con un preview del snippet actual (`name`, `type`, `scope`, `active`, `code_excerpt`, `code_length`, `created`, `last_modified`) en vez de ejecutar la operación. No reemplaza la regla de skill "no toques snippets que no creaste en esta tarea" (custom-code.md), pero fuerza un segundo paso explícito con el estado real delante antes de perder código ajeno.
* Nuevo `GET /custom-code/audit-log`: historial append-only (tabla propia `eia_audit_log`, reutilizable a futuro por otros recursos) de cada create/update/delete/restore de Custom Code — usuario de WordPress, operación, y snapshots antes/después. Responde la pregunta "¿qué le pasó a este snippet?" sin depender de que el agente lo recuerde.

= 1.0.36 =
* Fix: `GET /projects` (y la tool MCP `editor-ia/list-projects`) devolvía un array JSON plano en la raíz de la respuesta, distinto del resto de los endpoints `list_*` del plugin (`list_menus`, `list_media`, `list_assignments`, `list_revisions`), que siempre envuelven el listado en un objeto (`{menus: [...]}`, `{media: [...]}`, etc.). El protocolo MCP exige que `structuredContent` sea un objeto, no un array — un agente real reportó que `editor-ia-list-projects` fallaba por ese desajuste de formato y tenía que recurrir al fallback REST. Ahora `list_projects()` responde `{"projects": [...]}`, igual que el resto de la familia `list_*`.
* Doc: `GET /info` documentaba `returns` de `/menus` y `/shortcodes` sin la clave `uso` que ambos endpoints devuelven de verdad — corregido, encontrado por el nuevo chequeo `scripts/verify-rest-info-contract.py` (ver abajo).
* Nuevo (equipo, no distribuido al cliente — carpeta `scripts/` excluida del ZIP): dos chequeos mecánicos de código puro, primeros del plugin que no dependen de que un agente los ejecute bien.
  - `scripts/verify-mcp-tools.py`: handshake MCP real (initialize + tools/list + tools/call) contra cada tool de solo lectura sin parámetros requeridos, falla si `structuredContent` no es un objeto — la clase de bug de este mismo changelog.
  - `scripts/verify-rest-info-contract.py`: cruza lo que `GET /info` promete en `returns` para cada endpoint GET (sin parámetros de ruta) contra lo que ese endpoint responde de verdad.

= 1.0.35 =
* Red de seguridad anti scroll-horizontal (`Editor_IA_Renderer::DEFENSIVE_CSS`): `html,body{overflow-x:hidden;max-width:100%}` + `box-sizing:border-box` en `*` ahora se inyecta siempre en el `<head>`, hardcodeado en el plugin — landing modo full, landing modo integrado, componente global en páginas nativas y las 6 Custom Template. Hasta ahora el fix (regla de oro #9 en design.md) dependía por completo de que el agente escribiera ese CSS defensivo en el proyecto; con un modelo económico o apurado podía saltearse, como se repitió en sitios reales (ver skill v4.47/v4.64). Se imprime antes que el CSS del agente, así que sigue pudiéndose sobreescribir puntualmente si un elemento concreto necesita overflow-x controlado.

= 1.0.34 =
* Ajustes > Plantillas propias: simplifica el texto de descripción (ya no lista las 6 plantillas por nombre, las secciones/checkboxes de abajo ya lo dejan claro) y elimina la caja informativa sobre el Componente Global (redundante con el resto de páginas nativas del sitio).

= 1.0.33 =
* AJUSTES_MCP.md: nueva nota junto a la sección de acceso FTP/SFTP/SSH — si el agente necesita abrir wp-admin en un navegador (ej. verificación visual), usar siempre un navegador real o herramienta de automatización de navegador, nunca un cliente HTTP crudo sin cabeceras. Motivo: algunos firewalls (Wordfence) bloquean por IP las peticiones POST con User-Agent y Referer vacíos por ser el patrón típico de un bot — un navegador real siempre manda esas cabeceras y evita el falso positivo. Redactado en tono documentación (no orden), mismo criterio que el resto del archivo.

= 1.0.32 =
* Fix: Custom Code — un snippet PHP con error (ParseError, fatal, excepción) quedaba con el aviso "Snippets con errores de ejecución detectados" en pantalla para siempre, incluso después de corregir el código y que volviera a ejecutar bien. El registro de errores (`store_error()`) solo se borraba manualmente vía "Limpiar avisos", nunca solo. Ahora `execute_global_php()` y `execute_php_shortcode()` llaman a `clear_error()` en cuanto el `eval()` corre sin lanzar excepción, así el aviso desaparece solo cuando el problema ya no existe.

= 1.0.31 =
* Fix: las 6 Custom Template (Entrada, Categoría de entrada, Etiqueta de entrada, Producto, Categoría de producto, Etiqueta de producto) quedaban con el contenido pegado al borde izquierdo/derecho del navegador — el esqueleto PHP de fábrica no traía ningún padding/max-width lateral por defecto, a diferencia de una landing (donde el diseño CSS lo pone el propio agente). Se agrega la clase `.eia-custom-template-container` (`max-width:1200px; margin:0 auto; padding:0 24px`, misma receta que `.container` de `design.md`) al wrapper de cada una de las 6 plantillas, vía el CSS base ya centralizado en `Editor_IA_Custom_Templates::print_head()`. No requiere nada del agente ni de Custom Code — es el default de fábrica del plugin.

= 1.0.30 =
* Custom Template: nuevas plantillas de fábrica para Etiqueta de producto (`product_tag`, WooCommerce, `taxonomy-product_tag.php`) y Etiqueta de entrada (`post_tag`, WordPress core, `tag.php`) — pasan de 4 a 6 plantillas disponibles en Ajustes > Custom Template, mismo criterio incondicional que las 4 ya existentes. Producto/Categoría/Etiqueta de producto se enganchan a `template_include` (prioridad 11, después de WooCommerce); Entrada/Categoría/Etiqueta de entrada usan los filtros dedicados de WP core (`single_template`/`category_template`/`tag_template`, nuevo). Etiqueta de entrada comparte la misma columna de sidebar (`[eia_widget]`) que ya tenían Entrada y Categoría de entrada. `GET /info` (`environment.custom_templates`) y la tool MCP `editor-ia/get-info` ya reportan las 2 plantillas nuevas con sus hooks nativos.

= 1.0.29 =
* Ajustes > Custom Template: sacado el selector "Componente (header/footer/CSS/JS)" por plantilla — las 4 plantillas (Entrada, Categoría de entrada, Producto, Categoría de producto) usan siempre el Componente Global del sitio, sin vínculo propio. Fix de un bug real introducido junto con ese selector (v1.0.22): cuando una plantilla tenía un componente vinculado, el header/footer salía duplicado — una vez desde el vínculo propio de la plantilla (`print_head`/`print_foot`) y otra desde el mecanismo general de Componente Global (`Editor_IA_Renderer::setup_global_component()`, enganchado a `wp_body_open`/`wp_footer` en cualquier página nativa que no sea una landing full-mode, sin excluir estas). Como el editor solo permite un Componente Global por sitio de todas formas, el selector por plantilla no aportaba nada real. Se agrega `Editor_IA_Custom_Templates::will_serve_current_request()` para que `setup_global_component()` no se enganche en páginas que va a servir una Custom Template (que ya inyecta el Componente Global directo en su propio shell). Removido el endpoint `PUT /custom-templates/{key}/component` (ya no aplica) y `Editor_IA_Custom_Templates::get_component()`/`set_component()`; `GET /info` deja de reportar `environment.custom_templates.plantillas.{key}.componente`.

= 1.0.28 =
* Ajustes > Custom Template: el selector "Componente (header/footer/CSS/JS)" de cada plantilla (Entrada, Categoría de entrada, Producto, Categoría de producto) ahora arranca preseleccionado en el Componente Global del sitio (el mismo que ya se usa en páginas nativas vía Condiciones), en vez de "— Ninguno —", cuando esa plantilla todavía no tiene uno elegido explícitamente. Se agrega `Editor_IA_Conditions::get_global_component()`. No cambia el comportamiento en vivo hasta que el admin guarde: sigue pudiendo elegir otro componente o dejarlo explícitamente en "Ninguno" si esa plantilla no debe llevar header/footer.

= 1.0.27 =
* AJUSTES_MCP.md: el paso 0 ahora recomienda explícitamente guardar la conexión MCP como persistente y con alcance solo al proyecto actual (no en la config MCP global del cliente), y agrega .gitignore tanto del archivo de configuración del cliente como del propio AJUSTES_MCP.md — ambos quedan con la contraseña de aplicación en texto plano. No se hardcodea la ruta de config por cliente (`.codex/config.toml`, `.mcp.json`, `.agents/mcp_config.json`, etc.): cada agente ya la conoce para su propio formato, y esa lista crece con el tiempo.

= 1.0.26 =
* Reemplaza el sidebar nativo de WordPress agregado en 1.0.25 para Entrada/Categoría de entrada: se probó en vivo que asignar widgets vía la API REST nativa (wp/v2/widgets) puede perderlos silenciosamente en sitios con varios sidebars registrados (guardados en "Widgets inactivos" en vez del sidebar pedido) — bug de fondo de WordPress al reconciliar `retrieve_widgets()`, reproducido igual contra un sidebar propio de Astra, no algo de Editor IA. Se saca por completo `register_sidebar()`/`dynamic_sidebar()` (ya no aparece nada nuevo en Apariencia > Widgets).
* Nuevo shortcode `[eia_widget type="TIPO" instance='{"campo":"valor"}']`: renderiza cualquier widget nativo o de un plugin (ej. WooCommerce) de forma directa vía la función core `the_widget()`, que no depende de sidebars para nada — usable en cualquier lado (Custom Code, header/footer de un componente, o el contenido de sidebar de una Custom Template).
* Nuevo `PUT /custom-templates/sidebar-content`: setea el contenido (shortcodes/HTML, típicamente uno o más `[eia_widget]`) de la columna de sidebar compartida entre Entrada y Categoría de entrada. Si queda vacío, la columna no se imprime.
* `GET /info` reemplaza `environment.sidebars` por `environment.widgets`: mantiene el catálogo real de tipos de widget del sitio (`widget_types`, vía `wp/v2/widget-types`) y documenta el nuevo flujo por shortcode en vez de la API nativa de asignación (que queda desaconsejada explícitamente).

= 1.0.25 =
* Custom Template de Entrada y Categoría de entrada ahora soportan sidebar: el plugin registra su propio widget area ("Entrada y Categoría de entrada (Editor IA)", Apariencia > Widgets) que funciona igual sin importar el theme activo — no depende de que el theme registre sidebars propios (Astra sí trae los suyos, ej. "Barra lateral de WooCommerce"; el theme Lienzo, en cambio, hoy no registra ninguno). La columna de sidebar solo aparece si el admin le asignó al menos un widget; si está vacía, la plantilla se muestra a una sola columna.
* `GET /info` agrega `environment.sidebars`: lista todos los sidebars registrados en el sitio ahora mismo (id, nombre, si tiene widgets asignados), detectados de forma genérica vía el global nativo de WordPress — sin ningún mapeo hardcodeado por theme. `environment.custom_templates.plantillas.{key}.sidebar` reporta el id del sidebar que usa cada plantilla (hoy solo Entrada/Categoría de entrada).

= 1.0.24 =
* Ajustes > Custom Template: las filas de Producto y Categoría de producto ahora se ocultan por completo cuando WooCommerce no está activo, en vez de mostrarse deshabilitadas con un aviso — el toggle vuelve a aparecer solo con recargar la página una vez que WooCommerce se instala. También se reordenó la lista: Entrada y Categoría de entrada (siempre disponibles) van primero, Producto y Categoría de producto (dependen de WooCommerce) quedan al final.

= 1.0.23 =
* Ajustes: la etiqueta de la key mostrada ahora dice "Site Key MCP Server" en vez de "Key de MCP Server" — ajuste menor de texto.

= 1.0.22 =
* Custom Template ahora se puede vincular a un componente (header.html/footer.html/style.css/script.js) para el look de la plantilla, separado del PHP de Custom Code (que sigue siendo el lugar para la lógica/contenido dinámico enganchado a los hooks nativos). Nuevo endpoint `PUT /custom-templates/{key}/component` (agente, vía API) y selector nuevo en Ajustes > Custom Template (wp-admin). `GET /info` reporta el vínculo en `environment.custom_templates.plantillas.{key}.componente`. `script.js` es un archivo nuevo y opcional para componentes — hasta ahora solo se leían header.html/footer.html/style.css; esta es la única vía que también lee script.js.
* Motivación: hasta ahora la única forma de meter CSS/JS en una Custom Template era un snippet Custom Code type=css/js (texto en base de datos, sin historial de revisiones). Reutilizar el mecanismo de componente le da al agente archivos reales con el mismo sistema de revisiones/rollback que ya usa en landings, en vez de un tercer formato nuevo que aprender.

= 1.0.21 =
* Ajustes > Tracking: se oculta del menú (mientras Google Site Kit cubra GA4 en el sitio) sin desactivar la funcionalidad — la página sigue accesible por URL directa y el guardado de GA4/GTM/Meta Pixel sigue intacto por si se necesita reactivar la opción propia más adelante.

= 1.0.20 =
* Fix: el render de landings (`maybe_render`/`maybe_render_on_page`) pasa de prioridad default (10) a 20 en `template_redirect`. Como ese render termina en `exit()`, si corría antes que otro plugin enganchado al mismo hook a prioridad 10, ese plugin nunca llegaba a ejecutarse. Caso real detectado: Google Site Kit registra su tag de GA4 en `template_redirect` (prioridad 10) y, por el orden alfabético de carga de plugins, nunca le tocaba turno en una landing del Editor IA — el tag sí aparecía en páginas nativas de WordPress, pero no en las landings. Con la nueva prioridad, Site Kit (y cualquier plugin con el mismo patrón) alcanza a registrar su tag antes de que nosotros cortemos la ejecución.

= 1.0.19 =
* Description del plugin (lista de plugins de WordPress) reescrita: "Motor de páginas y skills que tu agente de IA usa para editar y administrar WordPress. Compatible con Claude, Antigravity, Codex y otros." Refleja el alcance actual (skills, no solo landings) y deja lugar a más agentes/plugins sin listar nombres cerrados.

= 1.0.18 =
* Ajustes > Custom Template: texto aclara que quien completa el contenido es el agente de IA ("El agente pone el contenido con Custom Code"), no el usuario a mano; mismo criterio en el aviso amarillo.

= 1.0.17 =
* Ajustes > Custom Template: texto corregido de voseo argentino ("vos ponés", "si activás") a español neutro ("tú pones", "si activas") — criterio de redacción para toda la UI del plugin en adelante.

= 1.0.16 =
* Nombre visible del plugin: "Editor IA" pasa a "Editor IA Buhoflow" en la lista de plugins (Plugin Name) y en el encabezado de Ajustes ("Ajustes — Editor IA Buhoflow"). Slug, namespace REST, capability, CPT, prefijo de shortcodes, constantes EDITOR_IA_* y Text Domain quedan igual — son detalles internos, no el nombre que ve el usuario.

= 1.0.15 =
* Ajustes > Custom Template: texto de la pantalla reescrito, más corto y sin jerga técnica (ganchos/hooks) para un usuario no técnico; el detalle de "hooks nativos" queda solo en el comentario interno de cada archivo de plantilla.
* Orden del menú: "Ajustes" ahora aparece al final (después de Custom Template) en vez de antes.

= 1.0.14 =
* La tool MCP `editor-ia/get-info` (y su descripción en `tools/list`) ahora menciona explícitamente el estado de Custom Template — el dato ya venía completo en la respuesta desde la 1.0.13, faltaba que la descripción corta lo mencionara para que un agente que solo lee `tools/list` sin ejecutar la tool no lo pase por alto.

= 1.0.13 =
* Nueva sección Ajustes > Custom Template: plantillas de fábrica para Producto, Categoría de producto, Entrada y Categoría de entrada, desactivadas por default. Al activar una, reemplaza sin condición lo que WooCommerce/WordPress hubieran usado por HTML propio (mismo criterio "modo full" que las landings, sin CSS/JS del theme activo), conservando la secuencia exacta de hooks nativos de WooCommerce o los filtros dedicados de WordPress core, para que Custom Code (PHP, scope global) pueda engancharse ahí con vocabulario estándar en vez de nombres inventados. No agrega ninguna capacidad nueva de escritura de archivos: las plantillas son código fijo del plugin, y el contenido dinámico sigue pasando por el pipeline ya existente de Custom Code (validación de sintaxis, lista negra de funciones, auto-desactivación ante fatal error). `GET /info` reporta el estado y los hooks disponibles de cada plantilla en `environment.custom_templates`.

= 1.0.12 =
* Nuevo endpoint `GET /shortcodes` (lista `array_keys($shortcode_tags)`, los tags realmente registrados en el sitio ahora mismo) para que el agente pueda verificar, antes de recomendar o insertar cualquier shortcode que no sea uno de los documentados en `GET /info`, si ese plugin/función existe de verdad en este sitio en vez de asumirlo por conocimiento genérico de otros sitios. Motivado por un caso real: un agente recomendó el shortcode de un plugin buscador que nunca estuvo instalado. Documentado en `discover()` (sección de endpoints y advertencia `shortcodes_verificacion`).

= 1.0.11 =
* Fix: el offset de compensación de la admin bar para headers `fixed`/`sticky` (introducido en 1.0.2) nunca se aplicaba en la práctica — el script se imprime en `wp_head`, antes de que exista `<body>`, y capturaba `document.body` como `null` en ese momento; la primera llamada a `sync()` fallaba en silencio (`Cannot read properties of null`) y la clase `eia-at-top` nunca se agregaba. Ahora `sync()` lee `document.body` en cada invocación (con reintento en `DOMContentLoaded` si aún no existe) en vez de capturarlo una sola vez al declarar el script.

= 1.0.10 =
* Custom Code: activar, editar (código o estado activo) o borrar un snippet ahora dispara `Editor_IA_Cache::flush_site()` (misma clase que ya usa `PUT /file` para landings/componentes) cuando el cambio afecta contenido servido activamente. Antes, un snippet `scope: global` podía cambiar sin que un plugin de cache de página (WP Rocket, LiteSpeed, etc.) se enterara — visitantes reales seguían viendo la versión anterior hasta que expirara el TTL.
* `PUT /file` y `PUT/POST /custom-code`: la respuesta ahora incluye un campo informativo `recordatorio_testing` cuando el cambio ya quedó activo en el sitio, recordando verificar con capturas reales (skill `testing`) antes de reportar la tarea como lista.

= 1.0.9 =
* Custom Code: solucionado un error de incompatibilidad en los métodos REST (rest_create y rest_update) que usaban $request->get_json_params() en vez de $request->get_param(). En llamadas sintéticas del servidor MCP (abilities), get_json_params() podía retornar null o WP_Error, ocasionando un TypeError fatal en PHP 8.0+ al intentar evaluar claves de arreglo no existentes. Con get_param() la lectura de parámetros es 100% compatible tanto en llamadas HTTP externas como en invocaciones MCP internas.

= 1.0.8 =
* Ajustes > Accesos para agentes: el checkbox "Activar API de WooCommerce" ahora recuerda su estado entre visitas a la página (antes volvía siempre desmarcado aunque el usuario lo hubiera activado la vez anterior).

= 1.0.7 =
* Nuevo endpoint/tool genérico `PATCH /native/{id}/meta` (ability `editor-ia/set-native-meta`) para escribir custom fields de posts/páginas NATIVAS de WordPress. Delega en el propio wp/v2/{tipo}/{id} vía rest_do_request() en vez de reimplementar permisos o sanitizado — sirve para Yoast SEO, ACF (con "Show in REST API" activo) o cualquier otro plugin que registre sus campos con show_in_rest, sin hardcodear nombres de campos ajenos en el plugin. Reemplaza la instrucción anterior del skill `seo` de armar el PATCH a wp/v2 a mano.
* Detecta y reporta explícitamente (campos `no_guardadas`/`aviso` en la respuesta, o error 400 si son todas) las claves enviadas que WordPress ignora en silencio por no estar registradas para ESE post_type específico (caso real detectado en pruebas: Yoast SEO 27.9 solo registra sus campos para el tipo "post", no para "page" — sin este chequeo la respuesta era 200 con el valor en null, un falso éxito).
* CORS: agregado PATCH a `Access-Control-Allow-Methods` (faltaba desde que se armó la cabecera, sin impacto hasta ahora porque ningún endpoint usaba ese método).

= 1.0.6 =
* Preparación para una eventual publicación en WordPress.org: renombrado el slug/archivo principal del plugin de `editor-ia` a `editor-ia-facilwp` — carpeta (`editor-ia/` → `editor-ia-facilwp/`), archivo principal (`editor-ia.php` → `editor-ia-facilwp.php`), header `Text Domain` y las 74 llamadas de traducción (`__`, `_e`, `esc_html_e`, etc.) actualizadas para coincidir con el nuevo slug. Necesario porque WordPress.org exige que el Text Domain coincida con el slug final para que el sistema de traducciones cargue los `.mo` automáticamente. Sin cambios en el namespace REST (`editor-ia/v1`), capability, CPT, prefijo de shortcodes (`eia_`) ni constantes `EDITOR_IA_*` — son detalles internos que no afectan a WordPress.org y que hubieran arrastrado toda la documentación/skills sin necesidad. El plugin todavía no se envía a publicación en WordPress.org; este cambio es solo preparación.

= 1.0.5 =
* Custom Code: si un snippet `type:php` falla la validación de sintaxis y el código contiene patrones exclusivos de JS (`document.`, `.setAttribute(`, `addEventListener(`, `querySelector(`, etc.), el error ahora incluye una pista de que el tipo correcto probablemente sea `type:js` — el modo PHP `global` corre en `init`, antes de que exista el HTML de la página, así que no puede modificar DOM ya renderizado.
* Ajustes > Accesos para agentes: simplificado el label del checkbox de WooCommerce, quitando el detalle de permisos entre paréntesis que quedaba redundante.

= 1.0.4 =
* GET /info ahora reporta `environment.yoast_seo` (activo, versión, y si sus campos meta están registrados como editables vía REST) — informativo, mismo patrón que Astra/WooCommerce/Elementor. No agrega ninguna tool nueva: la edición de título/meta description de contenido nativo de WordPress con Yoast activo ya es posible con la API REST estándar (PATCH /wp/v2/posts|pages con meta._yoast_wpseo_title / meta._yoast_wpseo_metadesc), documentado en el skill `seo`.

= 1.0.3 =
* GET /info ahora reporta `otros_servidores_mcp`: detección genérica (sin lista de plugins hardcodeada) de servidores MCP de terceros activos en el sitio — servidores dedicados con ruta REST propia (cualquier plugin que registre la suya vía wordpress/mcp-adapter, ej. Astra) y el gateway compartido de WordPress para plugins que solo registran WP Abilities sin servidor propio (ej. WooCommerce, Yoast SEO), listando las abilities detectadas de cada uno.

= 1.0.2 =
* Fix: el offset de compensación de la admin bar para headers fijados/sticky ahora solo se aplica mientras la página está sin scrollear (antes era permanente vía CSS `!important`, y hacía que el header terminara flotando a mitad de página en vez de quedar pegado al viewport al hacer scroll). Afecta solo a usuarios logueados con la admin bar visible.

= 1.0.1 =
* Ajustes > Accesos para agentes: reescrito el label del checkbox de WooCommerce (de pregunta a frase de acción directa), más claro sobre qué habilita.

= 1.0.0 =
* Primer lanzamiento público. El desarrollo interno previo (alpha, no distribuido) queda archivado como referencia del equipo en backups/v3.1.0-pre-1.0.0-reset/CHANGELOG.txt.
* Servidor MCP nativo (Abilities API de WordPress) para que un agente de IA administre el sitio vía tools estructuradas, con fallback completo por API REST clásica para entornos que no pueden hacer POST JSON-RPC.
* Motor de páginas/landings: modo full (HTML/CSS/JS propio, cero interferencia del theme) y modo integrado (usa get_header()/get_footer() del theme activo).
* Sistema de componentes reutilizables (header.html, footer.html, style.css) entre landings, y Componente Global para inyectar header/footer en páginas nativas de WordPress (blog, archivo, single, page) sin afectar las landings del plugin.
* Compatibilidad de theme para el Componente Global: remoción directa de hooks nativos (Astra) en vez de ocultar con CSS, con fallback CSS para temas sin adaptador propio.
* Editor de textos desde el admin de WordPress (meta box), sin tocar código — preserva HTML/formato inline.
* Sistema de revisiones automáticas por archivo (hasta 5 por archivo) con rollback vía API.
* SEO por proyecto (título, meta descripción) con desactivación automática de la salida de Yoast SEO / Rank Math en esas páginas para evitar duplicados.
* Biblioteca de medios de WordPress integrada: subida y listado con todos los tamaños generados, srcset/sizes automático y optimización de imágenes (lazy loading, fetchpriority en la candidata a LCP) sin que el agente tenga que escribirlo a mano.
* Compatibilidad con plugins de cache de página (WP Rocket, WP Super Cache, W3 Total Cache, LiteSpeed Cache, etc.): invalidación automática al editar vía API o admin.
* Custom Code: snippets de PHP, CSS y JS con modos de ejecución shortcode o global, con validación de sintaxis y bloqueo de funciones peligrosas para el caso PHP.
* Integración WooCommerce: shortcode [eia_cart] (carrito nativo con drawer lateral, sin dependencia de theme) y acceso a la API REST de WooCommerce para agentes.
* Sistema de condiciones granular para asignación de componentes.
* Menús dinámicos de WordPress vía shortcode y endpoint dedicado.
* Instrucciones del agente servidas en vivo desde un servicio central (nunca se descargan a disco), organizadas en núcleo + skills especializados por área, con verificación de instalación por dominio.
* Detección informativa de Elementor y Astra (sin tools ni flujos asociados).
