Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Use when writing or editing a GraphQL schema in SDL: apply the idiomatic casing, built-in-scalar, non-null, input/payload-suffix, and @deprecated conventions — which cheaper models do not follow by default.
.claude/skills/graphql-sdl-conventions/SKILL.md| Model | Eval pass | Runs |
|---|---|---|
| gemini-3.6-flashlowest | 94% | 18 |
| gemini-3.1-pro-preview | 100% | 1 |
| Model | Lift | Δ tokens | Δ turns | Cases | Verified |
|---|---|---|---|---|---|
| gemini-3.6-flashbest | +18% | +147% | 0% | 22 | 54d ago |
| gemini-3.5-flash | pending re-run | — | |||
| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-01 | ✗→✓ | ▲ Improved | — | — |
| case-14 | ✗→✓ | ▲ Improved | — | — |
| case-18 | ✗→✓ | ▲ Improved | — | — |
| case-17 | ✗→✓ | ▲ Improved | — | — |
| case-12 | ✗→✗ | = Same ✗ | — | — |
When you write or edit a GraphQL schema in the Schema Definition Language (SDL), conform to the spec's type system and the community naming conventions: PascalCase type names, camelCase fields/arguments, SCREAMING_SNAKE_CASE enum values, the exactly-five built-in scalars (Int Float String Boolean ID) with everything else declared as a custom scalar, non-null ! discipline, Input/Payload mutation suffixes, and the built-in @deprecated(reason:) directive for retiring fields. Apply this to any object type, interface, union, enum, input, mutation, or scalar you emit.
type, interface, union,enum, input, and any custom scalar — is UpperCamelCase: PaymentMethod, ShippingAddress. Never snake_case (payment_method) or camelCase (paymentMethod) for a type name. The three root operation types are named exactly Query, Mutation, Subscription.
lowerCamelCase: phoneNumber, createdAt, argument orderBy. Convert any snake_case the request hands you (phone_number, created_at) to camelCase — never keep snake_case, SCREAMING_SNAKE_CASE, or PascalCase on a field.
joined by underscores: PENDING, AWAITING_PAYMENT. Never lowercase (pending), camelCase (awaitingPayment), or PascalCase (AwaitingPayment) enum members. The enum type itself is still PascalCase.
Int(32-bit signed whole number), Float (double-precision decimal), String, Boolean, and ID. Use Int for counts/quantities — never Integer, Number, or Long. Use Float for decimals — never Double or Decimal. Use Boolean — never Bool. Any other primitive (a date, timestamp, URL, email, JSON blob, decimal money) is not built in: declare it once with the scalar keyword (scalar DateTime) and reference that, or fall back to String. Never write Date, DateTime, Timestamp, JSON, or URL as a field type without a matching scalar declaration.
!. A field that is always present carries atrailing ! (String!). The primary identifier is id: ID!. Lists: [T] is a nullable list of nullable items; a required list of required items is [T!]!. Choose nullability deliberately — do not make everything nullable and do not make everything non-null.
Input type. When a mutation takes more than atrivial argument, define an Input Object with the input keyword (not type) and name it with the Input suffix: input CreateBookingInput { ... }. The mutation then takes a single argument of that input type. Input fields follow the same camelCase rule.
Payload (or Response) type from mutations. A mutation returns adedicated object type whose name ends in Payload or Response (CreateBookingPayload), never the bare entity type and never a naked scalar like Boolean. Mutation field names are camelCase verbs: createBooking, cancelReservation.
@deprecated, don't delete them. To phase out a field or enumvalue that clients may still use, keep it in the schema and annotate it with the built-in @deprecated(reason: "...") directive; the reason string names the replacement. Never silently delete it, comment it out, or rename it in place.
BEFORE — snake_case fields, wrong scalars, no non-null (the base's reflexive default):
graphqltype blog_post { post_id: Integer created_at: Date view_count: Number }
AFTER — PascalCase type, camelCase fields, built-in + declared scalars, non-null id:
graphqlscalar DateTime type BlogPost { postId: ID! createdAt: DateTime! viewCount: Int! }
BEFORE — enum members in the wrong case:
graphqlenum Direction { north East southWest }
AFTER — SCREAMING_SNAKE_CASE members, PascalCase enum name:
graphqlenum Direction { NORTH EAST SOUTH_WEST }
BEFORE — a mutation with loose arguments returning the bare entity:
graphqltype Mutation { addProduct(name: String, price: Double, active: Bool): Product }
AFTER — input argument object, Int/Float/Boolean scalars, Payload result:
graphqlinput AddProductInput { name: String! price: Float! active: Boolean! } type AddProductPayload { product: Product! } type Mutation { addProduct(input: AddProductInput!): AddProductPayload! }
BEFORE — a retired field simply removed / commented out:
graphqltype Account { # username removed, use handle now handle: String! }
AFTER — kept and marked with the directive so existing clients keep working:
graphqltype Account { username: String! @deprecated(reason: "Use `handle` instead.") handle: String! }
Money/Decimal as a built-in; eithermodel as Int in the smallest currency unit (cents) or declare a custom scalar Decimal.
"awaiting refund" → AWAITING_REFUND, not AWAITINGREFUND or AwaitingRefund.
HttpEndpoint/ApiKey style and beconsistent — the type name is still Upper-first.
the scalar directly (id: ID!) but still returns a Payload/Response type.
@deprecated directive works on enum values too:LEGACY @deprecated(reason: "Use ACTIVE.").
type Photo implements Node { ... } (interfaces joined by&); union SearchResult = Photo | Article — both type names PascalCase.
user_id, created_at) into the schema.Int, Float, Boolean, ID, String and declare anything else as scalar.Integer, Number, Double, Bool, or an undeclared Date/DateTime.! and give the id ID!.input type named ...Input and return ...Payload.@deprecated(reason: "...").active/Active instead of ACTIVE.Integer/Number and decimals as Double/Decimal.Date/DateTime/JSON/URL as built-in scalars without a scalar declaration.Boolean or the bare entity from a mutation instead of a Payload type.Input object.@deprecated-annotating the old one.Int/Float/String/Boolean/ID used as built-ins; everything else is a declared scalar.!; primary id is ID!....Input; result is a ...Payload/...Response type.@deprecated(reason: "...").| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-12 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-09 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-11 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-05 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-08 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-06 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-04 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-07 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-02 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-01 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-10 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-03 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-22 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-15 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-21 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-13 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-14 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-20 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-16 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-18 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-17 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-19 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 22 cases were attempted. The headline lift of +18 percentage points is the difference between those two pass rates over the 22 comparable cases.
The per-case answers from this run were removed by the retention sweep, so the case table below shows the verdicts without the text either arm produced. The counts above were recorded at the time and are unaffected. Answers are now kept for 180 days.
| Model | Method | Date | Lift |
|---|---|---|---|
| gemini-3.5-flash | verified | 7/9/2026 | +13% |
Other measured skills in the registry, with their headline benchmark lift.