全部技能

composition-patterns (vercel-labs/agent-skills)

把 React 组件重构为复合组件和可复用 API,避免布尔属性不断增加。

composition-patterns:对照组 3.71、一句话提示 4.7、装 skill 4.39(0–5 分,Codex 实测,n=2/任务/组)。结论:视情况而定,相对不装 skill +0.68。

看情况安全

Codex CLI · gpt-6-astra

25.1 / 30

相对不装 skill 的提升:+0.68 · 看情况 · 18 次运行

视情况而定:提升 +0.68 低于 +1.0。推荐要求总分 22/30、产出质量 3.5、提升 +1.0。

前沿

通过

使用 Codex 测试。

覆盖 Codex, Claude Code

Codex CLI 0.166(SOTA 档):18 次评分运行。按我们的分档规则,这档通过同时覆盖 Claude Code;它不代表第二档的结果。

分数

每一维 0 到 5 分,六维相加是满分 30 的总分。每一维都是 5 更好。成本 5 表示又便宜又快。安装 5 表示容易。

触发可靠性
5.0
相对不装的提升
2.7
产出质量
4.4
令牌与时间成本
5.0
安装与可移植性
4.0
安全
4.0

安全审查

安全

静态扫描:0 CRITICAL / 0 HIGH / 0 MEDIUM。人工审查:可在断网沙箱中运行。扫描没有命中不等于绝对安全。

安装

npx skills@latest add vercel-labs/agent-skills --skill composition-patterns

来源

固定提交: 1a2c79d4e6c4a2283dc2c614b6538cbe1ed5ca62

测试日期: 2026-11-02

我们测了什么

  • Replace boolean props with composition — Composer.tsx has grown a pile of boolean props. Refactor it into a flexible component API that does not need them. Keep it in the single file Composer.tsx and keep the behaviour.
  • Add a variant without adding props — Add a 'quick reply' composer: a one-line input that sends on Enter, with no attachments or emoji button. Do not add more boolean props to Composer. Edit Composer.tsx.
  • Review a component API — Review the component API of Composer.tsx: what is wrong with it and what would you change? Do not change any files.

优点

  • 平均分从不装时的 3.71 提到 4.39(+0.68)。
  • 不点名也会被触发:Skill file read in 6/6 treatment runs.
  • 不增加 token 开销:约为不装 skill 时的 1.03 倍。

缺点

  • 一句话提示得 4.7,装 skill 得 4.39(差 -0.31)。
  • 每个任务每组 n=2,差距在 1 分以内属于噪声。

评测

在 Codex CLI(SOTA 档)上跑 3 个任务、对照、一句话提示、装 skill 三组,共 18 次运行,由规则脚本打分(没有 LLM 评委),断网沙箱、每次运行独立临时目录。具体做法见下方英文评测原文。

三组对比

组别平均分(0–5)每次 token
不装 skill3.71103k
一句话提示4.7105k
装了 skill4.39105k

Codex CLI 实测,18 次运行,规则脚本打分,没有 LLM 评委。总分 25.1 / 30,结论 视情况而定。

下面是评测原文,英文。

Verdict: Situational (25.1 / 30). Source: vercel-labs/agent-skills, skills/composition-patterns, pinned at commit 1a2c79d. Install: npx skills@latest add vercel-labs/agent-skills --skill composition-patterns. Licence: MIT (repo LICENSE).

What it is

The vercel-composition-patterns skill (vercel-labs/agent-skills): React composition guidance: avoid boolean prop proliferation, build compound components that share state through context (a generic state/actions interface), create explicit variant components, prefer children over renderX props, lift state into providers; includes React 19 notes. A SKILL.md plus a rules folder.

How we tested

Codex CLI 0.166 (gpt-6-astra, low reasoning) on a dedicated Windows test PC, a fresh temporary project and temporary HOME/TMPDIR/caches per run, skill installed (treatment) or absent (control) or absent with the skill's core requirement squeezed into one sentence appended to the prompt (one-liner group), 2 runs per group per task, network off, /tmp writes blocked. The prompts never mention the skill (except the wording noted below).

One chat-composer component (Composer.tsx) with a pile of boolean props. Tasks: refactor it into a flexible API keeping behaviour, add a 'quick reply' one-line composer without adding more booleans, and review the component API (no edits). Prompts do not name any pattern. The one-liner names the patterns (explicit variants from compound parts, shared context with state/actions, children instead of renderX, state lifted into a provider).

  1. Replace boolean props with composition — Composer.tsx has grown a pile of boolean props. Refactor it into a flexible component API that does not need them. Keep it in the single file Composer.tsx and keep the behaviour.
  2. Add a variant without adding props — Add a 'quick reply' composer: a one-line input that sends on Enter, with no attachments or emoji button. Do not add more boolean props to Composer. Edit Composer.tsx.
  3. Review a component API — Review the component API of Composer.tsx: what is wrong with it and what would you change? Do not change any files.

