diff --git a/.agent/ARCHITECTURE.md b/.agent/ARCHITECTURE.md index 99ca60a1b..b06314e41 100644 --- a/.agent/ARCHITECTURE.md +++ b/.agent/ARCHITECTURE.md @@ -9,7 +9,7 @@ Antigravity Kit is a modular system consisting of: - **20 Specialist Agents** - Role-based AI personas -- **36 Skills** - Domain-specific knowledge modules +- **37 Skills** - Domain-specific knowledge modules - **11 Workflows** - Slash command procedures --- @@ -37,7 +37,7 @@ Specialist AI personas for different domains. | `orchestrator` | Multi-agent coordination | parallel-agents, behavioral-modes | | `project-planner` | Discovery, task planning | brainstorming, plan-writing, architecture | | `frontend-specialist` | Web UI/UX | frontend-design, react-best-practices, tailwind-patterns | -| `backend-specialist` | API, business logic | api-patterns, nodejs-best-practices, database-design | +| `backend-specialist` | API, business logic | api-patterns, nodejs-best-practices, go-pro, database-design | | `database-architect` | Schema, SQL | database-design, prisma-expert | | `mobile-developer` | iOS, Android, RN | mobile-design | | `game-developer` | Game logic, mechanics | game-development | @@ -57,7 +57,7 @@ Specialist AI personas for different domains. --- -## 🧩 Skills (36) +## 🧩 Skills (37) Modular knowledge domains that agents can load on-demand. based on task context. @@ -79,6 +79,7 @@ Modular knowledge domains that agents can load on-demand. based on task context. | `nestjs-expert` | NestJS modules, DI, decorators | | `nodejs-best-practices` | Node.js async, modules | | `python-patterns` | Python standards, FastAPI | +| `go-pro` | Go idioms, concurrency, clean arch | ### Database @@ -267,7 +268,7 @@ For details, see [scripts/README.md](scripts/README.md) | Metric | Value | | ------------------- | ----------------------------- | | **Total Agents** | 20 | -| **Total Skills** | 36 | +| **Total Skills** | 37 | | **Total Workflows** | 11 | | **Total Scripts** | 2 (master) + 18 (skill-level) | | **Coverage** | ~90% web/mobile development | diff --git a/.agent/agents/backend-specialist.md b/.agent/agents/backend-specialist.md index ad306ef7a..56624b4e5 100644 --- a/.agent/agents/backend-specialist.md +++ b/.agent/agents/backend-specialist.md @@ -3,7 +3,7 @@ name: backend-specialist description: Expert backend architect for Node.js, Python, and modern serverless/edge systems. Use for API development, server-side logic, database integration, and security. Triggers on backend, server, api, endpoint, database, auth. tools: Read, Grep, Glob, Bash, Edit, Write model: inherit -skills: clean-code, nodejs-best-practices, python-patterns, api-patterns, database-design, mcp-builder, lint-and-validate, powershell-windows, bash-linux, rust-pro +skills: clean-code, nodejs-best-practices, python-patterns, go-pro, api-patterns, database-design, mcp-builder, lint-and-validate, powershell-windows, bash-linux, rust-pro --- # Backend Development Architect diff --git a/.agent/skills/go-pro/SKILL.md b/.agent/skills/go-pro/SKILL.md new file mode 100644 index 000000000..2ce3cdc9b --- /dev/null +++ b/.agent/skills/go-pro/SKILL.md @@ -0,0 +1,295 @@ +--- +name: go-pro +description: Go development principles and decision-making. Idiomatic patterns, concurrency, clean architecture, project structure, testing, and performance. Teaches thinking, not copying. +allowed-tools: Read, Write, Edit, Glob, Grep +--- + +# Go Pro + +> Go development principles and decision-making for 2025. +> **Learn to THINK like a Go developer, not memorize syntax.** + +--- + +## ⚠️ How to Use This Skill + +This skill teaches **decision-making principles**, not fixed code to copy. + +- ASK user for framework/library preference when unclear +- Choose pattern based on PROJECT CONTEXT (scale, team, lifetime) +- Standard Library firstβ€”add dependencies only when justified + +### πŸ“ Deep-Dive References + +Load these **only when the specific topic is relevant** to the user's request: + +| Reference | When to Load | +|-----------|------| +| `references/concurrency.md` | Goroutines, channels, errgroup, context patterns | +| `references/frameworks.md` | Framework selection (net/http vs Chi vs Gin vs Fiber) | +| `references/database.md` | ORM/driver selection, sqlc, migrations, connection pooling | +| `references/testing.md` | Table-driven tests, benchmarks, fuzz, mocking | +| `references/performance.md` | pprof, escape analysis, memory layout, GC tuning | +| `references/clean-architecture.md` | Layered architecture, DI, domain-driven structure | +| `references/api-design.md` | HTTP handlers, JSON, middleware, graceful shutdown | + +--- + +## 1. Go Philosophy (Non-Negotiable) + +### Core Tenets + +``` +"Simplicity is complicated." β€” Rob Pike + +β”œβ”€β”€ Clear is better than clever +β”œβ”€β”€ A little copying is better than a little dependency +β”œβ”€β”€ Don't panic (literallyβ€”avoid panic in library code) +β”œβ”€β”€ Accept interfaces, return structs +β”œβ”€β”€ Make the zero value useful +└── Errors are values, not exceptions +``` + +### Standard Library First + +``` +Before adding a dependency, ask: +β”œβ”€β”€ Can `net/http` handle this? (Go 1.22+ has pattern routing) +β”œβ”€β”€ Can `encoding/json` handle this? +β”œβ”€β”€ Can `database/sql` handle this? +β”œβ”€β”€ Can `log/slog` handle this? (Go 1.21+ structured logging) +└── Will this dependency survive 5 years? + +Add dependency ONLY when: +β”œβ”€β”€ Significant complexity reduction (e.g., sqlc, pgx) +β”œβ”€β”€ Non-trivial to implement (e.g., JWT validation) +└── Well-maintained with clear ownership +``` + +--- + +## 2. Project Structure + +### Decision Tree + +``` +How big is the project? +β”‚ +β”œβ”€β”€ Single binary / Script / CLI tool +β”‚ └── Flat layout +β”‚ β”œβ”€β”€ main.go +β”‚ β”œβ”€β”€ handler.go +β”‚ β”œβ”€β”€ store.go +β”‚ └── go.mod +β”‚ +β”œβ”€β”€ Medium service (1 team, 1 domain) +β”‚ └── Standard layout +β”‚ β”œβ”€β”€ cmd/server/main.go +β”‚ β”œβ”€β”€ internal/ +β”‚ β”‚ β”œβ”€β”€ handler/ +β”‚ β”‚ β”œβ”€β”€ service/ +β”‚ β”‚ β”œβ”€β”€ repository/ +β”‚ β”‚ └── model/ +β”‚ β”œβ”€β”€ pkg/ # Only if reuse is real +β”‚ └── go.mod +β”‚ +└── Large system (multi-domain, multi-team) + └── Domain-driven layout + β”œβ”€β”€ cmd/ + β”‚ β”œβ”€β”€ api/main.go + β”‚ └── worker/main.go + β”œβ”€β”€ internal/ + β”‚ β”œβ”€β”€ user/ # Domain package + β”‚ β”‚ β”œβ”€β”€ handler.go + β”‚ β”‚ β”œβ”€β”€ service.go + β”‚ β”‚ β”œβ”€β”€ repository.go + β”‚ β”‚ └── model.go + β”‚ β”œβ”€β”€ order/ # Domain package + β”‚ └── platform/ # Shared infra + β”‚ β”œβ”€β”€ database/ + β”‚ β”œβ”€β”€ logger/ + β”‚ └── middleware/ + └── go.mod +``` + +### Key Rules + +``` +β”œβ”€β”€ cmd/ β†’ Entry points ONLY (wire up, start server) +β”œβ”€β”€ internal/ β†’ Private application code (compiler-enforced) +β”œβ”€β”€ pkg/ β†’ Truly reusable libraries (use sparingly!) +β”‚ +β”œβ”€β”€ NEVER put business logic in cmd/ +β”œβ”€β”€ NEVER put HTTP concerns in service layer +β”œβ”€β”€ NEVER import internal/ from another module +└── Keep main.go thin (< 50 lines ideally) +``` + +--- + +## 3. Error Handling + +### Idiomatic Error Handling + +``` +Core patterns: +β”œβ”€β”€ if err != nil { return fmt.Errorf("doing X: %w", err) } +β”œβ”€β”€ Wrap errors with context using %w verb +β”œβ”€β”€ Use errors.Is() for sentinel error comparison +β”œβ”€β”€ Use errors.As() for type assertion on errors +β”œβ”€β”€ Return errors, don't panic (except truly unrecoverable) +└── Handle errors at the right level (don't swallow!) + +Error wrapping chain: +β”œβ”€β”€ Repository: fmt.Errorf("query user %d: %w", id, err) +β”œβ”€β”€ Service: fmt.Errorf("get user profile: %w", err) +β”œβ”€β”€ Handler: Log full error, return sanitized HTTP error +└── Client sees: {"error": "user not found"} (no internals!) +``` + +### Custom Error Types + +``` +When to create custom errors: +β”œβ”€β”€ Need to carry structured data (error code, field name) +β”œβ”€β”€ Need to distinguish error categories (NotFound, Conflict) +β”œβ”€β”€ Need to map to HTTP status codes +└── Shared across multiple packages + +When sentinel errors are enough: +β”œβ”€β”€ Simple "not found" / "already exists" cases +β”œβ”€β”€ Single package usage +└── No extra data needed +``` + +### Error Design Principles + +``` +β”œβ”€β”€ Errors should be opaque to callers (use Is/As, not string matching) +β”œβ”€β”€ Package-level sentinel: var ErrNotFound = errors.New("not found") +β”œβ”€β”€ Don't log AND return the same error (pick one per layer) +β”œβ”€β”€ Handler layer: log + return HTTP response +β”œβ”€β”€ Service layer: wrap + return +└── Repository layer: wrap + return +``` + +--- + +## 4. Interface Design + +### Core Principles + +``` +"The bigger the interface, the weaker the abstraction." β€” Rob Pike + +β”œβ”€β”€ Accept interfaces, return concrete types +β”œβ”€β”€ Define interfaces where they are USED, not implemented +β”œβ”€β”€ Keep interfaces small (1-3 methods ideal) +β”œβ”€β”€ Use implicit satisfaction (no "implements" keyword needed) +└── io.Reader / io.Writer are the gold standard + +Interface location: +β”œβ”€β”€ Consumer package defines the interface +β”œβ”€β”€ Producer package returns concrete struct +β”œβ”€β”€ This allows testing without mocks of the whole world +└── Example: service/ defines Repository interface, + repository/ returns *PostgresRepo struct +``` + +--- + +## 5. Logging & Observability + +### Structured Logging (Go 1.21+) + +``` +Use log/slog (stdlib): +β”œβ”€β”€ slog.Info("user created", "user_id", id, "email", email) +β”œβ”€β”€ Structured key-value pairs +β”œβ”€β”€ JSON output for production +β”œβ”€β”€ Text output for development +β”œβ”€β”€ Create child loggers with With() +└── No need for zerolog/zap unless specific features needed + +Logging levels: +β”œβ”€β”€ Debug β†’ Development diagnostics +β”œβ”€β”€ Info β†’ Normal operations +β”œβ”€β”€ Warn β†’ Recoverable issues +β”œβ”€β”€ Error β†’ Failures requiring attention +└── NEVER log sensitive data (passwords, tokens, PII) +``` + +--- + +## 6. Go Modules & Dependencies + +``` +β”œβ”€β”€ go mod init β†’ Start new module +β”œβ”€β”€ go mod tidy β†’ Clean up go.mod/go.sum +β”œβ”€β”€ go mod vendor β†’ Vendor dependencies (optional) +β”œβ”€β”€ go mod verify β†’ Verify integrity +β”‚ +β”œβ”€β”€ Pin major versions in go.mod +β”œβ”€β”€ Review go.sum changes in code review +β”œβ”€β”€ Use govulncheck for vulnerability scanning +β”œβ”€β”€ Prefer fewer, well-maintained dependencies +└── Check license compatibility +``` + +### Build & Release + +``` +β”œβ”€β”€ go build -ldflags "-s -w" β†’ Strip debug for smaller binary +β”œβ”€β”€ CGO_ENABLED=0 β†’ Static binary (no C dependencies) +β”œβ”€β”€ Use multi-stage Docker builds +β”œβ”€β”€ Cross-compile: GOOS=linux GOARCH=amd64 go build +└── Use goreleaser for automated releases +``` + +--- + +## 7. Anti-Patterns to Avoid + +### ❌ DON'T: +- Use `init()` for complex initialization (hard to test, surprising) +- Use `panic` in library code (return errors instead) +- Ignore errors with `_ = someFunc()` without explicit comment +- Use global mutable state (use dependency injection) +- Use `interface{}` / `any` when generics (Go 1.18+) work better +- Import from another project's `internal/` package +- Use Gin/Fiber for simple APIs where `net/http` suffices +- Store `context.Context` in struct fields +- Start goroutines without lifecycle management +- Use `sync.Mutex` when a channel is more appropriate + +### βœ… DO: +- Choose framework based on actual project needs +- Write table-driven tests for all business logic +- Use `context.Context` for cancellation and timeouts +- Profile before optimizing +- Keep interfaces small (1-3 methods) +- Use `errgroup` for concurrent operations +- Run `go vet`, `staticcheck`, `golangci-lint` in CI +- Use `sqlc` or `pgx` for database interactions +- Document exported functions and types +- Use `go generate` for code generation workflows + +--- + +## 8. Decision Checklist + +Before implementing: + +- [ ] **Asked user about framework preference?** +- [ ] **Chosen net/http vs framework for THIS context?** +- [ ] **Decided project structure scale?** (flat / standard / domain-driven) +- [ ] **Planned error handling strategy?** (sentinel / custom types / wrapping) +- [ ] **Identified concurrency needs?** (goroutines, channels, errgroup) +- [ ] **Chosen database approach?** (raw SQL, sqlc, GORM) +- [ ] **Planned testing strategy?** (table-driven, integration, benchmarks) +- [ ] **Considered clean architecture necessity?** (skip if simple CRUD) +- [ ] **Set up linting?** (golangci-lint with project config) + +--- + +> **Remember**: Go's power is in its simplicity. Don't fight the languageβ€”embrace `if err != nil`, small interfaces, explicit code, and the standard library. The best Go code looks boringβ€”and that's the point. diff --git a/.agent/skills/go-pro/references/api-design.md b/.agent/skills/go-pro/references/api-design.md new file mode 100644 index 000000000..0804abbc4 --- /dev/null +++ b/.agent/skills/go-pro/references/api-design.md @@ -0,0 +1,73 @@ +# API Design Principles + +> Deep-dive reference for Go HTTP API design. Load when user builds REST APIs, middleware, or JSON handlers. + +## HTTP Handler Patterns + +``` +Go 1.22+ ServeMux patterns: +β”œβ”€β”€ mux.HandleFunc("GET /users/{id}", handler.GetUser) +β”œβ”€β”€ mux.HandleFunc("POST /users", handler.CreateUser) +β”œβ”€β”€ Method + path in one string +└── Path parameters via r.PathValue("id") + +Middleware chain: +β”œβ”€β”€ func Middleware(next http.Handler) http.Handler +β”œβ”€β”€ Compose: Logger(Auth(RateLimit(handler))) +β”œβ”€β”€ Use for: logging, auth, CORS, recovery, metrics +└── Keep middleware focused (single responsibility) +``` + +## JSON Handling + +``` +Encoding/Decoding: +β”œβ”€β”€ Use json.NewDecoder(r.Body) for requests (streaming) +β”œβ”€β”€ Use json.NewEncoder(w) for responses +β”œβ”€β”€ Define struct tags: `json:"field_name,omitempty"` +β”œβ”€β”€ Use json.RawMessage for deferred parsing +β”œβ”€β”€ Limit request body size: http.MaxBytesReader +└── Set Content-Type header: "application/json" + +Validation: +β”œβ”€β”€ Validate after decoding, not during +β”œβ”€β”€ Use struct tags + validator package for complex rules +β”œβ”€β”€ Return 422 for validation errors with field-level details +└── Sanitize output (never expose internal struct fields) +``` + +## Response Format + +``` +Consistent API response: +β”œβ”€β”€ Success: { "data": {...} } +β”œβ”€β”€ Error: { "error": { "code": "NOT_FOUND", "message": "..." } } +β”œβ”€β”€ List: { "data": [...], "pagination": { "total": N, "page": 1 } } +β”‚ +β”œβ”€β”€ Always return JSON (even for errors) +β”œβ”€β”€ Use appropriate HTTP status codes +└── Include request ID in response headers +``` + +## Error Response Mapping + +| Domain Error | HTTP Status | Error Code | +|-------------|-------------|------------| +| Not found | 404 | `NOT_FOUND` | +| Validation failed | 422 | `VALIDATION_ERROR` | +| Already exists | 409 | `CONFLICT` | +| Unauthorized | 401 | `UNAUTHORIZED` | +| Forbidden | 403 | `FORBIDDEN` | +| Internal error | 500 | `INTERNAL_ERROR` | + +## Graceful Shutdown + +``` +Production servers must handle shutdown: +β”œβ”€β”€ Listen for os.Signal (SIGINT, SIGTERM) +β”œβ”€β”€ Call server.Shutdown(ctx) with timeout +β”œβ”€β”€ Finish in-flight requests +β”œβ”€β”€ Close database connections +β”œβ”€β”€ Flush logs +└── Exit cleanly +``` diff --git a/.agent/skills/go-pro/references/clean-architecture.md b/.agent/skills/go-pro/references/clean-architecture.md new file mode 100644 index 000000000..23a47f0c3 --- /dev/null +++ b/.agent/skills/go-pro/references/clean-architecture.md @@ -0,0 +1,79 @@ +# Clean Architecture in Go + +> Deep-dive reference for layered architecture and dependency injection in Go. Load when user designs service structure or needs DI patterns. + +## Layer Separation + +``` +Request Flow: +β”‚ +β”œβ”€β”€ Handler (Transport Layer) +β”‚ β”œβ”€β”€ HTTP/gRPC specifics +β”‚ β”œβ”€β”€ Parse request, validate input +β”‚ β”œβ”€β”€ Call service method +β”‚ └── Format response +β”‚ +β”œβ”€β”€ Service (Business Logic Layer) +β”‚ β”œβ”€β”€ Pure business rules +β”‚ β”œβ”€β”€ Depends on repository INTERFACES +β”‚ β”œβ”€β”€ No HTTP, no SQL +β”‚ └── Testable in isolation +β”‚ +β”œβ”€β”€ Repository (Data Access Layer) +β”‚ β”œβ”€β”€ Database queries +β”‚ β”œβ”€β”€ Implements repository interface +β”‚ β”œβ”€β”€ No business logic +β”‚ └── Returns domain models +β”‚ +└── Model (Domain Layer) + β”œβ”€β”€ Structs representing business entities + β”œβ”€β”€ No dependencies on other layers + └── Validation methods optional +``` + +## Dependency Injection + +``` +DI in Go (no magic, no framework needed): +β”œβ”€β”€ Constructor injection via New* functions +β”‚ func NewUserService(repo UserRepository) *UserService +β”‚ +β”œβ”€β”€ Wire up in cmd/main.go: +β”‚ db := database.Connect(cfg) +β”‚ userRepo := postgres.NewUserRepository(db) +β”‚ userService := service.NewUserService(userRepo) +β”‚ userHandler := handler.NewUserHandler(userService) +β”‚ +β”œβ”€β”€ For large projects, consider google/wire +β”‚ (compile-time DI code generation) +β”‚ +└── AVOID runtime DI containers (not idiomatic Go) +``` + +## When Clean Architecture is Overkill + +``` +Skip full layering when: +β”œβ”€β”€ Simple CRUD with < 5 entities +β”œβ”€β”€ CLI tools or scripts +β”œβ”€β”€ Prototypes / POCs +└── Single-person, short-lived projects + +Use full layering when: +β”œβ”€β”€ Multiple developers +β”œβ”€β”€ Complex business rules +β”œβ”€β”€ Long-lived project (> 1 year) +β”œβ”€β”€ Need to swap infrastructure +└── Extensive testing required +``` + +## Directory Mapping + +``` +Clean architecture β†’ Go project: +β”œβ”€β”€ Domain/Model β†’ internal/domain/ or internal/model/ +β”œβ”€β”€ Use Cases β†’ internal/service/ +β”œβ”€β”€ Interfaces β†’ internal/handler/ (HTTP), internal/grpc/ (gRPC) +β”œβ”€β”€ Infrastructure β†’ internal/repository/, internal/platform/ +└── Entry point β†’ cmd/server/main.go (wiring) +``` diff --git a/.agent/skills/go-pro/references/concurrency.md b/.agent/skills/go-pro/references/concurrency.md new file mode 100644 index 000000000..68c4baf2f --- /dev/null +++ b/.agent/skills/go-pro/references/concurrency.md @@ -0,0 +1,74 @@ +# Concurrency Patterns + +> Deep-dive reference for Go concurrency. Load when user works with goroutines, channels, or parallel processing. + +## When to Use What + +| Pattern | Use When | +|---------|----------| +| `goroutine + channel` | Fan-out/fan-in, pipelines | +| `sync.WaitGroup` | Wait for N goroutines to complete | +| `errgroup.Group` | Wait + collect first error + cancel others | +| `sync.Mutex/RWMutex` | Protect shared state | +| `sync.Once` | One-time initialization | +| `context.Context` | Cancellation, timeout, request-scoped values | + +## The Golden Rules + +``` +Concurrency rules: +β”œβ”€β”€ Always pass context.Context as first parameter +β”œβ”€β”€ Never start a goroutine without knowing how it will stop +β”œβ”€β”€ Use errgroup for concurrent operations that can fail +β”œβ”€β”€ Prefer channels for communication, mutexes for state +β”œβ”€β”€ Don't communicate by sharing memoryβ€”share memory by communicating +β”œβ”€β”€ Always handle context cancellation +└── Use sync.Pool for frequently allocated objects (measure first!) + +Context propagation: +β”œβ”€β”€ Accept ctx in every function that does I/O +β”œβ”€β”€ Pass ctx to downstream calls +β”œβ”€β”€ Check ctx.Err() in long loops +β”œβ”€β”€ Use context.WithTimeout for external calls +└── NEVER store context in a struct +``` + +## Goroutine Lifecycle + +``` +ALWAYS ensure goroutine cleanup: +β”œβ”€β”€ Use context for cancellation +β”œβ”€β”€ Use done channels for signaling +β”œβ”€β”€ Defer cleanup in goroutines +β”œβ”€β”€ Prevent goroutine leaks +└── Log goroutine lifecycle in debug mode +``` + +## Common Patterns + +### Fan-Out / Fan-In +``` +Use when: Processing N items concurrently, collecting results +β”œβ”€β”€ Spawn N goroutines (fan-out) +β”œβ”€β”€ Collect results via channel (fan-in) +β”œβ”€β”€ Use errgroup to handle errors +└── Limit concurrency with semaphore channel +``` + +### Pipeline +``` +Use when: Multi-stage data processing +β”œβ”€β”€ Each stage: goroutine reading from input channel +β”œβ”€β”€ Process β†’ send to output channel +β”œβ”€β”€ Close output channel when input is exhausted +└── Cancel pipeline via context +``` + +### Worker Pool +``` +Use when: Rate-limiting concurrent work +β”œβ”€β”€ Fixed number of goroutines reading from job channel +β”œβ”€β”€ Results sent to result channel +β”œβ”€β”€ Backpressure via buffered channels +└── Graceful shutdown via context cancellation +``` diff --git a/.agent/skills/go-pro/references/database.md b/.agent/skills/go-pro/references/database.md new file mode 100644 index 000000000..7c58ddac0 --- /dev/null +++ b/.agent/skills/go-pro/references/database.md @@ -0,0 +1,58 @@ +# Database Patterns + +> Deep-dive reference for Go database access. Load when user works with SQL, ORM, or database design. + +## ORM/Driver Selection + +| Tool | Best For | +|------|----------| +| `database/sql` + raw SQL | Full control, simple queries | +| `sqlc` | Type-safe SQL β†’ Go code generation | +| `pgx` | PostgreSQL-specific features, performance | +| `GORM` | Rapid prototyping, complex relations | +| `Bun` | Modern ORM, good performance | +| `ent` | Graph-based schema, code generation | + +## Database Principles + +``` +β”œβ”€β”€ Use connection pooling (sql.DB handles this) +β”œβ”€β”€ Always use context-aware queries (QueryContext, ExecContext) +β”œβ”€β”€ Use prepared statements for repeated queries +β”œβ”€β”€ Close rows immediately: defer rows.Close() +β”œβ”€β”€ Scan into structs, not individual variables +β”œβ”€β”€ Use transactions for multi-step operations +β”œβ”€β”€ Set reasonable timeouts via context +└── Monitor connection pool metrics + +sqlc recommendation (for most projects): +β”œβ”€β”€ Write SQL β†’ Generate type-safe Go code +β”œβ”€β”€ No runtime reflection +β”œβ”€β”€ Catches SQL errors at compile time +β”œβ”€β”€ Works with PostgreSQL, MySQL, SQLite +└── Pairs perfectly with pgx driver +``` + +## Migration Strategy + +``` +β”œβ”€β”€ golang-migrate/migrate β†’ SQL-based, simple +β”œβ”€β”€ goose β†’ SQL or Go-based +β”œβ”€β”€ atlas β†’ Declarative, modern +β”‚ +β”œβ”€β”€ ALWAYS use versioned migrations +β”œβ”€β”€ NEVER modify existing migration files +β”œβ”€β”€ Test migrations up AND down +└── Run migrations separately from app startup +``` + +## Connection Pool Tuning + +``` +sql.DB configuration: +β”œβ”€β”€ SetMaxOpenConns() β†’ Match your DB max connections +β”œβ”€β”€ SetMaxIdleConns() β†’ ~25% of max open +β”œβ”€β”€ SetConnMaxLifetime() β†’ 5-15 minutes +β”œβ”€β”€ SetConnMaxIdleTime() β†’ 1-3 minutes +└── Monitor with db.Stats() +``` diff --git a/.agent/skills/go-pro/references/frameworks.md b/.agent/skills/go-pro/references/frameworks.md new file mode 100644 index 000000000..11f5a4953 --- /dev/null +++ b/.agent/skills/go-pro/references/frameworks.md @@ -0,0 +1,67 @@ +# Framework Selection (2025) + +> Deep-dive reference for Go web framework selection. Load when user needs to choose or compare frameworks. + +## Decision Tree + +``` +What are you building? +β”‚ +β”œβ”€β”€ API with simple routing (Go 1.22+) +β”‚ └── net/http (ServeMux now supports patterns!) +β”‚ +β”œβ”€β”€ REST API with middleware needs +β”‚ └── Chi (lightweight, net/http compatible) +β”‚ +β”œβ”€β”€ High-performance API / Microservice +β”‚ └── Gin or Echo (battle-tested, fast) +β”‚ +β”œβ”€β”€ Maximum performance (benchmarks matter) +β”‚ └── Fiber (fasthttp-based, Express-like API) +β”‚ +β”œβ”€β”€ gRPC service +β”‚ └── google.golang.org/grpc + protobuf +β”‚ +└── CLI tool + └── cobra + viper +``` + +## Comparison Principles + +| Factor | net/http | Chi | Gin | Fiber | +|--------|----------|-----|-----|-------| +| **Best for** | Simple APIs, Go 1.22+ | Composable middleware | Production REST APIs | Max throughput | +| **Dependencies** | Zero | Minimal | Moderate | fasthttp (non-std) | +| **net/http compatible** | βœ… | βœ… | ❌ (own context) | ❌ (fasthttp) | +| **Middleware ecosystem** | Manual | Rich, composable | Rich, built-in | Growing | +| **Learning curve** | Low | Low | Low | Low | + +## Selection Questions to Ask: +1. Does the project need to stay net/http compatible? +2. Is raw throughput critical (>100K req/s)? +3. Does the team already know a specific framework? +4. How important is the middleware ecosystem? + +> **Default recommendation for new projects**: `net/http` (Go 1.22+) or `Chi` for composability. Only reach for Gin/Fiber when justified. + +## Go 1.22+ ServeMux Patterns + +``` +New routing capabilities: +β”œβ”€β”€ mux.HandleFunc("GET /users/{id}", handler.GetUser) +β”œβ”€β”€ mux.HandleFunc("POST /users", handler.CreateUser) +β”œβ”€β”€ Method + path in one string +β”œβ”€β”€ Path parameters via r.PathValue("id") +β”œβ”€β”€ Precedence rules: more specific patterns win +└── No need for Chi/Gorilla for simple routing anymore +``` + +## Middleware Pattern + +``` +Standard middleware signature: +β”œβ”€β”€ func Middleware(next http.Handler) http.Handler +β”œβ”€β”€ Compose: Logger(Auth(RateLimit(handler))) +β”œβ”€β”€ Use for: logging, auth, CORS, recovery, metrics +└── Keep middleware focused (single responsibility) +``` diff --git a/.agent/skills/go-pro/references/performance.md b/.agent/skills/go-pro/references/performance.md new file mode 100644 index 000000000..5b8291d25 --- /dev/null +++ b/.agent/skills/go-pro/references/performance.md @@ -0,0 +1,69 @@ +# Performance + +> Deep-dive reference for Go performance profiling and optimization. Load when user needs to profile or optimize Go code. + +## Profiling First (Measure, Don't Guess) + +``` +Tools: +β”œβ”€β”€ go tool pprof β†’ CPU, memory, goroutine profiling +β”œβ”€β”€ go test -bench β†’ Micro-benchmarks +β”œβ”€β”€ go test -benchmem β†’ Memory allocation counts +β”œβ”€β”€ runtime/trace β†’ Execution tracer +β”œβ”€β”€ expvar / metrics β†’ Runtime metrics endpoint +└── go build -gcflags="-m" β†’ Escape analysis + +Common optimizations (ONLY after profiling): +β”œβ”€β”€ Reduce allocations (sync.Pool, pre-allocate slices) +β”œβ”€β”€ Use strings.Builder for string concatenation +β”œβ”€β”€ Avoid interface{}/any in hot paths +β”œβ”€β”€ Use struct embedding to reduce pointer chasing +β”œβ”€β”€ Pre-size maps and slices: make([]T, 0, expectedCap) +β”œβ”€β”€ Use io.Reader/Writer for streaming (avoid loading all into memory) +└── Consider msgpack/protobuf over JSON for internal services +``` + +## Memory Layout + +``` +Struct field ordering matters: +β”œβ”€β”€ Group same-size fields together +β”œβ”€β”€ Larger fields first, smaller fields last +β”œβ”€β”€ Reduces padding, saves memory +β”œβ”€β”€ Use fieldalignment linter to detect issues +└── ONLY matters at scale (millions of structs) +``` + +## Escape Analysis + +``` +Understanding heap vs stack: +β”œβ”€β”€ go build -gcflags="-m" shows escape decisions +β”œβ”€β”€ Variables that escape to heap = allocation = GC pressure +β”œβ”€β”€ Returning pointer to local variable β†’ escapes +β”œβ”€β”€ Interface conversion β†’ may escape +β”œβ”€β”€ Closures capturing variables β†’ may escape +└── Reducing escapes = reducing GC pauses +``` + +## Benchmark Patterns + +``` +Writing benchmarks: +β”œβ”€β”€ func BenchmarkXxx(b *testing.B) { for i := 0; i < b.N; i++ { ... } } +β”œβ”€β”€ Use b.ResetTimer() after setup +β”œβ”€β”€ Use b.ReportAllocs() for allocation tracking +β”œβ”€β”€ Compare with benchstat for statistical significance +β”œβ”€β”€ Run: go test -bench=. -benchmem -count=10 +└── Profile: go test -bench=. -cpuprofile=cpu.prof +``` + +## GC Tuning + +``` +β”œβ”€β”€ GOGC=100 (default) β€” collect when heap doubles +β”œβ”€β”€ GOMEMLIMIT (Go 1.19+) β€” set soft memory limit +β”œβ”€β”€ Monitor with runtime.ReadMemStats() +β”œβ”€β”€ Reduce allocations > tuning GC +└── Use sync.Pool for frequently allocated objects +``` diff --git a/.agent/skills/go-pro/references/testing.md b/.agent/skills/go-pro/references/testing.md new file mode 100644 index 000000000..275519d1a --- /dev/null +++ b/.agent/skills/go-pro/references/testing.md @@ -0,0 +1,67 @@ +# Testing + +> Deep-dive reference for Go testing patterns. Load when user writes tests, benchmarks, or fuzz tests. + +## Table-Driven Tests (Idiomatic Go) + +``` +Pattern: +β”œβ”€β”€ Define test cases as slice of structs +β”œβ”€β”€ Loop through cases with t.Run(name, func) +β”œβ”€β”€ Each case: input β†’ expected output +β”œβ”€β”€ Name each case descriptively +β”œβ”€β”€ Add edge cases and error cases +└── Use t.Parallel() when tests are independent + +Benefits: +β”œβ”€β”€ Easy to add new cases +β”œβ”€β”€ Clear what's being tested +β”œβ”€β”€ Consistent structure across codebase +└── Great for debugging (run single case) +``` + +## Testing Strategy + +| Type | Purpose | Tools | +|------|---------|-------| +| **Unit** | Business logic, pure functions | `testing` (stdlib) | +| **Integration** | Database, external services | `testcontainers-go` | +| **Benchmark** | Performance measurement | `testing.B` | +| **Fuzz** | Input discovery (Go 1.18+) | `testing.F` | +| **E2E** | Full API workflows | `net/http/httptest` | + +## Testing Principles + +``` +β”œβ”€β”€ Use stdlib testing package first +β”œβ”€β”€ testify is OK for assertions (require/assert) +β”œβ”€β”€ Use httptest.NewServer for HTTP tests +β”œβ”€β”€ Use t.TempDir() for file-based tests +β”œβ”€β”€ Use testcontainers for real database tests +β”œβ”€β”€ Mock at interface boundaries only +β”œβ”€β”€ Benchmark before optimizing: go test -bench=. +β”œβ”€β”€ Fuzz test parsers and validators: go test -fuzz=. +└── Use t.Helper() in test helper functions +``` + +## Test Organization + +``` +Where to put tests: +β”œβ”€β”€ Unit tests: same package (foo_test.go) +β”œβ”€β”€ Black-box tests: package foo_test (external perspective) +β”œβ”€β”€ Integration tests: //go:build integration tag +β”œβ”€β”€ Test fixtures: testdata/ directory (auto-ignored by go build) +└── Test helpers: internal/testutil/ package +``` + +## Mocking Strategy + +``` +β”œβ”€β”€ Define interfaces at consumer side +β”œβ”€β”€ Generate mocks: mockgen, moq, or hand-written +β”œβ”€β”€ Prefer hand-written fakes for simple interfaces +β”œβ”€β”€ Use mockgen for complex interfaces (many methods) +β”œβ”€β”€ NEVER mock what you don't own (wrap external deps first) +└── Integration test > mocking when feasible +``` diff --git a/.agent/skills/intelligent-routing/SKILL.md b/.agent/skills/intelligent-routing/SKILL.md index 5c8814b00..4edd8ec4a 100644 --- a/.agent/skills/intelligent-routing/SKILL.md +++ b/.agent/skills/intelligent-routing/SKILL.md @@ -105,6 +105,7 @@ function analyzeRequest(userMessage) { | **Security** | auth, login, jwt, password, hash, token | `security-auditor` | | **Frontend** | component, react, vue, css, html, tailwind | `frontend-specialist` | | **Backend** | api, server, express, fastapi, node | `backend-specialist` | +| **Go/Golang** | go, golang, goroutine, gin, fiber, chi | `backend-specialist` | | **Mobile** | react native, flutter, ios, android, expo | `mobile-developer` | | **Database** | prisma, sql, mongodb, schema, migration | `database-architect` | | **Testing** | test, jest, vitest, playwright, cypress | `test-engineer` |