composition-patterns (vercel-labs/agent-skills)
Refatora componentes React em componentes compostos e APIs reutilizáveis, evitando a proliferação de props booleanas.
vercel-composition-patterns: converte um componente React com props booleanas para uma API de componente composto (controle 3.7, skill 4.4), sem custo extra de tokens, mas um prompt de uma frase com o mesmo conselho pontua 4.7
Codex CLI · gpt-6-astra
25.1 / 30
Ganho sobre sem skill: +0.68 · Situacional · 18 execuções
Situacional: o ganho +0.68 está abaixo de +1.0. Para ser recomendado, é preciso total de 22/30, qualidade da saída de 3.5 e ganho de +1.0.
SOTA
AprovadoTestado com Codex.
Cobre Codex, Claude Code
Codex CLI 0.166 (nível SOTA): 18 execuções avaliadas. Uma aprovação aqui também vale para o Claude Code pela nossa regra de níveis; ela não diz nada sobre o segundo nível.
Notas
Cada dimensão vai de 0 a 5, e as seis somam o total de 30. 5 é melhor em todas as dimensões. Custo 5 significa barato e rápido. Instalação 5 significa fácil.
- Confiabilidade do acionamento
- 5.0
- Ganho sobre sem skill
- 2.7
- Qualidade da saída
- 4.4
- Custo de tokens e tempo
- 5.0
- Instalação e portabilidade
- 4.0
- Segurança
- 4.0
Revisão de segurança
SeguroVarredura estática: 0 CRÍTICO / 0 ALTO / 0 MÉDIO. Revisão manual: seguro para executar em sandbox sem rede (nenhum achado). Uma varredura limpa não prova que a skill é segura.
Instalar
npx skills@latest add vercel-labs/agent-skills --skill composition-patterns
Commit fixado: 1a2c79d4e6c4a2283dc2c614b6538cbe1ed5ca62
Testado: 2026-11-02
O que testamos
- Substituir props booleanas por composição — Composer.tsx acumulou um monte de props booleanas. Refatore-o para uma API de componente flexível que não precise delas. Mantenha tudo no único arquivo Composer.tsx e preserve o comportamento.
- Adicionar uma variante sem adicionar props — Adicione um composer de 'resposta rápida': um input de uma linha que envia no Enter, sem anexos nem botão de emoji. Não adicione mais props booleanas ao Composer. Edite Composer.tsx.
- Revisar a API de um componente — Revise a API do componente Composer.tsx: o que há de errado e o que você mudaria? Não altere nenhum arquivo.
Prós
- Eleva a nota média de 3.71 para 4.39 em relação ao grupo sem skill (+0.68).
- A skill foi acionada sem ser nomeada: o arquivo da skill foi lido em 6/6 execuções de tratamento.
- Sem custo extra de tokens: 1.03x os tokens do grupo sem skill.
Contras
- Um prompt de uma frase marcou 4.7, contra 4.39 com a skill (-0.31).
- n=2 por tarefa por braço; diferenças abaixo de cerca de 1 ponto são ruído.
Avaliação
Codex CLI 0.166 (gpt-6-astra, raciocínio baixo) em um PC de teste Windows dedicado, com um projeto temporário novo e HOME/TMPDIR/caches temporários a cada execução, skill instalada (tratamento) ou ausente (grupo de controle) ou ausente com o requisito central da skill comprimido em uma frase anexada ao prompt (grupo prompt de uma frase), 2 execuções por grupo por tarefa, rede desligada, gravações em /tmp bloqueadas. Os prompts nunca mencionam a skill (exceto pelo texto indicado abaixo). Um componente de composer de chat (Composer.tsx) com um monte de props booleanas. Tarefas: refatorá-lo para uma API flexível mantendo o comportamento, adicionar um composer de 'resposta rápida' de uma linha sem adicionar mais booleanos, e revisar a API do componente (sem edições). Os prompts não nomeiam nenhum padrão. O prompt de uma frase nomeia os padrões (variantes explícitas a partir de partes compostas, contexto compartilhado com estado e ações, children em vez de renderX, estado elevado para um provider).
Comparação entre os braços
| Braço | Nota média (0-5) | Tokens por execução |
|---|---|---|
| Sem a skill | 3.71 | 103k |
| Prompt de uma frase | 4.7 | 105k |
| Com a skill | 4.39 | 105k |
Medido com Codex CLI em 18 execuções, com pontuação por verificações baseadas em regras e sem juiz LLM. Total 25.1 / 30, veredito Situacional.
Veredito: Situacional (25.1 / 30). Fonte: vercel-labs/agent-skills, skills/composition-patterns, fixada no commit 1a2c79d. Instalação: npx skills@latest add vercel-labs/agent-skills --skill composition-patterns. Licença: MIT (LICENSE do repositório).
O que é
A skill vercel-composition-patterns (vercel-labs/agent-skills): orientação de composição em React: evite a proliferação de props booleanas, construa componentes compostos que compartilham estado por contexto (uma interface genérica de estado/ações), crie componentes de variante explícitos, prefira children a props renderX, eleve o estado para providers; inclui notas sobre React 19. Um SKILL.md mais uma pasta de regras.
Como testamos
Codex CLI 0.166 (gpt-6-astra, raciocínio baixo) em um PC Windows dedicado a testes, um projeto temporário novo e HOME/TMPDIR/caches temporários a cada execução, skill instalada (grupo com skill), ausente (controle) ou ausente com o requisito central da skill comprimido em uma frase anexada ao prompt (grupo de uma frase), 2 execuções por grupo por tarefa, rede desativada, gravações em /tmp bloqueadas. Os prompts nunca mencionam a skill (exceto pela formulação indicada abaixo).
Um componente de compositor de chat (Composer.tsx) com um monte de props booleanas. Tarefas: refatorá-lo para uma API flexível mantendo o comportamento, adicionar um compositor de 'resposta rápida' de uma linha sem adicionar mais booleanos, e revisar a API do componente (sem edições). Os prompts não nomeiam nenhum padrão. A frase única nomeia os padrões (variantes explícitas a partir de partes compostas, contexto compartilhado com estado/ações, children em vez de renderX, estado elevado para um provider).
- Substituir props booleanas por composição — Composer.tsx acumulou um monte de props booleanas. Refatore-o para uma API de componente flexível que não precise delas. Mantenha tudo no único arquivo Composer.tsx e preserve o comportamento.
- Adicionar uma variante sem adicionar props — Adicione um compositor de 'resposta rápida': um input de uma linha que envia ao pressionar Enter, sem anexos nem botão de emoji. Não adicione mais props booleanas ao Composer. Edite Composer.tsx.
- Revisar a API de um componente — Revise a API do componente Composer.tsx: o que há de errado com ela e o que você mudaria? Não altere nenhum arquivo.
A pontuação é programática (testes ocultos / detecção de problemas plantados / verificações de restrições / renderização+OCR quando aplicável), de 0 a 5 por execução. Nenhum juiz LLM decidiu qualquer nota.
Resultados
A frase única dada ao terceiro grupo: "Evite a proliferação de props booleanas: separe os modos em componentes de variante explícitos construídos a partir de partes compostas que compartilham um contexto com uma interface genérica de estado/ações, use children em vez de props renderX e eleve o estado para um provider."
| Tarefa | Nota do controle | Uma frase | Com a skill | Tokens do controle | Tokens da frase | Tokens com a skill | Skill lida |
|---|---|---|---|---|---|---|---|
| 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 |
Nota média: 3.71 sem vs 4.39 com a skill (delta +0.68). Tokens por execução: 103k vs 105k (1.03x); tempo 53s vs 49s. Grupo de uma frase: 4.7 (ganho da skill sobre a frase: -0.31; ganho da própria frase sobre sem skill: +0.99); tokens da frase: 105k por execução, então a skill custa 1.00x a frase.
O que aconteceu
- Controle 3.71, skill 4.39, frase 4.70 (n=6 cada). Sem orientação, as refatorações do controle usaram partes compostas, mas nas duas execuções o contexto compartilhado não expunha uma interface de estado/ações, e nas duas execuções de resposta rápida o novo compositor não enviava ao pressionar Enter.
- As refatorações da skill tinham o contexto com estado e ações (2/2), e seu compositor de resposta rápida enviava ao pressionar Enter (2/2). Mas as duas refatorações com a skill, como o controle, não criaram componentes de variante explícitos (as execuções da frase criaram em 2/2), e na tarefa de revisão as duas execuções com a skill e as duas do controle perderam o ponto de 'proliferação de props booleanas' (um padrão de verificação fraco: revisores podem escrever isso de outro jeito).
- Os tokens são os mesmos para skill, frase e controle (105k, 105k, 103k): a skill é lida em 6/6 execuções com a skill sem ser nomeada, e não custa nada extra.
- As execuções com a skill copiam a pasta de regras para o projeto (14.7 arquivos novos por execução).
Notas por dimensão
| Dimensão | Nota | Por quê |
|---|---|---|
| 1_output_quality | 4.39 | Nota média 4.39/5 com a skill (verificações programáticas, veja a tabela por tarefa). |
| 2_lift_vs_no_skill | 2.68 | +0.68 pontos vs 3.71 sem a skill (n=2 por tarefa; abaixo de ~1 ponto é ruído). |
| 3_trigger | 5.0 | Arquivo da skill lido em 6/6 execuções com a skill. |
| 4_instructions_portability | 4 | SKILL.md, um índice AGENTS.md e uma pasta de regras; somente documentação. |
| 5_efficiency | 5 | 1.03x tokens (105k vs 103k por execução) e 0.93x tempo (49s vs 53s). |
| 6_safety_hygiene | 4 | Somente prosa; veja security.md. |
Limitações deste teste
- Verificações baseadas em regras no texto do código (padrões de contexto/provider, componentes de variante, props key); o TypeScript não foi compilado nem renderizado (React não está instalado no sandbox).
- Uma verificação da tarefa de revisão é fraca: ela procura a expressão literal 'boolean prop', que revisores podem expressar de outra forma.
- Um único componente de teste; n=2 por célula.
- n = 2 por grupo por tarefa: diferenças abaixo de cerca de 1 ponto são ruído.
- A pontuação baseada em regras mede o que as verificações conseguem ver; não avalia gosto nem se o resultado é o melhor possível.
Segurança
Veja security.md. Varredura: 0 CRITICAL / 0 HIGH / 0 MEDIUM. Veredito: seguro para executar (sandbox sem rede). Uma varredura limpa não prova que a skill é segura.
Conclusão
Um guia de padrões decente: a estrutura de componentes compostos aparece de forma confiável com a skill e raramente sem ela, de graça. Uma única frase nomeando os padrões foi melhor aqui, então o benefício da skill é conveniência e amplitude, não um teto de qualidade.
Transcrição
Log de execuções: composition-patterns (Codex CLI, network off, per-run temp HOME/TMPDIR, one row per graded run.) Colunas: tarefa, grupo-execução, nota (0-5), tokens, segundos, verificações aprovadas, arquivos da skill abertos pelo agente. t1-refactor control-1: nota 3.0, tokens 130032, s 72.5, verificações 3/5, nada aberto t1-refactor control-2: nota 3.0, tokens 123317, s 64.3, verificações 3/5, nada aberto t1-refactor oneliner-1: nota 4.0, tokens 127545, s 101.8, verificações 4/5, nada aberto t1-refactor oneliner-2: nota 5.0, tokens 127024, s 89.6, verificações 5/5, nada aberto t1-refactor treatment-1: nota 4.0, tokens 158276, s 67.7, verificações 4/5, abriu composition-patterns t1-refactor treatment-2: nota 4.0, tokens 130234, s 59.2, verificações 4/5, abriu composition-patterns t2-add-variant control-1: nota 4.38, tokens 99946, s 40.3, verificações 3/4, nada aberto t2-add-variant control-2: nota 4.38, tokens 100013, s 39.2, verificações 3/4, nada aberto t2-add-variant oneliner-1: nota 5.0, tokens 106946, s 70.9, verificações 4/4, nada aberto
18 execuções, 3 artefatos
Resultado de exemplo
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]