composition-patterns (vercel-labs/agent-skills)
Refactoriza componentes React en componentes compuestos y API reutilizables, evitando la proliferación de props booleanas.
vercel-composition-patterns: lleva un componente React con props booleanas a una API de componentes compuestos (control 3.7, con skill 4.4), sin tokens adicionales, pero un prompt de una frase con el mismo consejo obtiene 4.7
Codex CLI · gpt-6-astra
25.1 / 30
Mejora frente a sin skill: +0.68 · Según el caso · 18 ejecuciones
Según el caso: la mejora +0.68 está por debajo de +1.0. Para ser recomendada hace falta un total de 22/30, una calidad de salida de 3.5 y una mejora de +1.0.
SOTA
AprobadaProbada con Codex.
Cubre Codex, Claude Code
Codex CLI 0.166 (nivel SOTA): 18 ejecuciones puntuadas. Una pasada aquí también cubre Claude Code según nuestra regla de niveles; no dice nada sobre el segundo nivel.
Puntuaciones
Cada dimensión va de 0 a 5 y las seis suman el total sobre 30. 5 es mejor en todas las dimensiones. Coste 5 significa barato y rápido. Instalación 5 significa fácil.
- Fiabilidad de activación
- 5.0
- Mejora frente a sin skill
- 2.7
- Calidad de salida
- 4.4
- Coste en tokens y tiempo
- 5.0
- Instalación y portabilidad
- 4.0
- Seguridad
- 4.0
Revisión de seguridad
SeguraEscaneo estático: 0 CRITICAL / 0 HIGH / 0 MEDIUM. Revisión manual: Segura de ejecutar en un sandbox sin red (sin hallazgos). Un escaneo limpio no demuestra que una skill sea segura.
Instalar
npx skills@latest add vercel-labs/agent-skills --skill composition-patterns
Commit fijado: 1a2c79d4e6c4a2283dc2c614b6538cbe1ed5ca62
Probada: 2026-11-02
Qué probamos
- Sustituye las props booleanas por composición — Composer.tsx ha acumulado un montón de props booleanas. Refactorízalo a una API de componente flexible que no las necesite. Mantenlo en el único archivo Composer.tsx y conserva el comportamiento.
- Añade una variante sin añadir props — Añade un compositor de «respuesta rápida»: una entrada de una línea que envía al pulsar Enter, sin adjuntos ni botón de emoji. No añadas más props booleanas a Composer. Edita Composer.tsx.
- Revisa una API de componente — Revisa la API del componente Composer.tsx: ¿qué tiene de malo y qué cambiarías? No cambies ningún archivo.
Ventajas
- Eleva la puntuación media de 3.71 a 4.39 frente a sin skill (+0.68).
- La skill se activó sin nombrarla: se leyó el archivo de la skill en 6/6 ejecuciones con skill.
- Sin sobrecoste de tokens: 1.03x los tokens de sin skill.
Inconvenientes
- Un prompt de una frase obtuvo 4.7, frente a 4.39 con la skill (-0.31).
- n=2 por tarea y rama; las diferencias de menos de aproximadamente 1 punto son ruido.
Reseña
Codex CLI 0.166 (gpt-6-astra, razonamiento bajo) en un PC de pruebas Windows dedicado, un proyecto temporal nuevo y HOME/TMPDIR/cachés temporales en cada ejecución, skill instalada (grupo con skill), ausente (control) o ausente con el requisito central de la skill comprimido en una frase añadida al prompt (grupo del prompt de una frase), 2 ejecuciones por grupo y tarea, red desactivada, escrituras en /tmp bloqueadas. Los prompts nunca mencionan la skill (salvo la redacción indicada abajo). Un componente de compositor de chat (Composer.tsx) con un montón de props booleanas. Tareas: refactorizarlo a una API flexible conservando el comportamiento, añadir un compositor de «respuesta rápida» de una línea sin añadir más booleanos y revisar la API del componente (sin editar). Los prompts no nombran ningún patrón. El prompt de una frase nombra los patrones (variantes explícitas a partir de partes compuestas, contexto compartido con estado/acciones, children en lugar de renderX, estado elevado a un provider).
Comparación de tres ramas
| Rama | Puntuación media (0-5) | Tokens por ejecución |
|---|---|---|
| Sin la skill | 3.71 | 103k |
| Prompt de una frase | 4.7 | 105k |
| Con la skill | 4.39 | 105k |
Medido con Codex CLI en 18 ejecuciones, puntuado con comprobaciones basadas en reglas y sin juez LLM. Total 25.1 / 30, veredicto Según el caso.
Veredicto: Según el caso (25.1 / 30). Fuente: vercel-labs/agent-skills, skills/composition-patterns, fijada en el commit 1a2c79d. Instalación: npx skills@latest add vercel-labs/agent-skills --skill composition-patterns. Licencia: MIT (LICENSE del repositorio).
Qué es
La skill vercel-composition-patterns (vercel-labs/agent-skills): orientación sobre composición en React: evita la proliferación de props booleanas, crea componentes compuestos que comparten estado mediante contexto (una interfaz genérica de estado/acciones), crea componentes de variante explícitos, prefiere children frente a props renderX, eleva el estado a providers; incluye notas de React 19. Un SKILL.md más una carpeta de reglas.
Cómo lo probamos
Codex CLI 0.166 (gpt-6-astra, razonamiento bajo) en un PC de pruebas Windows dedicado, un proyecto temporal nuevo y HOME/TMPDIR/cachés temporales por ejecución, skill instalada (tratamiento) o ausente (control) o ausente con el requisito central de la skill comprimido en una frase añadida al final del prompt (grupo de una frase), 2 ejecuciones por grupo y tarea, red desactivada, escrituras en /tmp bloqueadas. Los prompts nunca mencionan la skill (salvo la formulación indicada abajo).
Un componente de compositor de chat (Composer.tsx) con un montón de props booleanas. Tareas: refactorizarlo a una API flexible conservando el comportamiento, añadir un compositor de 'respuesta rápida' de una línea sin añadir más props booleanas, y revisar la API del componente (sin ediciones). Los prompts no nombran ningún patrón. La frase única nombra los patrones (variantes explícitas a partir de partes compuestas, contexto compartido con estado/acciones, children en lugar de renderX, estado elevado a un provider).
- Sustituir props booleanas por composición — Composer.tsx ha acumulado un montón de props booleanas. Refactorízalo a una API de componente flexible que no las necesite. Mantenlo en el único archivo Composer.tsx y conserva el comportamiento.
- Añadir una variante sin añadir props — Añade un compositor de 'respuesta rápida': una entrada de una línea que envía con Enter, sin archivos adjuntos ni botón de emoji. No añadas más props booleanas a Composer. Edita Composer.tsx.
- Revisar la API de un componente — Revisa la API del componente Composer.tsx: ¿qué está mal y qué cambiarías? No cambies ningún archivo.
La puntuación es programática (tests ocultos / detección de problemas sembrados / comprobaciones de restricciones / renderizado + OCR cuando corresponde), 0–5 por ejecución. Ningún juez LLM decidió ninguna puntuación.
Resultados
La frase única que recibió el tercer grupo: "Evita la proliferación de props booleanas: separa los modos en componentes de variante explícitos construidos a partir de partes compuestas que comparten un contexto con una interfaz genérica de estado/acciones, usa children en lugar de props renderX y eleva el estado a un provider."
| Tarea | Puntuación control | Una frase | Con la skill | Tokens control | Tokens de una frase | Tokens con la skill | Skill leída |
|---|---|---|---|---|---|---|---|
| t1-refactor | 3.0 | 4.5 | 4.0 | 126k | 127k | 144k | 2/2 |
| t2-add-variant | 4.38 | 5.0 | 5.0 | 99k | 106k | 100k | 2/2 |
| t3-review | 3.75 | 4.58 | 4.17 | 81k | 80k | 70k | 2/2 |
Puntuación media: 3.71 sin vs 4.39 con la skill (delta +0.68). Tokens por ejecución: 103k vs 105k (1.03x); tiempo 53s vs 49s. Grupo de una frase: 4.7 (la ganancia de la skill sobre la frase única: -0.31; la ganancia de la frase única sobre sin skill: +0.99); tokens de la frase única 105k por ejecución, así que la skill cuesta 1.00x la frase única.
Qué ocurrió
- Control 3.71, skill 4.39, una frase 4.70 (n=6 cada uno). Sin orientación, las refactorizaciones del control sí usaron partes compuestas, pero en ambas ejecuciones el contexto compartido no exponía una interfaz de estado/acciones, y en ambas ejecuciones de respuesta rápida el nuevo compositor no enviaba con Enter.
- Las refactorizaciones de la skill tenían el contexto con estado y acciones (2/2) y su compositor de respuesta rápida enviaba con Enter (2/2). Pero ambas refactorizaciones de tratamiento, igual que el control, no crearon componentes de variante explícitos (las ejecuciones de una frase sí, en 2/2), y en la tarea de revisión tanto las dos ejecuciones de tratamiento como las dos de control omitieron el punto de 'proliferación de props booleanas' (un patrón de comprobación débil: los revisores pueden formularlo de otra manera).
- Los tokens son los mismos para skill, frase única y control (105k, 105k, 103k): la skill se leyó en 6/6 ejecuciones de tratamiento sin ser nombrada, y no cuesta nada extra.
- Las ejecuciones de tratamiento copian la carpeta de reglas al proyecto (14.7 archivos nuevos por ejecución).
Puntuaciones por dimensión
| Dimensión | Puntuación | Motivo |
|---|---|---|
| 1_output_quality | 4.39 | Puntuación media 4.39/5 con la skill (comprobaciones programáticas, véase la tabla por tarea). |
| 2_lift_vs_no_skill | 2.68 | +0.68 puntos frente a 3.71 sin la skill (n=2 por tarea; menos de ~1 punto es ruido). |
| 3_trigger | 5.0 | Archivo de la skill leído en 6/6 ejecuciones de tratamiento. |
| 4_instructions_portability | 4 | SKILL.md más un índice AGENTS.md y una carpeta de reglas; solo documentación. |
| 5_efficiency | 5 | 1.03x tokens (105k vs 103k por ejecución) y 0.93x tiempo (49s vs 53s). |
| 6_safety_hygiene | 4 | Solo prosa; consulta security.md. |
Límites de esta prueba
- Comprobaciones basadas en reglas sobre el texto del código (patrones de contexto/provider, componentes de variante, props clave); el TypeScript no se compiló ni se renderizó (React no está instalado en el sandbox).
- Una comprobación de la tarea de revisión es débil: busca la formulación literal 'boolean prop', que los revisores pueden expresar de otra forma.
- Un único componente de prueba; n=2 por celda.
- n = 2 por grupo y tarea: las diferencias de menos de ~1 punto son ruido.
- La puntuación basada en reglas mide lo que las comprobaciones pueden ver; no puede juzgar el gusto ni si el resultado es el mejor posible.
Seguridad
Consulta security.md. Escaneo: 0 CRITICAL / 0 HIGH / 0 MEDIUM. Veredicto: segura de ejecutar (sandbox sin red). Un escaneo limpio no demuestra que una skill sea segura.
Conclusión
Una guía de patrones decente: la estructura de componentes compuestos aparece de forma fiable con la skill y rara vez sin ella, gratis. Una sola frase que nombre los patrones rindió mejor aquí, así que el beneficio de la skill es comodidad y amplitud, no un techo de calidad.
Transcripción
Registro de ejecuciones: composition-patterns (Codex CLI, network off, per-run temp HOME/TMPDIR, one row per graded run.) Columnas: tarea, grupo-ejecución, puntuación (0-5), tokens, segundos, comprobaciones superadas, archivos de la skill que abrió el agente. t1-refactor control-1: puntuación 3.0, tokens 130032, s 72.5, comprobaciones 3/5, no abrió nada t1-refactor control-2: puntuación 3.0, tokens 123317, s 64.3, comprobaciones 3/5, no abrió nada t1-refactor oneliner-1: puntuación 4.0, tokens 127545, s 101.8, comprobaciones 4/5, no abrió nada t1-refactor oneliner-2: puntuación 5.0, tokens 127024, s 89.6, comprobaciones 5/5, no abrió nada t1-refactor treatment-1: puntuación 4.0, tokens 158276, s 67.7, comprobaciones 4/5, abrió composition-patterns t1-refactor treatment-2: puntuación 4.0, tokens 130234, s 59.2, comprobaciones 4/5, abrió composition-patterns t2-add-variant control-1: puntuación 4.38, tokens 99946, s 40.3, comprobaciones 3/4, no abrió nada t2-add-variant control-2: puntuación 4.38, tokens 100013, s 39.2, comprobaciones 3/4, no abrió nada t2-add-variant oneliner-1: puntuación 5.0, tokens 106946, s 70.9, comprobaciones 4/4, no abrió nada
18 ejecuciones, 3 artefactos
Resultado de ejemplo
SOTA · With the skill: Composer.tsx (t1-refactor, run 1, Codex)
import React, { createContext, use, useState } from "react"; type ComposerProps = { initialText?: string; onSubmit: (text: string) => void; children?: React.ReactNode; }; type ComposerContextValue = { state: { text: string }; actions: { setText: (text: string) => void; submit: () => void; }; }; const ComposerContext = createContext<ComposerContextValue | null>(null); export function useComposer() { const context = use(ComposerContext); if (!context) { throw new Error("Composer components must be inside Composer.Provider or Composer."); } return context; } function ComposerProvider({ initialText = "", onSubmit, children }: ComposerProps) { const [text, setText] = useState(initialText); function submit() { onSubmit(text); setText(""); } return ( <ComposerContext value={{ state: { text }, actions: { setText, submit } }}> {children} </ComposerContext> ); } function ComposerFrame({ children }: { children: React.ReactNode }) { const { actions } = useComposer(); return ( <form onSubmit={(event) => { event.preventDefault(); actions.submit(); }}> {children} </form> ); } function ComposerInput({ placeholder = "Message" }: { placeholder?: string }) { const { state, actions } = useComposer(); return ( <textarea value={state.text} onChange={(event) => actions.setText(event.target.value)} placeholder={placeholder} /> ); } function ComposerFormatting() { return ( <div className="toolbar"> <button type="button">B</button> <button type="button">I</button> </div> ); } function ComposerAttachments() { return <button type="button">Attach</button>; } function ComposerEmojis() { return <button type="button">😀</button>; } function ComposerSubmit({ children = "Send" }: { children?: React.ReactNode }) { return <button type="submit">{children}</button>; } function ComposerRoot({ children, ...props }: ComposerProps) { return ( <ComposerProvider {...props}> <ComposerFrame> {children === undefined ? <><ComposerInput /><ComposerSubmit /></> : children} </ComposerFrame> </ComposerProvider> ); } /** * Compose controls in their display order; footer content is ordinary children: * * <Composer initialText="Draft" onSubmit={send}> * <Composer.Formatting /> * <Composer.Input placeholder="Reply in thread" /> * <Composer.Attachments /> * <Composer.Emojis /> * <Composer.Submit /> * <CustomFooter /> * </Composer> * * Message: use the default input placeholder and submit label. * Thread: use "Reply in thread" and "Send". * Forward: use "Add a note" and "Forward". * Edit: use "Edit message" and "Save", and omit Attachments. * When migrating overlapping modes, edit takes precedence over forward, then thread. * Include Formatting, Attachments, and Emojis only where needed. * Provider and Frame can also be composed separately to share state with siblings. */ export const Composer = Object.assign(ComposerRoot, { Provider: ComposerProvider, Frame: ComposerFrame, Input: ComposerInput, Formatting: ComposerFormatting, Attachments: ComposerAttachments, Emojis: [... excerpt: first 3200 of 3247 characters]