CtrlK
BlogDocsLog inGet started
Tessl Logo

igmarin/rails-agent-skills

Curated library of AI agent skills for Ruby on Rails development. Covers code review, architecture, security, testing (RSpec), engines, service objects, DDD patterns, and workflow automation.

98

1.38x
Quality

99%

Does it follow best practices?

Impact

98%

1.38x

Average score across 26 eval scenarios

SecuritybySnyk

Passed

No known issues

Overview
Quality
Evals
Security
Files

criteria.jsonevals/scenario-16/

{
  "context": "Tests whether the agent follows rails-graphql-best-practices: using dataloaders for association loads, applying field-level auth on sensitive fields, returning structured { result, errors } from mutations, disabling introspection in production, setting query depth/complexity limits, using dedicated resolver classes, connection types for paginated fields, and schema.execute in tests.",
  "type": "weighted_checklist",
  "checklist": [
    {
      "name": "Dataloader for association",
      "description": "ListResolver loads the buyer association through a dataloader (dataloader.with(...).load(...)) rather than calling object.buyer or object.buyer_id directly",
      "max_score": 10
    },
    {
      "name": "Field-level guard on sensitive field",
      "description": "The internal_notes field in Types::OrderType has its own field-level authorization guard (not just relying on type-level auth)",
      "max_score": 10
    },
    {
      "name": "No type-only auth for sensitive field",
      "description": "Types::OrderType does NOT rely solely on a class-level guard — internal_notes has a separate guard block or before_check",
      "max_score": 8
    },
    {
      "name": "Mutation returns errors array",
      "description": "Mutations::PlaceOrder defines a field :errors of array type (e.g. [String]) that is always present in the response",
      "max_score": 10
    },
    {
      "name": "Mutation no unhandled raise",
      "description": "Mutations::PlaceOrder does NOT raise unhandled exceptions to the caller — errors are caught and returned in the errors field",
      "max_score": 8
    },
    {
      "name": "Introspection disabled in production",
      "description": "AppSchema calls disable_introspection_entry_points (conditionally for production environment, or unconditionally)",
      "max_score": 10
    },
    {
      "name": "max_depth set",
      "description": "AppSchema sets max_depth with a numeric value",
      "max_score": 6
    },
    {
      "name": "max_complexity set",
      "description": "AppSchema sets max_complexity with a numeric value",
      "max_score": 6
    },
    {
      "name": "Dedicated resolver class",
      "description": "Orders list resolution is in a dedicated Resolvers::Orders::ListResolver class, not as an inline field block in QueryType",
      "max_score": 8
    },
    {
      "name": "Connection type for paginated list",
      "description": "The orders field (wherever it is defined) uses .connection_type (e.g. Types::OrderType.connection_type) rather than a plain array type",
      "max_score": 8
    },
    {
      "name": "schema.execute in specs",
      "description": "Both spec files use AppSchema.execute(...) to run queries/mutations — not controller dispatch or request specs via HTTP",
      "max_score": 8
    },
    {
      "name": "descriptions on fields",
      "description": "Types::OrderType includes description calls on at least 3 of its fields",
      "max_score": 8
    }
  ]
}

README.md

tile.json