CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl-labs/go-project-structure

Go project structure -- cmd/internal layout, handler/service/repository layers, Makefile, config from environment, domain error types, test placement, dependency injection

90

1.02x
Quality

84%

Does it follow best practices?

Impact

100%

1.02x

Average score across 5 eval scenarios

SecuritybySnyk

Passed

No known issues

Overview
Quality
Evals
Security
Files

criteria.jsonevals/scenario-3/

{
  "context": "Tests whether the agent scaffolds a Go payment microservice with proper cmd/internal layout, handler/service/repository layers, domain error types, config from environment, Makefile, test placement, and dependency injection.",
  "type": "weighted_checklist",
  "checklist": [
    {
      "name": "cmd/server/main.go entry point",
      "description": "main.go is in cmd/server/ (or cmd/<name>/) and contains dependency wiring and server startup only -- no HTTP handler logic or SQL queries",
      "max_score": 8
    },
    {
      "name": "internal/ directory used",
      "description": "Application packages are inside internal/ directory (internal/handler/, internal/service/, internal/repository/, etc.)",
      "max_score": 8
    },
    {
      "name": "Handler layer separated",
      "description": "HTTP handlers are in internal/handler/ package with a Handler struct, constructor, and route registration method. Handlers call service methods, not database queries directly.",
      "max_score": 7
    },
    {
      "name": "Service layer with interface",
      "description": "Business logic is in internal/service/ package. The service defines an interface for its repository dependency (e.g., PaymentRepository interface) rather than depending on concrete types.",
      "max_score": 8
    },
    {
      "name": "Repository layer separated",
      "description": "Database queries are in internal/repository/ (or internal/store/) package, separate from handlers and service logic",
      "max_score": 7
    },
    {
      "name": "Domain models in own package",
      "description": "Domain types (Payment, PaymentStatus, CreatePaymentRequest) are in internal/domain/ or internal/model/ package",
      "max_score": 6
    },
    {
      "name": "Domain error types",
      "description": "Domain error types (AppError, NotFoundError, ValidationError) are defined in the domain package with HTTP status codes, not scattered across handlers",
      "max_score": 7
    },
    {
      "name": "Config from environment",
      "description": "Configuration is in internal/config/ with a Config struct that loads from environment variables (os.Getenv or envconfig) with defaults -- not hardcoded values",
      "max_score": 7
    },
    {
      "name": "go.mod with module path",
      "description": "go.mod exists with a proper module path set",
      "max_score": 5
    },
    {
      "name": "Makefile with standard targets",
      "description": "Makefile exists with at least build, test, and run targets. Test target uses go test ./...",
      "max_score": 6
    },
    {
      "name": "Test files alongside source",
      "description": "At least one _test.go file exists in the same directory as its source code (e.g., internal/service/payments_test.go), NOT in a separate tests/ directory",
      "max_score": 7
    },
    {
      "name": "Table-driven tests",
      "description": "Tests use table-driven pattern with test case structs and t.Run() subtests",
      "max_score": 5
    },
    {
      "name": ".gitignore for Go",
      "description": ".gitignore exists and includes bin/, coverage.out or *.test, and .env",
      "max_score": 4
    },
    {
      "name": "Constructor-based DI in main.go",
      "description": "main.go wires dependencies using constructor functions (e.g., NewOrderRepo -> NewOrderService -> NewHandler), not global variables",
      "max_score": 6
    },
    {
      "name": "Graceful shutdown",
      "description": "main.go includes signal handling for graceful shutdown (os.Signal, syscall.SIGTERM)",
      "max_score": 4
    }
  ]
}

evals

tile.json