Patrones de la App BlackAgents
Cuándo Aplicar
Léelo al implementar una funcionalidad o corrección que toque app/**, app/api/** o lib/**. Las restricciones estrictas viven en las reglas typescript-strict y api-response-format; este archivo explica las capas y las recetas.
Arquitectura (respeta las capas)
UI (components/features/, client) ──fetch──▶ API routes (app/api/**/route.ts)
│ { success, data | error }
Domain (lib/artifacts/, lib/standards/)
│ parse / serialize / graph
Filesystem (lib/fs-service.ts)
│ resolveInWorkspace (sin escape)
Carpeta del workspace (.cursor / .claude ...)
Reglas de convivencia:
- La lógica pura e independiente de plataforma vive en
lib/artifacts/**. Nunca importa React ninext/server. - Las preocupaciones HTTP viven solo en
app/api/**/route.ts. - Todo acceso a disco pasa por
lib/fs-service.ts; nunca llames anode:fsdirectamente desde una ruta.
Convenciones del App Router
- Las páginas son componentes servidor por defecto; añade
"use client"solo para interactividad/estado/efectos. - Grupos de rutas:
/agents,/commands,/rules,/skillscada uno tiene una página de lista, una página de edición[name]y una páginanew;/newes el asistente guiado. Otras rutas:/graph,/standards,/export,/sync,/chat,/providers,/settings. - Los componentes de funcionalidad del cliente obtienen datos mediante
apiFetch(lib/api.ts) y leen el estado del workspace activo desdeWorkspaceProvider— nada defetchcrudo ni lecturas directas de configuración en el cliente.
Receta de Ruta API
import { ok, fail, handle } from "@/lib/api-response"
import { artifactInputSchema } from "@/lib/artifacts/schemas"
export async function POST(req: Request) {
return handle(async () => {
const parsed = artifactInputSchema.safeParse(await req.json())
if (!parsed.success) return fail(parsed.error.issues[0].message, 400)
// ...trabajo de dominio via lib/artifacts + lib/fs-service...
return ok({ /* datos */ })
})
}
- Siempre retorna mediante
ok/fail; envuélvelo enhandlepara que las excepciones se conviertan en un envelope500. - Lee la raíz del workspace desde la configuración (
lib/config.ts), luego usaresolveInWorkspace(raíz, relPath). - Lee los secrets con
lib/secrets.tssolo del lado servidor; credenciales faltantes →fail("...", 412).
El Modelo de Dominio
lib/artifacts/:
types.ts—Artifact,ArtifactType,Platform,ArtifactFrontmatter(independiente de herramienta).layout.ts—PLATFORM_LAYOUTS+artifactRelPath()/artifactDeletePath(); el único lugar que conoce las carpetas/extensiones de una plataforma.ACTIVE_PLATFORMS = ["cursor", "claude"], por defectocursor.parser.ts—scanWorkspace(raíz)yparseArtifact(mediantegray-matter); los skills se recorren recursivamente como un directorio<nombre>/SKILL.md.serializer.ts—serializeArtifact(input)escribe frontmatter + cuerpo; las reglas omitenname(identificado por el nombre de archivo).schemas.ts—nameSchema(kebab-case),artifactInputSchema,normalizeExtra(frontmatter por tipo).graph.ts— extrae referencias cruzadas de las convenciones de autoría.
Convenciones de Referencias Cruzadas (lo que lee el grafo)
| De → A | Convención en el cuerpo |
|---|---|
| Comando → Agente | nombre-del-agente (negrita) |
| Agente → Regla | `nombre-regla` regla |
| Agente → Skill | `nombre-skill` skill |
| Regla → Regla | Reglas relacionadas: a, b. |
| Regla → Skill | Ver también: skill x. |
Escribe los cuerpos con estas convenciones exactas para que el grafo de relaciones y la detección de enlaces del asistente los reconozcan.
Seguridad del Sistema de Archivos
export function resolveInWorkspace(raíz: string, rutaRelativa: string): string {
// resuelve rutaRelativa bajo raíz y lanza WorkspaceError si escapa
}
Cada lectura/escritura debe construirse a partir de una ruta relativa al workspace a través de esta función. Nunca concatenes rutas absolutas ni aceptes una ruta absoluta proporcionada por el cliente.
Persistencia Fuera del Workspace
~/.black-agents/config.json— workspaces guardados +currentPathactivo (lib/config.ts).~/.black-agents/secrets.json— claves LLM, modo0600, solo servidor (lib/secrets.ts).<workspace>/.black-agents/standards.md— sobrescritura de estándares de autoría por workspace.- Sobrescribe el directorio de configuración con
BLACK_AGENTS_CONFIG_DIR(útil en tests).
Cómo Usar
Solo como referencia. La personalidad y el flujo de trabajo viven en el agente feature-developer; las barreras de seguridad viven en las reglas typescript-strict y api-response-format. Usa este archivo para ubicar la lógica en la capa correcta y copiar la receta de rutas, luego pasa la UI al agente uiux-designer y la cobertura al agente tester.