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-14/

{
  "context": "Tests whether the agent implements background jobs following the rails-background-jobs skill: passing IDs not objects, adding idempotency checks before side effects, using correct retry/discard strategies, keeping perform thin, and configuring the recurring schedule in recurring.yml.",
  "type": "weighted_checklist",
  "checklist": [
    {
      "name": "Pass ID not object",
      "description": "SendInvoiceReminderJob.perform_later is called with an invoice ID (integer/string), NOT an Invoice object",
      "max_score": 10
    },
    {
      "name": "Load record in perform",
      "description": "The job's perform method looks up the invoice via a finder (e.g. Invoice.find) using the passed ID, not from an instance variable or argument object",
      "max_score": 8
    },
    {
      "name": "Idempotency check present",
      "description": "SendInvoiceReminderJob checks whether the reminder was already sent (e.g. checks reminder_sent_at or a flag) BEFORE sending the email",
      "max_score": 12
    },
    {
      "name": "Side effect after guard",
      "description": "The mailer call (InvoiceMailer or similar) appears AFTER the idempotency guard, not before it",
      "max_score": 8
    },
    {
      "name": "retry_on with attempts",
      "description": "retry_on is used for at least one transient error class AND includes an explicit attempts: N limit (not open-ended)",
      "max_score": 10
    },
    {
      "name": "discard_on permanent error",
      "description": "discard_on is used for at least one permanent/non-retriable error (e.g. ActiveRecord::RecordNotFound)",
      "max_score": 8
    },
    {
      "name": "Thin perform — service delegation",
      "description": "SendInvoiceReminderJob delegates business logic to a service object or mailer rather than containing multi-step orchestration inline in perform",
      "max_score": 8
    },
    {
      "name": "Recurring in recurring.yml",
      "description": "config/recurring.yml exists and defines the nightly sweep job with a cron or schedule expression targeting 08:00 UTC",
      "max_score": 10
    },
    {
      "name": "Solid Queue adapter",
      "description": "The implementation uses Solid Queue as the queue adapter (referenced in config, gemfile, or process_log.md) — not Sidekiq or async",
      "max_score": 8
    },
    {
      "name": "Spec covers idempotency",
      "description": "SendInvoiceReminderJob spec includes a test case verifying that enqueueing the job twice does NOT send the email twice (second enqueue is a no-op)",
      "max_score": 10
    },
    {
      "name": "Spec written for job",
      "description": "Both spec files exist (send_invoice_reminder_job_spec.rb and nightly_overdue_invoice_sweep_job_spec.rb) with at least one describe/it block each",
      "max_score": 8
    }
  ]
}

README.md

tile.json