CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl-labs/separation-of-concerns

Enforce strict three-layer architecture: thin HTTP routes, pure service logic with domain errors, isolated data access with dependency injection.

94

1.08x
Quality

93%

Does it follow best practices?

Impact

97%

1.08x

Average score across 5 eval scenarios

SecuritybySnyk

Passed

No known issues

Overview
Quality
Evals
Security
Files

criteria.jsonevals/scenario-1/

{
  "context": "Tests whether the agent correctly separates error concerns: services throw typed domain errors (never HTTP errors), routes catch domain errors and map them to HTTP status codes, and error classes are framework-agnostic.",
  "type": "weighted_checklist",
  "checklist": [
    {
      "name": "Domain error file",
      "description": "A dedicated errors/domain.ts (or similarly named) file exists containing domain error class definitions, separate from route/service files",
      "max_score": 8
    },
    {
      "name": "Framework-agnostic errors",
      "description": "Domain error classes do NOT extend or import any HTTP framework types (e.g., no express, fastify, http imports in the errors file)",
      "max_score": 8
    },
    {
      "name": "Service throws typed errors",
      "description": "The service throws instances of typed domain error classes (e.g., ValidationError, BusinessRuleError, NotFoundError) — not generic Error with HTTP codes or status strings",
      "max_score": 10
    },
    {
      "name": "No HTTP in service",
      "description": "The service file does NOT import or reference any HTTP framework module, req, res, response, request, ctx, or context objects",
      "max_score": 10
    },
    {
      "name": "No status codes in service",
      "description": "The service does NOT set or return HTTP status codes (no references to 400, 404, 422, 500, or .status() calls)",
      "max_score": 8
    },
    {
      "name": "Route maps domain errors",
      "description": "The route handler contains explicit catch blocks (or equivalent) that map domain error types to specific HTTP status codes (e.g., ValidationError → 400, NotFoundError → 404, BusinessRuleError → 422)",
      "max_score": 10
    },
    {
      "name": "Route re-throws unexpected",
      "description": "The route handler re-throws (or passes to next()) errors that are NOT recognized domain errors, rather than swallowing them with a generic 500 response",
      "max_score": 8
    },
    {
      "name": "Route uses plain data",
      "description": "The route handler passes plain data objects (not req, res, or ctx) to the service function",
      "max_score": 8
    },
    {
      "name": "No SQL in service",
      "description": "The service file does NOT contain direct SQL queries or ORM query calls — it delegates to a repository/data access module",
      "max_score": 10
    },
    {
      "name": "Repo handles null",
      "description": "The repository/data access module returns null (not throws) when an item is not found, and the service layer decides whether to throw an error based on that",
      "max_score": 10
    },
    {
      "name": "Plan describes flow",
      "description": "plan.md describes error flow: service throws typed domain errors → route layer catches and maps to HTTP status",
      "max_score": 10
    }
  ]
}

evals

scenario-1

criteria.json

task.md

tile.json