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

{
  "context": "Tests whether the agent correctly isolates data access into a separate repository layer that maps DB rows to domain objects and returns null for missing items, while keeping business logic exclusively in services and HTTP concerns in routes.",
  "type": "weighted_checklist",
  "checklist": [
    {
      "name": "Repository file exists",
      "description": "A dedicated repository or store file (e.g., repositories/bookRepo.ts or similar) exists that is separate from service and route files",
      "max_score": 8
    },
    {
      "name": "No SQL in service",
      "description": "The service file does NOT contain inline SQL queries, ORM query calls, or direct array/map lookups acting as a database — all data queries are delegated to the repository",
      "max_score": 10
    },
    {
      "name": "No SQL in routes",
      "description": "Route handler files do NOT contain SQL, ORM queries, or direct data store access",
      "max_score": 8
    },
    {
      "name": "Repo returns null for missing",
      "description": "The repository's find/lookup method returns null or undefined (not throws) when a book is not found — the service is the one that decides whether to throw",
      "max_score": 10
    },
    {
      "name": "Service decides on null",
      "description": "The service layer is the one that decides whether a null result from the repo is an error — e.g., throws NotFoundError when the repo returns null",
      "max_score": 10
    },
    {
      "name": "Repo maps to domain type",
      "description": "The repository contains an explicit mapping function or step that converts raw data (e.g., DB row, plain object) to a typed domain object (e.g., Book interface/type) — not just returning raw storage format",
      "max_score": 10
    },
    {
      "name": "No business logic in repo",
      "description": "The repository does NOT contain business rules (e.g., it does not check if a book is available before checkout — that check is in the service layer)",
      "max_score": 10
    },
    {
      "name": "Routes pass plain data",
      "description": "Route handlers extract data from req.body/req.params and pass plain objects or primitives to the service — not the req or res objects",
      "max_score": 8
    },
    {
      "name": "No HTTP in service",
      "description": "The service file does NOT import or reference req, res, response, request, ctx, or any HTTP framework module",
      "max_score": 8
    },
    {
      "name": "Route re-throws unexpected errors",
      "description": "The route handler re-throws (or passes to next()) errors that are NOT recognized domain errors, rather than catching all errors with a generic 500",
      "max_score": 8
    },
    {
      "name": "Types separated",
      "description": "A dedicated types file (types/book.ts or similar) exists defining the Book domain interface/type",
      "max_score": 5
    },
    {
      "name": "Architecture notes layers",
      "description": "architecture-notes.md describes all three layers (route, service, repository) and how data flows between them",
      "max_score": 5
    }
  ]
}

evals

tile.json