C4
C4 responde "¿qué es este sistema, de qué está hecho y quién llama a quién"
en tres niveles de zoom. La superficie es el motor visualize: un lienzo rataflow,
una sección descrita por nivel, cajas containers para la propiedad. Lee
agents/.agents/skills/visualize/SKILL.md para el propio renderizador — esta
habilidad solo cubre lo que C4 añade.
C4 añade tres cosas que visualize no hace:
- Una escalera de niveles. L0 contexto, luego L1/L1b contenedores, luego L2/L2b componentes. Cada nivel existe para motivar el siguiente, y el nivel en el que se encuentra un lector es visible desde la caja, no desde una leyenda.
- Recopilación de hechos. C4 debe ser completo acerca de quién llama a qué y por qué. Los exploradores leen el código base y producen un inventario de elementos y relaciones respaldado por evidencia antes de que exista cualquier especificación.
- Contención como afirmación. Una caja contenedora contiene las partes del propio componente y nada más. Esa es una afirmación de propiedad, por lo que necesita fuentes, y debe sobrevivir a que un lector verifique la caja contra el código.
No inventes un elemento, una relación o un límite. Si los exploradores no pueden citarlo, no se dibuja.
Enrutamiento
| Pregunta | Uso |
|---|---|
| Niveles C4 de un componente en un código base real | esta habilidad |
| Un gráfico de relaciones a partir de hechos que ya tienes | visualize |
| Diagrama dentro de la respuesta del chat | herramienta mermaid |
| ANSI / PNG estático | habilidad mermaid |
| Página o presentación de prosa de arquitectura | habilidad artifact |
/c4 <componente> o "dame una vista C4 de X" es la invocación. La habilidad
funciona en un repositorio que nunca ha visto: los exploradores son la única forma
en que aprende algo, por lo que nada aquí depende de conocimiento previo del código.
Paso 0 — Fijar el componente
Indica, antes de que cualquier explorador se ejecute:
componente: administrador de máquinas
raíz del repositorio: /Usuarios/aviral/modal
ancla: administrador_maquinas/ (un paquete, un desplegable)
- Componente es una cosa que un lector puede señalar en el código: un servicio, un paquete, una unidad desplegable. Si la solicitud nombra un subsistema que abarca varios desplegables, elige el desplegable y di qué vecinos atrae como externos.
- Raíz del repositorio es donde los exploradores comienzan. Confirma que el checkout existe; no asumas una ruta.
- Ancla es la pieza de evidencia más fuerte de que el componente
es una sola cosa (manifiesto de paquete, Helm chart, módulo de Terraform, servicio proto,
main.go). Si no puedes nombrar una, el componente probablemente son dos componentes — pregunta al humano en lugar de adivinar.
Haz como máximo una pregunta aclaratoria (el límite del componente es la única que vale la pena preguntar). De lo contrario, decide y registra.
Paso 1 — Lanzar los exploradores
Cuatro indicaciones viven en prompts/; cada una es una tarea completa de subagente. Lánzalas
como llamadas subagent con agent: "explorador" (reconocimiento de solo lectura — los exploradores
no deben editar el repositorio), las cuatro en un solo turno para que se ejecuten en
paralelo, cwd: la raíz del repositorio resuelta en el paso 0, y el nombre del componente
sustituido por <componente>:
| Explorador | Indicación | Devuelve |
|---|---|---|
| Alcance | prompts/alcance.md | inventario de elementos: id, rol de una línea, puntos de entrada, desplegables, almacenes, servicios externos, actores, rutas de archivo |
| Relaciones | prompts/relaciones.md | filas desde → hacia: verbo + transporte, cada una con archivo:línea |
| Límite | prompts/limite.md | miembros vs. externos + el límite de módulo/despliegue que justifica cada membresía |
| Niveles | prompts/niveles.md | asignación de nivel por elemento, y qué niveles deben dividirse en L1/L1b (L2/L2b) |
Cada explorador devuelve evidencia con referencias archivo:línea. Una fila sin una
es un rumor; descártala o vuelve a preguntar a ese explorador por una fuente.
Lanza los exploradores desde la raíz del repositorio — ejecuta la sesión allí (o haz que
cwd: sea el mismo directorio donde ya está la sesión). Un explorador cuyo cwd
difiere del de la sesión que lo genera puede morir antes de que su proceso comience,
y el fallo se lee como "no apareció ningún proceso pi en su panel".
No consultes a los subagentes. Los resultados llegan por sí solos; continúa cuando los cuatro hayan regresado. Si uno falla, di cuál, y vuelve a intentarlo o registra la brecha en el registro de generación — nunca llenes el vacío desde la memoria.
Paso 2 — Conciliar en un único registro
Fusiona los cuatro resultados en tres tablas en el registro de generación. Esta es la base de hechos completa; la especificación no puede contener nada que no esté aquí.
elementos: id | etiqueta | rol | clase (actor|externo|miembro|almacen) | evidencia
relaciones: id | desde → hasta | verbo + transporte | nivel | evidencia
limite: id | dentro/fuera | límite justificante | evidencia
- Conflictos se resuelven citando la fuente más fuerte (un manifiesto o un chart de despliegue supera un comentario; un sitio de llamada supera una cadena de documentación), y la afirmación perdedora se registra, no se elimina.
- Conflictos no resueltos y relaciones sin fuente sobreviviente se registran como preguntas abiertas. El silencio es un defecto; una duda visible no lo es.
- Mantén un id por elemento y reutilízalo a través de los niveles, para que un lector
que rastrea
q → regvea las mismas dos cajas en L1 y L2.
Paso 3 — Qué dibujar (priorización)
Una vista C4 es un juicio sobre la importancia, no un volcado del gráfico de llamadas. El registro contiene cada relación que un explorador encontró; el diagrama contiene las que un lector necesita, y dice en voz alta lo que omitió.
Una relación se gana un lugar cuando cumple al menos uno de estos criterios:
| id | prueba | ejemplo |
|---|---|---|
| I1 | cruza el límite del componente (miembro ↔ externo, externo ↔ externo) | webapi → API de Latitud, maquinas → sshx.io |
| I2 | es una solicitud primaria, ruta de control o datos que la fuente distingue (aprovisionar, latido, auditoría, reconciliar, arrancar) | plano de control → gRPC privado, cola River → trabajadores |
| I3 | lleva un protocolo o calificador que el lector necesita: verbo RPC, transporte, puerto, bucket, intervalo, tiempo de espera | registrar + latido cada 1 min, sincronización gcore cada 1 min |
| I4 | explica un almacén de datos o un actor que el lector no puede inferir de las cajas | almacén → Postgres, ops + mmctl → webapi |
| I5 | es una rama de una ruta redundante o paralela que debe permanecer contable | maquinas → arranque y arranque → maquinas; dos extracciones independientes |
Clases de eliminación — una relación abandona el diagrama solo como uno de estos:
| id | clase | qué es |
|---|---|---|
| C1 | detalle interno | completamente dentro de un contenedor, no añade información de límite, protocolo o actor (trabajador → almacén fila por consulta cuando los escritores del almacén ya están dibujados) |
| C2 | sitio de llamada duplicado | el mismo salto que una relación dibujada, difiriendo solo en el tipo de trabajo o argumento, que la etiqueta dibujada ya lleva |
| C3 | auxiliar | un elemento cuyo único trabajo es volver a entrar en el mismo contenedor (un envoltorio de cliente entre dos cajas dibujadas) |
| C4 | rama redundante | una rama paralela adicional de una ruta cuya contabilidad el lector no necesita (un segundo artefacto del mismo bucket, mismo transporte) |
Reglas que mantienen el juicio honesto:
- Una flecha puede llevar varios sitios de llamada cuando la etiqueta lleva sus
verbos (
crear / terminar / reparar). Eso es un pliegue C2, no una eliminación. - El cruce de límites gana un empate (I1 antes que I3 antes que I2). Un diagrama que elimina un salto externo para hacer espacio para uno interno ha invertido sus propias prioridades.
- En caso de duda, dibújalo, y deja que la descripción del nivel diga por qué está
allí. La duda no es una razón para eliminar;
C1–C4sí lo son. - Nunca elimines en silencio. Cada fila del registro termina como una de: dibujada,
plegada en <relación dibujada>(con el pliegue justificado como C2), oomitida — C1|C2|C3|C4con una línea de por qué. El mapa de cobertura (Paso 7) indica los cuatro recuentos: dibujadas, plegadas, omitidas por clase, no contabilizadas. - La reducción de alcance es algo diferente y necesita las palabras del solicitante.
"Solo la vista del plano de control" o "20 relaciones como máximo" es una solicitud de alcance: regístrala
como la base (
base: alcance del solicitante, N relaciones) junto con el registro contado. La priorización es el valor predeterminado; un subconjunto es una decisión que el solicitante toma, no una que el generador infiera.
Paso 4 — La escalera de niveles
La forma objetivo son cinco secciones, de arriba a abajo:
L0 · Contexto del sistema un nodo para el componente + sus vecinos
L1 · El componente el componente abierto una vez, contenedor sobre sus partes
L1b · <segundo lado> la misma profundidad, el otro lado del sistema
L2 · Dentro — <rebanada A> relaciones entre miembros, contenedor sobre ellos
L2b · Dentro — <rebanada B> la misma profundidad, la otra rebanada
Esa es la escalera: un lienzo de cinco secciones es el entregable. Más secciones es un defecto a menos que se cumpla la disciplina de división a continuación, con números.
Dibuja cada nivel solo después de que exista el anterior, y dale a cada uno su descripción antes de continuar.
| Nivel | Dibuja | Comportamiento de la caja |
|---|---|---|
| L0 contexto del sistema | el componente como UN nodo simple, más cada actor y sistema externo a su alrededor, más las flechas gruesas entre ellos | sin contenedor, sin focus, sin borde doble — el punto es el mundo circundante, por lo que el componente se ve como cualquier otra caja |
| L1 contenedores | el componente abierto un nivel: sus propias unidades desplegables/tiempo de ejecución dentro de un contenedor; los externos de L0 permanecen fuera | caja contenedora sobre los miembros |
| L1b vista lateral | la segunda rebanada opcional cuando un L1 genuinamente no puede contener el flujo (el extremo de la flota, el plano de datos, la ruta por lotes) — medida, nunca un nuevo tema | contenedor, mismas reglas |
| L2 componentes | las relaciones dentro de un contenedor — los miembros de L1, ahora llamándose entre sí | caja contenedora a su alrededor |
| L2b | segunda rebanada opcional de la misma profundidad cuando un L2 no puede enrutar sus relaciones, o dos historias necesitan rangos separados | contenedor, mismas reglas |
Reglas de nivel que no son negociables:
- L0 es el componente como UN nodo simple. Una caja para todo el
componente, su borde normal, más los actores y sistemas externos a su alrededor.
No sus partes, no sus oyentes, no sus tablas — esos son el siguiente
nivel. Si L0 tiene más de un nodo que pertenece dentro del componente,
no es una vista de contexto. La contención en L0 reclamaría internos que el lector
aún no ha visto, y
focusapuntaría a un nivel que aún no existe. - L1/L1b abren la caja de L0. Cada miembro se sienta dentro del contenedor; cada elemento que era un externo en L0 se sienta fuera de él. Un miembro que no puede dibujarse fuera del cuadro delimitador de la caja obtiene su propia entrada de contenedor (ver Contigüidad) — nunca una forzada.
- L2/L2b permanecen dentro de una caja. Ambos extremos de cada relación L2 son miembros del contenedor. Si una relación sale de la caja, pertenece a L1/L1b.
- Un nivel se describe a sí mismo. El título es corto (
L0 · Contexto del sistema); la descripción indica qué está dentro de la caja, qué está fuera de ella, y cómo se relaciona con su nivel vecino. Apunta a 2–3 líneas ajustadas. - El movimiento no es una propiedad de C4. Los niveles 0–1b son estáticos (
puntos: 0). Un nivel interno cuyas relaciones son flujos en vivo puede llevar exactamente un punto por ruta (flujo: verdadero, puntos: 1); registra la elección. Nunca animes una flecha externa para decorar la escalera.
Disciplina de división — un nivel es una PROFUNDIDAD, no un tema
Un nivel C4 responde una pregunta a un nivel de zoom. Dos niveles de la misma profundidad existen solo porque una sección no podía contener el contenido; un nuevo tema no es una razón para agregar una sección.
- Nunca agregues L1c, L1d, L1e o un quinto lado. La escalera tiene tres profundidades (contexto, contenedores, componentes) y como máximo dos rebanadas en cada profundidad debajo de la primera. Un lienzo que crece una rebanada por subsistema o por mención es una lista de temas que lleva títulos de nivel.
- Una segunda rebanada debe nombrar su medición: las rutas que
--checkrechaza, el corredor compartido que informa, o los rangos que chocan (dos extremos externos sin ningún externo en común). "Se sentía abarrotado" no es una. - Las rebanadas de la misma profundidad comparten la caja, las etiquetas y los ids. L1 y L1b dibujan el mismo componente con los mismos ids de miembro; L2 y L2b dibujan los mismos miembros. Solo el conjunto de bordes y los rangos difieren, y cada descripción dice qué rebanada es.
- Una rebanada se nombra
b(l1b,l2b); nunca inventes una profundidad. - La profundidad más allá de L2 no se dibuja. Si los internos del componente aún se descomponen, dilo en el registro y para: las clases de código y las funciones no son un nivel C4 que un lector haya solicitado. La escalera termina donde termina la solicitud.
- Todo lo que el registro contiene y la escalera no dibuja es una decisión de alcance, escrita (Paso 6), no una eliminación silenciosa y no una nueva sección.
Paso 5 — Mecánica de la especificación
Un lienzo, una dirección de lectura, una sección por nivel:
{
"dirección": "lr",
"tema": "gruvbox",
"diagramas": [
{
"id": "l0",
"título": "L0 · Contexto del sistema",
"descripción": "Contexto del sistema: el administrador es una caja. ...",
"nodos": [ ... ],
"bordes": [ ... ]
},
{
"id": "l1",
"título": "L1 · El administrador",
"descripción": "La caja de L0 abierta un nivel: ...",
"contenedores": [ { "etiqueta": "Administrador de máquinas", "miembros": ["api", "q", "db"] } ],
"capas": [ ["actor"], ["api", "q"], ["db"], ["prov"] ],
"nodos": [ ... ],
"bordes": [ ... ]
}
]
}
dirección: "lr"una vez, en el lienzo. Nunca una anulación por diagrama: un lector que reorienta en cada sección ha perdido la escalera.- Cinco secciones.
l0,l1,l1b,l2,l2b, en ese orden. Una sexta sección necesita la medición del Paso 3 registrada; un lienzo de diez o veinte secciones es una lista de temas, no una escalera — pliégala de nuevo a tres profundidades y dos rebanadas cada una. contenedoreses una lista por diagrama de{etiqueta, miembros}. La caja es un rectángulo real de doble borde que crece alrededor de los miembros, con la etiqueta colocada en su borde superior. Se permiten varias cajas por diagrama.- Los ids de los miembros deben existir en los
nodosde ese diagrama. Un id de miembro que no nombra ningún nodo es eliminado silenciosamente por el analizador — la caja entonces dibuja alrededor de menos nodos de los que declaraste y--checkno advierte. Cuenta la caja dibujada contra los miembros que declaraste. - Regla de contigüidad. Un contenedor es un rectángulo