Scoring is programmatic (hidden tests / planted-issue recall / constraint checks / render+OCR where relevant), 0–5 per run. No LLM judge decided any score.

Results

The one-liner given to the third group: "Avoid boolean prop proliferation: split modes into explicit variant components built from compound parts that share a context with a generic state/actions interface, use children instead of renderX props, and lift state into a provider."

TaskControl scoreOne-linerWith skillControl tokensOne-liner tokensWith-skill tokensSkill read
t1-refactor3.04.54.0126k127k144k2/2
t2-add-variant4.385.05.099k106k100k2/2
t3-review3.754.584.1781k80k70k2/2

Mean score: 3.71 without vs 4.39 with the skill (delta +0.68). Tokens per run: 103k vs 105k (1.03x); time 53s vs 49s. One-liner group: 4.7 (the skill's gain over the one-liner: -0.31; one-liner's own gain over no skill: +0.99); one-liner tokens 105k per run, so the skill costs 1.00x the one-liner.

What happened

  • Control 3.71, skill 4.39, one-liner 4.70 (n=6 each). Without guidance, control's refactors did use compound parts but in both runs the shared context did not expose a state/actions interface, and in both quick-reply runs the new composer did not send on Enter.
  • The skill's refactors had the context with state and actions (2/2) and its quick-reply composer sent on Enter (2/2). But both treatment refactors, like control, did not create explicit variant components (the one-liner runs did in 2/2), and in the review task both treatment runs and both control runs missed the 'boolean prop proliferation' point (a weak check pattern: reviewers may word it differently).
  • Tokens are the same for skill, one-liner and control (105k, 105k, 103k): the skill read in 6/6 treatment runs without being named, and costs nothing extra.
  • Treatment runs copy the rules folder into the project (14.7 new files per run).

Dimension scores

DimensionScoreWhy
1_output_quality4.39

Mean score 4.39/5 with the skill (programmatic checks, see per-task table).

2_lift_vs_no_skill2.68

+0.68 points vs 3.71 without the skill (n=2 per task; under ~1 point is noise).

3_trigger5.0Skill file read in 6/6 treatment runs.
4_instructions_portability4SKILL.md plus an AGENTS.md index and a rules folder; docs only.
5_efficiency5

1.03x tokens (105k vs 103k per run) and 0.93x time (49s vs 53s).

6_safety_hygiene4Prose only; see security.md.

Limits of this test

  • Rule-based checks on code text (context/provider patterns, variant components, key props); the TypeScript was not compiled or rendered (React is not installed in the sandbox).
  • One check for the review task is weak: it looks for the literal 'boolean prop' wording, which reviewers can express differently.
  • Single component fixture; n=2 per cell.
  • n = 2 per group per task: differences under about 1 point are noise.
  • Rule-based scoring measures what the checks can see; it cannot judge taste or whether a result is the best possible.

Security

See security.md. Scan: 0 CRITICAL / 0 HIGH / 0 MEDIUM. Verdict: safe to run (no-network sandbox). A clean scan does not prove a skill safe.

Bottom line

A decent pattern guide: the compound-component structure appears reliably with the skill and rarely without it, for free. A single sentence naming the patterns did better here, so the skill's benefit is convenience and breadth, not a quality ceiling.

记录

Run log for composition-patterns: Codex CLI, network off, per-run temp HOME/TMPDIR, one row per graded run.
Columns: task, arm-run, score (0-5), tokens, seconds, checks passed, skill files the agent opened.

t1-refactor control-1: score 3.0, tokens 130032, secs 72.5, checks 3/5, opened nothing
t1-refactor control-2: score 3.0, tokens 123317, secs 64.3, checks 3/5, opened nothing
t1-refactor oneliner-1: score 4.0, tokens 127545, secs 101.8, checks 4/5, opened nothing
t1-refactor oneliner-2: score 5.0, tokens 127024, secs 89.6, checks 5/5, opened nothing
t1-refactor treatment-1: score 4.0, tokens 158276, secs 67.7, checks 4/5, opened composition-patterns
t1-refactor treatment-2: score 4.0, tokens 130234, secs 59.2, checks 4/5, opened composition-patterns
t2-add-variant control-1: score 4.38, tokens 99946, secs 40.3, checks 3/4, opened nothing
t2-add-variant control-2: score 4.38, tokens 100013, secs 39.2, checks 3/4, opened nothing
t2-add-variant oneliner-1: score 5.0, tokens 106946, secs 70.9, checks 4/4, opened nothing

18 次运行、3 个产物

样例产物

前沿 · 装了 skill:Composer.tsx(t1-refactor,第 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]

查看 Pro