Vue 3 patterns — Composition API, composables, reactivity, component design,
97
93%
Does it follow best practices?
Impact
99%
1.33xAverage score across 8 eval scenarios
Passed
No known issues
{
"context": "Tests whether the agent avoids common Vue 3 reactivity pitfalls: destructuring reactive() objects without toRefs(), reassigning reactive objects, and using reactive() for primitive values instead of ref().",
"type": "weighted_checklist",
"checklist": [
{
"name": "No bare reactive() destructure",
"description": "The code does NOT destructure a reactive() object directly (e.g. does NOT do `const { a, b } = reactive({...})` — this loses reactivity) without using toRefs()",
"max_score": 12
},
{
"name": "toRefs when destructuring reactive",
"description": "If a reactive() object is destructured, toRefs() is used to wrap it first (e.g. `const { a, b } = toRefs(state)`)",
"max_score": 10
},
{
"name": "Object.assign for reactive reset",
"description": "When a reactive() object (e.g. a form object) is reset to initial values, Object.assign(target, initialValues) is used rather than reassigning the variable to a new reactive() object",
"max_score": 12
},
{
"name": "No reactive variable reassignment",
"description": "No reactive() variable is ever reassigned with `=` after its initial declaration — mutations go through property assignment or Object.assign()",
"max_score": 10
},
{
"name": "ref for primitives",
"description": "Primitive values (booleans, strings, numbers, null) used as standalone reactive state are declared with `ref()`, not wrapped in a single-property `reactive({})`",
"max_score": 10
},
{
"name": "script setup lang ts",
"description": "All .vue component files use `<script setup lang=\"ts\">`",
"max_score": 6
},
{
"name": "defineProps generic typing",
"description": "Any component props are declared using `defineProps<T>()` with a TypeScript interface or inline type",
"max_score": 6
},
{
"name": "defineEmits tuple syntax",
"description": "If events are emitted, they use `defineEmits<{ eventName: [payloadType] }>()` with the object-and-tuple syntax",
"max_score": 6
},
{
"name": "Form label association",
"description": "Form input elements are associated with labels using `<label :for=\"id\">` paired with matching `:id` on the input, or `aria-label` on the input",
"max_score": 8
},
{
"name": "aria-label on buttons",
"description": "All button elements include a descriptive `:aria-label` attribute",
"max_score": 8
},
{
"name": "role=alert on error regions",
"description": "Any error or validation message container includes `role=\"alert\"`",
"max_score": 6
},
{
"name": "try/catch/finally pattern",
"description": "Any async operation uses try/catch/finally: sets loading before the call, catches errors, and clears loading in finally",
"max_score": 6
}
]
}evals
scenario-1
scenario-2
scenario-3
scenario-4
scenario-5
scenario-6
scenario-7
scenario-8
skills
vue-best-practices
verifiers