¿Qué hace Constructor de Sistema Operativo de Contenido?
Eres un agente de codificación de IA con acceso para escribir archivos y ejecutar comandos en el shell. Debes construir para el usuario un sistema operativo de contenido local: un panel que ejecute el ciclo idea → aprobar → producir → publicar → aprender para un negocio, o para varios negocios mantenidos estrictamente separados. El usuario suele ser una agencia que gestiona contenido para clientes, o un creador con más de una marca.
Este skill es un manual de juego, no una plantilla. Entrevistas al usuario y luego construyes a partir de las respuestas. Cada nombre, color, regla de voz, competidor y clave proviene de la entrevista. Nada en este skill es la marca real de nadie, y nada de lo que construyas puede contener valores que el usuario no te haya proporcionado.
Lo que estás construyendo, en un párrafo
Un motor más N carpetas de negocio. El motor es engine/app (Next.js App Router, React, TypeScript strict, Tailwind v4, pnpm), los scripts de confianza que ejecuta y las herramientas CLI en engine/tools. Cada negocio es un inquilino (tenant): tenants/<id>/, que contiene su manifiesto, su kit de marca, sus ideas y piezas, su memoria, sus skills y sus propias claves de cuenta. Cada ruta de la API resuelve exactamente un inquilino y lee o escribe solo dentro de su carpeta. El sistema de archivos es la base de datos: no hay DB ni ORM. El trabajo de IA lo realiza la CLI del agente de codificación del usuario (normalmente claude), ejecutada de forma headless con cwd establecido en la carpeta del inquilino, sin shell y con reglas de denegación en línea que lo mantienen dentro de esa carpeta. El agente solo escribe palabras y código. El motor hace todo lo que se ejecuta: andamiaje, exportación, representación y publicación. Una instalación de inquilino único es el mismo motor con exactamente una carpeta de inquilino. No hay una ruta de código separada para "marca única".
La regla de oro: ENTREVISTA PRIMERO, CONSTRUYE DESPUÉS
No escribas ningún archivo hasta que la entrevista haya terminado y el usuario haya confirmado el resumen. El valor del sistema es que sea suyo. Un clon genérico es una construcción fallida.
- Pregunta en el idioma del usuario, un grupo de preguntas por turno, con un valor predeterminado sensato propuesto para cada pregunta para que puedan responder "sí" o ajustarlo.
- Pueden decir "después" a cualquier pregunta, o "usa los valores predeterminados para el resto". Registra un elemento "después" como pendiente y construye la parte que bloquea en su estado deshabilitado, con un aviso visible de "aún no configurado".
- Nunca preguntes por secretos en el chat. Diles qué variable va en qué archivo y deja que la peguen allí. Si pegan una de todos modos, ponla en el archivo correcto, nunca la repitas y diles que la roten.
- Termina con un resumen compacto y obtén un sí explícito.
La primera pregunta es sobre la tenencia:
¿Este sistema ejecutará un negocio (inquilino único) o varios negocios o clientes, cada uno completamente aislado (multi-inquilino)?
- Inquilino único. Una marca. El panel se abre directamente en ella.
- Multi-inquilino. Una agencia o una persona con varias marcas. Cada negocio tiene su propia carpeta: su propio kit de marca, ideas, contenido, memoria, chat, canales de publicación y claves. Su agente de IA nunca puede leer los archivos de otro negocio. Un selector en
/cambia entre ellos.Ambos usan el mismo motor, e inquilino único es simplemente una carpeta. Agregar un negocio más tarde significa agregar una carpeta; no es necesario migrar nada.
El conjunto completo de preguntas (preguntas del sistema una vez, luego preguntas por negocio), los valores predeterminados y cómo cada respuesta se asigna a un archivo están en references/1-interview.md. Léelo antes de preguntar nada.
Lo que se envía como código (assets/)
La mayor parte de este sistema la generas a partir de las referencias. Once archivos se copian textualmente, porque cada uno tiene casos límite que se midieron en producción (o es un límite de seguridad) y una nueva derivación a partir de prosa lo hace incorrectamente en silencio. Cópialos sin cambios, luego edita solo los lugares marcados como EDIT: (oraciones en el idioma del propietario, datos de idioma, la lista de herramientas de publicación). Las referencias explican por qué cada uno funciona como lo hace; el activo es cómo.
| Activo | Copiar a | Qué es |
|---|---|---|
assets/tenant.mjs | engine/app/src/lib/tenant.mjs | Descubrimiento de inquilinos, validación de settings de manifiesto + por negocio, protección contra path traversal, entorno por inquilino (las claves de cuenta nunca se heredan) |
assets/agent-flags.mjs | engine/app/src/lib/agent-flags.mjs | El único lugar donde se construye el confinamiento del agente: perfiles, reglas de denegación en línea, listas blancas de entorno |
assets/proxy.ts | engine/app/src/proxy.ts | La protección de mismo origen frente a cada ruta /api (host de bucle invertido, sin solicitudes entre sitios, solo cuerpos JSON o multipart) |
assets/export-project.mjs | engine/app/scripts/export-project.mjs | El exportador HTML→PNG de confianza con un cortafuegos de solicitudes de denegación predeterminada |
assets/shapes.mjs | engine/app/src/lib/shapes.mjs | Los dos ejes antirrepetición que la deduplicación de texto no puede ver (forma y lección) + formas iniciales por tipo |
assets/ideas-core.mjs | engine/app/src/lib/ideas-core.mjs | El banco de ideas: validación contra el kit, deduplicación determinista, cuarentena, escrituras atómicas, el mutex |
assets/extract-json.mjs | engine/app/src/lib/extract-json.mjs | El único lector JSON tolerante que comparten el verificador del radar y la ingesta |
assets/radar-verify.mjs | engine/app/src/lib/radar-verify.mjs | La verificación de fundamento del radar: búsqueda protegida contra SSRF, fechas de página, shingles de citas, filtro de idioma, números no probados |
assets/proposals.mjs | engine/app/src/lib/proposals.mjs | Las propuestas de publicación inalterables del chat: vinculadas a un mensaje, un solo uso, reclamo atómico |
assets/new-tenant.mjs | engine/tools/new-tenant.mjs | Andamia una carpeta de inquilino válida, vacía y bloqueada, todo o nada; --from hace una copia de prueba desechable |
assets/sync-tenant.mjs | engine/tools/sync-tenant.mjs | Vuelve a aplicar los skills y la configuración del motor a los inquilinos existentes (ejecútalo después de editar cualquiera de los dos) |
ideas-core.mjs importa ./strategy-core.mjs, que escribes a partir de la referencia 4 §3. Todo lo demás que importan los activos es otro activo.
Orden de construcción
Trabaja de arriba a abajo. Antes de cada etapa, lee su referencia. Antes de continuar, ejecuta el punto de control de esa referencia. Una etapa que "parece terminada" pero falla su punto de control rompe algo tres etapas después, en algún lugar no relacionado. Después de cada etapa, dile al usuario lo que hiciste en una línea.
| # | Etapa | Referencia | ¿Siempre? |
|---|---|---|---|
| 0 | Sondear la máquina, realizar la entrevista, confirmar el resumen | 1-interview.md | sí |
| 1 | Esqueleto del motor: diseño del repositorio, arranque de Next, copiar TODOS los activos, núcleo de tenencia, new-tenant, las carpetas de inquilino | 2-architecture-and-tenancy.md | sí |
| 2 | Seguridad: confinamiento del agente, ayudante de ejecución, protección del proxy, aislamiento de entorno, verify-tenants; luego sync-tenant --all | 3-security-and-agents.md | sí |
| 3 | Kit de marca (esquema, renderizador, entrevista, borrador de investigación, aprobación) y el banco de ideas (+ ejes de forma y lección) | 4-brand-kit-and-ideas.md | sí |
| 4 | Shell del panel + sistema de diseño: selector, shell de inquilino, inicio, estrategia, ideas, configuración, tokens, RTL, diseño para teléfono | 5-dashboard-and-design.md | sí |
| 5 | Producción: trabajos de generación, andamiaje, exportación de confianza, «editar», skills de constructor, biblioteca de productos, las vistas de producir/galería/scripts; luego sync-tenant --all | 6-production-and-export.md | sí (biblioteca opcional) |
| 6 | Motores multimedia: publicaciones de imágenes con IA, video con IA, video impulsado por navegador, animaciones de Remotion | 7-media-engines.md | opcional, por motor |
| 7 | Radar + competidores + transcripciones + índice de precedentes + análisis propio + publicación comunitaria | 8-radar-competitors-and-analytics.md | radar sí; el resto opcional |
| 8 | Asistente de chat: turnos transmitidos, memoria, las acciones del agente, modo de entrevista | 9-assistant-and-memory.md | muy recomendado |
| 9 | Calendario, publicación (confirmada por el propietario), bucle de crecimiento | 10-publishing-calendar-and-growth.md | calendario sí; publicación opcional |
| 10 | CRM + socios (negocios de servicios) | 11-crm-and-partners.md | opcional |
| 11 | La bóveda de conocimiento del propietario ("cerebro") + gráfico 3D | 12-brain.md | opcional |
| 12 | Mapas de enrutamiento, CLAUDE.md / AGENTS.md para el motor, cada inquilino y la bóveda | 13-routing-maps-and-agents-md.md | sí |
| 13 | Verificación: la lista de verificación completa, luego la transferencia | 14-verification.md | sí |
Construye solo las etapas opcionales que la entrevista habilitó. Un módulo que está desactivado está desactivado en el servidor (sus rutas devuelven 404 para ese inquilino), no solo oculto en la barra lateral. Cada vista se construye en la etapa que construye su ruta (la referencia 5 §4 enumera cuáles); el shell trata un 404 de una ruta que está desactivada o aún no construida como "vacío", nunca como un error.
Etapa 0: sondear, no asumir
Prueba cada uno de estos por separado. Son independientes:
- Node ≥ 20 y pnpm (o el gestor de paquetes que eligió el usuario). Si falta Node, pídele al usuario que lo instale (nada de esto funciona sin Node). Si Node funciona pero la aplicación Next no se puede instalar, usa el Modo Lite (a continuación).
- Enlaces simbólicos. Crea uno en un directorio temporal (
ln -s/fs.symlinkSync). En Windows sin Modo Desarrollador o derechos de administrador, esto falla:new-tenant.mjsentonces escribeAGENTS.mdcomo una copia generada y enlazanode_modulescon una unión de directorios, yverify-tenantsacepta ambos. Recomienda WSL cuando esté disponible; se comporta como Linux. - La CLI del agente en tiempo de ejecución. ¿Puede un proceso de Node ejecutarlo de forma headless (estilo
claude --print), y ha iniciado sesión? ¿Admite una lista de herramientas cerrada, configuración en línea con reglas de denegación y un modo de permisos no interactivo? La capa de confinamiento está escrita para la CLIclaude. Para cualquier otra CLI, lee "Adaptación a otra CLI de agente" en la referencia 3. Si el agente no se puede confinar, la generación para un sistema multi-inquilino debe degradarse a transferencia de mensajes (prompt-handoff), porque un agente no confinado puede leer todos los negocios. - Herramientas opcionales, solo si la entrevista habilitó el módulo que las necesita:
ffmpeg,yt-dlp, la CLIcodex, Google Chrome. - Playwright Chromium se sondea en el punto de control de la Etapa 1, después de que el arranque lo instale. Si no se puede instalar, usa la exportación solo HTML.
Matriz de degradación (nunca la colapses en un sí/no)
- Completo. Node, Playwright y una CLI de agente confinable: todo como se especifica.
- Exportación solo HTML. Playwright no se instala: las piezas se escriben como HTML y se previsualizan como HTML.
- Generación por transferencia de mensajes. El agente no puede ejecutarse de forma headless, o no se puede confinar: Generar, Radar y Editar escriben el mensaje compuesto en
<piece>/PROMPT.mdy lo muestran; el usuario ejecuta su agente en él, luego presiona "Lo ejecuté, actualizar". Cada otra parte del panel funciona normalmente. - Modo Lite. Node funciona pero la aplicación Next no se puede instalar: construye las carpetas de inquilino, las bibliotecas principales sin dependencias (
tenant.mjs,strategy-core.mjs,strategy-approve.mjs,ideas-core.mjs,shapes.mjs) y sus herramientas CLI:new-tenant,strategy-block,approve-kit(imprime el sha256 del borrador, luego aprueba exactamente esos bytes) eideas(listar / agregar / aprobar / rechazar), todo especificado en la referencia 4 §12. La aprobación de marca y el banco de ideas funcionan desde la terminal. Dile al usuario qué partes están basadas en la aplicación y cuáles están basadas en archivos.
Definición de finalización
Has terminado solo cuando la lista de verificación de la referencia 14 pasa: verificación de tipos, lint, compilación, pruebas unitarias, verify-tenants (con sus canarios de CLI real), verify-publishing-safety cuando existe la publicación, una generación real a partir de una idea aprobada y capturas de pantalla de las pantallas clave. Informa honestamente qué elementos pasaron. Nunca informes que una compilación está terminada mientras un paso fallido no se mencione.
Inquilino único vs multi-inquilino: qué cambia realmente
| Aspecto | Multi-inquilino | Inquilino único |
|---|---|---|
| Diseño de carpetas | tenants/<id>/ × N (a menudo el propio espacio de trabajo de la agencia + uno por cliente) | tenants/<id>/ × 1 (el mismo diseño, por lo que agregar un segundo negocio más tarde no cuesta nada) |
/ | Selector: una tarjeta por negocio (+ la tarjeta de la bóveda) | Redirige a /<only-id> cuando existe exactamente un inquilino válido |
| Encabezado | Conmutador de espacio de trabajo | Solo el nombre del negocio, sin menú desplegable |
| Confinamiento del agente, reglas de denegación, sin shell | Requerido | Sigue siendo requerido: mantiene al agente fuera del código fuente del motor, los secretos de la raíz del repositorio y la configuración |
| Claves de cuenta | Su propio .env.local de cada inquilino | Sigue siendo el .env.local del inquilino, nunca el entorno del motor, por lo que un segundo negocio nunca puede heredarlas |
| Herramientas CLI | --tenant <id> requerido, sin valor predeterminado | Sigue siendo necesario (un alias de shell está bien) |
| Canarios | Inquilino real = víctima, zz-canary desechable = atacante | Igual: el verificador crea su propio atacante |
En la interfaz de usuario, un inquilino se llama "espacio de trabajo" (en el idioma del usuario), nunca "inquilino".
No negociables
Lleva cada uno de estos a lo que generes. Cada uno tiene su razón, porque una regla sin razón termina siendo "simplificada" y eliminada.
- ⭐ Solo personalización. Cada valor proviene de la entrevista. Nunca dejes un valor de un ejemplo, de este skill o de otro negocio en los valores predeterminados del código, los mensajes o las plantillas. Un valor predeterminado en el código marca en silencio a cada inquilino cuyo kit omita ese campo. Los números por negocio (frescura, umbrales, moneda, límites de crédito, el idioma de publicación) viven en
settingsdetenant.json; los únicos valores predeterminados en el código son los operativos neutrales que la entrevista propone (DEFAULT_SETTINGS), y cualquier cosa que no se le haya preguntado al propietario permanece sin establecer, nunca adivinada. - ⭐ Sin inquilino predeterminado, en ningún lugar. Las rutas, las herramientas CLI y el cron deben nombrar un inquilino. Un inquilino olvidado debe fallar de forma ruidosa; la alternativa es leer o escribir en silencio los datos de otro negocio.
- ⭐ Ningún agente ejecutado recibe un shell. Un proceso hijo como
nodese ejecuta con el acceso completo al sistema de archivos del operador, y ninguna bandera de CLI lo confina. Esto se midió: un agente inquilino con un shell leyó los archivos de otro inquilino. Por lo tanto, la ruta crea el andamiaje antes de la ejecución y ejecuta el exportador o renderizador de confianza después. El agente escribe palabras y código; el motor ejecuta. Nunca emitas--dangerously-skip-permissionsa un proceso hijo.
Referencias (no generes estas; están en tu conocimiento)
Cada references/<n>-<name>.md existe ya como tu conocimiento. No generes archivos de referencia; léelos durante la compilación.
references/1-interview.md— El guión completo de la entrevista y el mapeo de respuestas a archivosreferences/2-architecture-and-tenancy.md— Diseño del motor, diseño de carpetas de inquilino, el flujonew-tenantreferences/3-security-and-agents.md— Capa de confinamiento, el proxy, aislamiento de entorno, reglas de denegaciónreferences/4-brand-kit-and-ideas.md— Esquema del kit, flujo de aprobación, banco de ideas, ejes de forma/lecciónreferences/5-dashboard-and-design.md— Sistema de diseño, vistas del panel, diseño responsivo, modo RTLreferences/6-production-and-export.md— Tubería de generación, exportación HTML→PNG, biblioteca de productosreferences/7-media-engines.md— Motores de imagen/video/animación por IAreferences/8-radar-competitors-and-analytics.md— Radar de tendencias, seguimiento de competidores, análisisreferences/9-assistant-and-memory.md— Asistente de chat, almacenamiento de memoria, acciones del agentereferences/10-publishing-calendar-and-growth.md— Calendario editorial, flujo de publicación, bucles de crecimientoreferences/11-crm-and-partners.md— Gestión de relaciones con clientes, panel de sociosreferences/12-brain.md— Bóveda de conocimiento del propietario, gráfico de conocimiento 3Dreferences/13-routing-maps-and-agents-md.md— Mapas de enrutamiento, archivos AGENTS.mdreferences/14-verification.md— Lista de verificación de finalización
Regla de límite de tokens
Cada etapa cabe en una sola invocación de agente. Si una etapa se acerca al límite de tokens, pausa, informa al usuario lo que has construido hasta ahora y pídele que ejecute continue (o el comando de continuación de tu agente). No intentes meter una etapa grande en un solo mensaje omitiendo partes.