wip: [01-stabilize] paused at task 1/1 - OCR Hallucination Immune logic via Semantic delta window and fret-isolation
This commit is contained in:
100
.agent/knowledge/everything_claude/examples/CLAUDE.md
Normal file
100
.agent/knowledge/everything_claude/examples/CLAUDE.md
Normal file
@@ -0,0 +1,100 @@
|
||||
# Example Project CLAUDE.md
|
||||
|
||||
This is an example project-level CLAUDE.md file. Place this in your project root.
|
||||
|
||||
## Project Overview
|
||||
|
||||
[Brief description of your project - what it does, tech stack]
|
||||
|
||||
## Critical Rules
|
||||
|
||||
### 1. Code Organization
|
||||
|
||||
- Many small files over few large files
|
||||
- High cohesion, low coupling
|
||||
- 200-400 lines typical, 800 max per file
|
||||
- Organize by feature/domain, not by type
|
||||
|
||||
### 2. Code Style
|
||||
|
||||
- No emojis in code, comments, or documentation
|
||||
- Immutability always - never mutate objects or arrays
|
||||
- No console.log in production code
|
||||
- Proper error handling with try/catch
|
||||
- Input validation with Zod or similar
|
||||
|
||||
### 3. Testing
|
||||
|
||||
- TDD: Write tests first
|
||||
- 80% minimum coverage
|
||||
- Unit tests for utilities
|
||||
- Integration tests for APIs
|
||||
- E2E tests for critical flows
|
||||
|
||||
### 4. Security
|
||||
|
||||
- No hardcoded secrets
|
||||
- Environment variables for sensitive data
|
||||
- Validate all user inputs
|
||||
- Parameterized queries only
|
||||
- CSRF protection enabled
|
||||
|
||||
## File Structure
|
||||
|
||||
```
|
||||
src/
|
||||
|-- app/ # Next.js app router
|
||||
|-- components/ # Reusable UI components
|
||||
|-- hooks/ # Custom React hooks
|
||||
|-- lib/ # Utility libraries
|
||||
|-- types/ # TypeScript definitions
|
||||
```
|
||||
|
||||
## Key Patterns
|
||||
|
||||
### API Response Format
|
||||
|
||||
```typescript
|
||||
interface ApiResponse<T> {
|
||||
success: boolean
|
||||
data?: T
|
||||
error?: string
|
||||
}
|
||||
```
|
||||
|
||||
### Error Handling
|
||||
|
||||
```typescript
|
||||
try {
|
||||
const result = await operation()
|
||||
return { success: true, data: result }
|
||||
} catch (error) {
|
||||
console.error('Operation failed:', error)
|
||||
return { success: false, error: 'User-friendly message' }
|
||||
}
|
||||
```
|
||||
|
||||
## Environment Variables
|
||||
|
||||
```bash
|
||||
# Required
|
||||
DATABASE_URL=
|
||||
API_KEY=
|
||||
|
||||
# Optional
|
||||
DEBUG=false
|
||||
```
|
||||
|
||||
## Available Commands
|
||||
|
||||
- `/tdd` - Test-driven development workflow
|
||||
- `/plan` - Create implementation plan
|
||||
- `/code-review` - Review code quality
|
||||
- `/build-fix` - Fix build errors
|
||||
|
||||
## Git Workflow
|
||||
|
||||
- Conventional commits: `feat:`, `fix:`, `refactor:`, `docs:`, `test:`
|
||||
- Never commit to main directly
|
||||
- PRs require review
|
||||
- All tests must pass before merge
|
||||
308
.agent/knowledge/everything_claude/examples/django-api-CLAUDE.md
Normal file
308
.agent/knowledge/everything_claude/examples/django-api-CLAUDE.md
Normal file
@@ -0,0 +1,308 @@
|
||||
# Django REST API — Project CLAUDE.md
|
||||
|
||||
> Real-world example for a Django REST Framework API with PostgreSQL and Celery.
|
||||
> Copy this to your project root and customize for your service.
|
||||
|
||||
## Project Overview
|
||||
|
||||
**Stack:** Python 3.12+, Django 5.x, Django REST Framework, PostgreSQL, Celery + Redis, pytest, Docker Compose
|
||||
|
||||
**Architecture:** Domain-driven design with apps per business domain. DRF for API layer, Celery for async tasks, pytest for testing. All endpoints return JSON — no template rendering.
|
||||
|
||||
## Critical Rules
|
||||
|
||||
### Python Conventions
|
||||
|
||||
- Type hints on all function signatures — use `from __future__ import annotations`
|
||||
- No `print()` statements — use `logging.getLogger(__name__)`
|
||||
- f-strings for string formatting, never `%` or `.format()`
|
||||
- Use `pathlib.Path` not `os.path` for file operations
|
||||
- Imports sorted with isort: stdlib, third-party, local (enforced by ruff)
|
||||
|
||||
### Database
|
||||
|
||||
- All queries use Django ORM — raw SQL only with `.raw()` and parameterized queries
|
||||
- Migrations committed to git — never use `--fake` in production
|
||||
- Use `select_related()` and `prefetch_related()` to prevent N+1 queries
|
||||
- All models must have `created_at` and `updated_at` auto-fields
|
||||
- Indexes on any field used in `filter()`, `order_by()`, or `WHERE` clauses
|
||||
|
||||
```python
|
||||
# BAD: N+1 query
|
||||
orders = Order.objects.all()
|
||||
for order in orders:
|
||||
print(order.customer.name) # hits DB for each order
|
||||
|
||||
# GOOD: Single query with join
|
||||
orders = Order.objects.select_related("customer").all()
|
||||
```
|
||||
|
||||
### Authentication
|
||||
|
||||
- JWT via `djangorestframework-simplejwt` — access token (15 min) + refresh token (7 days)
|
||||
- Permission classes on every view — never rely on default
|
||||
- Use `IsAuthenticated` as base, add custom permissions for object-level access
|
||||
- Token blacklisting enabled for logout
|
||||
|
||||
### Serializers
|
||||
|
||||
- Use `ModelSerializer` for simple CRUD, `Serializer` for complex validation
|
||||
- Separate read and write serializers when input/output shapes differ
|
||||
- Validate at serializer level, not in views — views should be thin
|
||||
|
||||
```python
|
||||
class CreateOrderSerializer(serializers.Serializer):
|
||||
product_id = serializers.UUIDField()
|
||||
quantity = serializers.IntegerField(min_value=1, max_value=100)
|
||||
|
||||
def validate_product_id(self, value):
|
||||
if not Product.objects.filter(id=value, active=True).exists():
|
||||
raise serializers.ValidationError("Product not found or inactive")
|
||||
return value
|
||||
|
||||
class OrderDetailSerializer(serializers.ModelSerializer):
|
||||
customer = CustomerSerializer(read_only=True)
|
||||
product = ProductSerializer(read_only=True)
|
||||
|
||||
class Meta:
|
||||
model = Order
|
||||
fields = ["id", "customer", "product", "quantity", "total", "status", "created_at"]
|
||||
```
|
||||
|
||||
### Error Handling
|
||||
|
||||
- Use DRF exception handler for consistent error responses
|
||||
- Custom exceptions for business logic in `core/exceptions.py`
|
||||
- Never expose internal error details to clients
|
||||
|
||||
```python
|
||||
# core/exceptions.py
|
||||
from rest_framework.exceptions import APIException
|
||||
|
||||
class InsufficientStockError(APIException):
|
||||
status_code = 409
|
||||
default_detail = "Insufficient stock for this order"
|
||||
default_code = "insufficient_stock"
|
||||
```
|
||||
|
||||
### Code Style
|
||||
|
||||
- No emojis in code or comments
|
||||
- Max line length: 120 characters (enforced by ruff)
|
||||
- Classes: PascalCase, functions/variables: snake_case, constants: UPPER_SNAKE_CASE
|
||||
- Views are thin — business logic lives in service functions or model methods
|
||||
|
||||
## File Structure
|
||||
|
||||
```
|
||||
config/
|
||||
settings/
|
||||
base.py # Shared settings
|
||||
local.py # Dev overrides (DEBUG=True)
|
||||
production.py # Production settings
|
||||
urls.py # Root URL config
|
||||
celery.py # Celery app configuration
|
||||
apps/
|
||||
accounts/ # User auth, registration, profile
|
||||
models.py
|
||||
serializers.py
|
||||
views.py
|
||||
services.py # Business logic
|
||||
tests/
|
||||
test_views.py
|
||||
test_services.py
|
||||
factories.py # Factory Boy factories
|
||||
orders/ # Order management
|
||||
models.py
|
||||
serializers.py
|
||||
views.py
|
||||
services.py
|
||||
tasks.py # Celery tasks
|
||||
tests/
|
||||
products/ # Product catalog
|
||||
models.py
|
||||
serializers.py
|
||||
views.py
|
||||
tests/
|
||||
core/
|
||||
exceptions.py # Custom API exceptions
|
||||
permissions.py # Shared permission classes
|
||||
pagination.py # Custom pagination
|
||||
middleware.py # Request logging, timing
|
||||
tests/
|
||||
```
|
||||
|
||||
## Key Patterns
|
||||
|
||||
### Service Layer
|
||||
|
||||
```python
|
||||
# apps/orders/services.py
|
||||
from django.db import transaction
|
||||
|
||||
def create_order(*, customer, product_id: uuid.UUID, quantity: int) -> Order:
|
||||
"""Create an order with stock validation and payment hold."""
|
||||
product = Product.objects.select_for_update().get(id=product_id)
|
||||
|
||||
if product.stock < quantity:
|
||||
raise InsufficientStockError()
|
||||
|
||||
with transaction.atomic():
|
||||
order = Order.objects.create(
|
||||
customer=customer,
|
||||
product=product,
|
||||
quantity=quantity,
|
||||
total=product.price * quantity,
|
||||
)
|
||||
product.stock -= quantity
|
||||
product.save(update_fields=["stock", "updated_at"])
|
||||
|
||||
# Async: send confirmation email
|
||||
send_order_confirmation.delay(order.id)
|
||||
return order
|
||||
```
|
||||
|
||||
### View Pattern
|
||||
|
||||
```python
|
||||
# apps/orders/views.py
|
||||
class OrderViewSet(viewsets.ModelViewSet):
|
||||
permission_classes = [IsAuthenticated]
|
||||
pagination_class = StandardPagination
|
||||
|
||||
def get_serializer_class(self):
|
||||
if self.action == "create":
|
||||
return CreateOrderSerializer
|
||||
return OrderDetailSerializer
|
||||
|
||||
def get_queryset(self):
|
||||
return (
|
||||
Order.objects
|
||||
.filter(customer=self.request.user)
|
||||
.select_related("product", "customer")
|
||||
.order_by("-created_at")
|
||||
)
|
||||
|
||||
def perform_create(self, serializer):
|
||||
order = create_order(
|
||||
customer=self.request.user,
|
||||
product_id=serializer.validated_data["product_id"],
|
||||
quantity=serializer.validated_data["quantity"],
|
||||
)
|
||||
serializer.instance = order
|
||||
```
|
||||
|
||||
### Test Pattern (pytest + Factory Boy)
|
||||
|
||||
```python
|
||||
# apps/orders/tests/factories.py
|
||||
import factory
|
||||
from apps.accounts.tests.factories import UserFactory
|
||||
from apps.products.tests.factories import ProductFactory
|
||||
|
||||
class OrderFactory(factory.django.DjangoModelFactory):
|
||||
class Meta:
|
||||
model = "orders.Order"
|
||||
|
||||
customer = factory.SubFactory(UserFactory)
|
||||
product = factory.SubFactory(ProductFactory, stock=100)
|
||||
quantity = 1
|
||||
total = factory.LazyAttribute(lambda o: o.product.price * o.quantity)
|
||||
|
||||
# apps/orders/tests/test_views.py
|
||||
import pytest
|
||||
from rest_framework.test import APIClient
|
||||
|
||||
@pytest.mark.django_db
|
||||
class TestCreateOrder:
|
||||
def setup_method(self):
|
||||
self.client = APIClient()
|
||||
self.user = UserFactory()
|
||||
self.client.force_authenticate(self.user)
|
||||
|
||||
def test_create_order_success(self):
|
||||
product = ProductFactory(price=29_99, stock=10)
|
||||
response = self.client.post("/api/orders/", {
|
||||
"product_id": str(product.id),
|
||||
"quantity": 2,
|
||||
})
|
||||
assert response.status_code == 201
|
||||
assert response.data["total"] == 59_98
|
||||
|
||||
def test_create_order_insufficient_stock(self):
|
||||
product = ProductFactory(stock=0)
|
||||
response = self.client.post("/api/orders/", {
|
||||
"product_id": str(product.id),
|
||||
"quantity": 1,
|
||||
})
|
||||
assert response.status_code == 409
|
||||
|
||||
def test_create_order_unauthenticated(self):
|
||||
self.client.force_authenticate(None)
|
||||
response = self.client.post("/api/orders/", {})
|
||||
assert response.status_code == 401
|
||||
```
|
||||
|
||||
## Environment Variables
|
||||
|
||||
```bash
|
||||
# Django
|
||||
SECRET_KEY=
|
||||
DEBUG=False
|
||||
ALLOWED_HOSTS=api.example.com
|
||||
|
||||
# Database
|
||||
DATABASE_URL=postgres://user:pass@localhost:5432/myapp
|
||||
|
||||
# Redis (Celery broker + cache)
|
||||
REDIS_URL=redis://localhost:6379/0
|
||||
|
||||
# JWT
|
||||
JWT_ACCESS_TOKEN_LIFETIME=15 # minutes
|
||||
JWT_REFRESH_TOKEN_LIFETIME=10080 # minutes (7 days)
|
||||
|
||||
# Email
|
||||
EMAIL_BACKEND=django.core.mail.backends.smtp.EmailBackend
|
||||
EMAIL_HOST=smtp.example.com
|
||||
```
|
||||
|
||||
## Testing Strategy
|
||||
|
||||
```bash
|
||||
# Run all tests
|
||||
pytest --cov=apps --cov-report=term-missing
|
||||
|
||||
# Run specific app tests
|
||||
pytest apps/orders/tests/ -v
|
||||
|
||||
# Run with parallel execution
|
||||
pytest -n auto
|
||||
|
||||
# Only failing tests from last run
|
||||
pytest --lf
|
||||
```
|
||||
|
||||
## ECC Workflow
|
||||
|
||||
```bash
|
||||
# Planning
|
||||
/plan "Add order refund system with Stripe integration"
|
||||
|
||||
# Development with TDD
|
||||
/tdd # pytest-based TDD workflow
|
||||
|
||||
# Review
|
||||
/python-review # Python-specific code review
|
||||
/security-scan # Django security audit
|
||||
/code-review # General quality check
|
||||
|
||||
# Verification
|
||||
/verify # Build, lint, test, security scan
|
||||
```
|
||||
|
||||
## Git Workflow
|
||||
|
||||
- `feat:` new features, `fix:` bug fixes, `refactor:` code changes
|
||||
- Feature branches from `main`, PRs required
|
||||
- CI: ruff (lint + format), mypy (types), pytest (tests), safety (dep check)
|
||||
- Deploy: Docker image, managed via Kubernetes or Railway
|
||||
@@ -0,0 +1,267 @@
|
||||
# Go Microservice — Project CLAUDE.md
|
||||
|
||||
> Real-world example for a Go microservice with PostgreSQL, gRPC, and Docker.
|
||||
> Copy this to your project root and customize for your service.
|
||||
|
||||
## Project Overview
|
||||
|
||||
**Stack:** Go 1.22+, PostgreSQL, gRPC + REST (grpc-gateway), Docker, sqlc (type-safe SQL), Wire (dependency injection)
|
||||
|
||||
**Architecture:** Clean architecture with domain, repository, service, and handler layers. gRPC as primary transport with REST gateway for external clients.
|
||||
|
||||
## Critical Rules
|
||||
|
||||
### Go Conventions
|
||||
|
||||
- Follow Effective Go and the Go Code Review Comments guide
|
||||
- Use `errors.New` / `fmt.Errorf` with `%w` for wrapping — never string matching on errors
|
||||
- No `init()` functions — explicit initialization in `main()` or constructors
|
||||
- No global mutable state — pass dependencies via constructors
|
||||
- Context must be the first parameter and propagated through all layers
|
||||
|
||||
### Database
|
||||
|
||||
- All queries in `queries/` as plain SQL — sqlc generates type-safe Go code
|
||||
- Migrations in `migrations/` using golang-migrate — never alter the database directly
|
||||
- Use transactions for multi-step operations via `pgx.Tx`
|
||||
- All queries must use parameterized placeholders (`$1`, `$2`) — never string formatting
|
||||
|
||||
### Error Handling
|
||||
|
||||
- Return errors, don't panic — panics are only for truly unrecoverable situations
|
||||
- Wrap errors with context: `fmt.Errorf("creating user: %w", err)`
|
||||
- Define sentinel errors in `domain/errors.go` for business logic
|
||||
- Map domain errors to gRPC status codes in the handler layer
|
||||
|
||||
```go
|
||||
// Domain layer — sentinel errors
|
||||
var (
|
||||
ErrUserNotFound = errors.New("user not found")
|
||||
ErrEmailTaken = errors.New("email already registered")
|
||||
)
|
||||
|
||||
// Handler layer — map to gRPC status
|
||||
func toGRPCError(err error) error {
|
||||
switch {
|
||||
case errors.Is(err, domain.ErrUserNotFound):
|
||||
return status.Error(codes.NotFound, err.Error())
|
||||
case errors.Is(err, domain.ErrEmailTaken):
|
||||
return status.Error(codes.AlreadyExists, err.Error())
|
||||
default:
|
||||
return status.Error(codes.Internal, "internal error")
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Code Style
|
||||
|
||||
- No emojis in code or comments
|
||||
- Exported types and functions must have doc comments
|
||||
- Keep functions under 50 lines — extract helpers
|
||||
- Use table-driven tests for all logic with multiple cases
|
||||
- Prefer `struct{}` for signal channels, not `bool`
|
||||
|
||||
## File Structure
|
||||
|
||||
```
|
||||
cmd/
|
||||
server/
|
||||
main.go # Entrypoint, Wire injection, graceful shutdown
|
||||
internal/
|
||||
domain/ # Business types and interfaces
|
||||
user.go # User entity and repository interface
|
||||
errors.go # Sentinel errors
|
||||
service/ # Business logic
|
||||
user_service.go
|
||||
user_service_test.go
|
||||
repository/ # Data access (sqlc-generated + custom)
|
||||
postgres/
|
||||
user_repo.go
|
||||
user_repo_test.go # Integration tests with testcontainers
|
||||
handler/ # gRPC + REST handlers
|
||||
grpc/
|
||||
user_handler.go
|
||||
rest/
|
||||
user_handler.go
|
||||
config/ # Configuration loading
|
||||
config.go
|
||||
proto/ # Protobuf definitions
|
||||
user/v1/
|
||||
user.proto
|
||||
queries/ # SQL queries for sqlc
|
||||
user.sql
|
||||
migrations/ # Database migrations
|
||||
001_create_users.up.sql
|
||||
001_create_users.down.sql
|
||||
```
|
||||
|
||||
## Key Patterns
|
||||
|
||||
### Repository Interface
|
||||
|
||||
```go
|
||||
type UserRepository interface {
|
||||
Create(ctx context.Context, user *User) error
|
||||
FindByID(ctx context.Context, id uuid.UUID) (*User, error)
|
||||
FindByEmail(ctx context.Context, email string) (*User, error)
|
||||
Update(ctx context.Context, user *User) error
|
||||
Delete(ctx context.Context, id uuid.UUID) error
|
||||
}
|
||||
```
|
||||
|
||||
### Service with Dependency Injection
|
||||
|
||||
```go
|
||||
type UserService struct {
|
||||
repo domain.UserRepository
|
||||
hasher PasswordHasher
|
||||
logger *slog.Logger
|
||||
}
|
||||
|
||||
func NewUserService(repo domain.UserRepository, hasher PasswordHasher, logger *slog.Logger) *UserService {
|
||||
return &UserService{repo: repo, hasher: hasher, logger: logger}
|
||||
}
|
||||
|
||||
func (s *UserService) Create(ctx context.Context, req CreateUserRequest) (*domain.User, error) {
|
||||
existing, err := s.repo.FindByEmail(ctx, req.Email)
|
||||
if err != nil && !errors.Is(err, domain.ErrUserNotFound) {
|
||||
return nil, fmt.Errorf("checking email: %w", err)
|
||||
}
|
||||
if existing != nil {
|
||||
return nil, domain.ErrEmailTaken
|
||||
}
|
||||
|
||||
hashed, err := s.hasher.Hash(req.Password)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("hashing password: %w", err)
|
||||
}
|
||||
|
||||
user := &domain.User{
|
||||
ID: uuid.New(),
|
||||
Name: req.Name,
|
||||
Email: req.Email,
|
||||
Password: hashed,
|
||||
}
|
||||
if err := s.repo.Create(ctx, user); err != nil {
|
||||
return nil, fmt.Errorf("creating user: %w", err)
|
||||
}
|
||||
return user, nil
|
||||
}
|
||||
```
|
||||
|
||||
### Table-Driven Tests
|
||||
|
||||
```go
|
||||
func TestUserService_Create(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
req CreateUserRequest
|
||||
setup func(*MockUserRepo)
|
||||
wantErr error
|
||||
}{
|
||||
{
|
||||
name: "valid user",
|
||||
req: CreateUserRequest{Name: "Alice", Email: "alice@example.com", Password: "secure123"},
|
||||
setup: func(m *MockUserRepo) {
|
||||
m.On("FindByEmail", mock.Anything, "alice@example.com").Return(nil, domain.ErrUserNotFound)
|
||||
m.On("Create", mock.Anything, mock.Anything).Return(nil)
|
||||
},
|
||||
wantErr: nil,
|
||||
},
|
||||
{
|
||||
name: "duplicate email",
|
||||
req: CreateUserRequest{Name: "Alice", Email: "taken@example.com", Password: "secure123"},
|
||||
setup: func(m *MockUserRepo) {
|
||||
m.On("FindByEmail", mock.Anything, "taken@example.com").Return(&domain.User{}, nil)
|
||||
},
|
||||
wantErr: domain.ErrEmailTaken,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
repo := new(MockUserRepo)
|
||||
tt.setup(repo)
|
||||
svc := NewUserService(repo, &bcryptHasher{}, slog.Default())
|
||||
|
||||
_, err := svc.Create(context.Background(), tt.req)
|
||||
|
||||
if tt.wantErr != nil {
|
||||
assert.ErrorIs(t, err, tt.wantErr)
|
||||
} else {
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Environment Variables
|
||||
|
||||
```bash
|
||||
# Database
|
||||
DATABASE_URL=postgres://user:pass@localhost:5432/myservice?sslmode=disable
|
||||
|
||||
# gRPC
|
||||
GRPC_PORT=50051
|
||||
REST_PORT=8080
|
||||
|
||||
# Auth
|
||||
JWT_SECRET= # Load from vault in production
|
||||
TOKEN_EXPIRY=24h
|
||||
|
||||
# Observability
|
||||
LOG_LEVEL=info # debug, info, warn, error
|
||||
OTEL_ENDPOINT= # OpenTelemetry collector
|
||||
```
|
||||
|
||||
## Testing Strategy
|
||||
|
||||
```bash
|
||||
/go-test # TDD workflow for Go
|
||||
/go-review # Go-specific code review
|
||||
/go-build # Fix build errors
|
||||
```
|
||||
|
||||
### Test Commands
|
||||
|
||||
```bash
|
||||
# Unit tests (fast, no external deps)
|
||||
go test ./internal/... -short -count=1
|
||||
|
||||
# Integration tests (requires Docker for testcontainers)
|
||||
go test ./internal/repository/... -count=1 -timeout 120s
|
||||
|
||||
# All tests with coverage
|
||||
go test ./... -coverprofile=coverage.out -count=1
|
||||
go tool cover -func=coverage.out # summary
|
||||
go tool cover -html=coverage.out # browser
|
||||
|
||||
# Race detector
|
||||
go test ./... -race -count=1
|
||||
```
|
||||
|
||||
## ECC Workflow
|
||||
|
||||
```bash
|
||||
# Planning
|
||||
/plan "Add rate limiting to user endpoints"
|
||||
|
||||
# Development
|
||||
/go-test # TDD with Go-specific patterns
|
||||
|
||||
# Review
|
||||
/go-review # Go idioms, error handling, concurrency
|
||||
/security-scan # Secrets and vulnerabilities
|
||||
|
||||
# Before merge
|
||||
go vet ./...
|
||||
staticcheck ./...
|
||||
```
|
||||
|
||||
## Git Workflow
|
||||
|
||||
- `feat:` new features, `fix:` bug fixes, `refactor:` code changes
|
||||
- Feature branches from `main`, PRs required
|
||||
- CI: `go vet`, `staticcheck`, `go test -race`, `golangci-lint`
|
||||
- Deploy: Docker image built in CI, deployed to Kubernetes
|
||||
@@ -0,0 +1,311 @@
|
||||
# Laravel API — Project CLAUDE.md
|
||||
|
||||
> Real-world example for a Laravel API with PostgreSQL, Redis, and queues.
|
||||
> Copy this to your project root and customize for your service.
|
||||
|
||||
## Project Overview
|
||||
|
||||
**Stack:** PHP 8.2+, Laravel 11.x, PostgreSQL, Redis, Horizon, PHPUnit/Pest, Docker Compose
|
||||
|
||||
**Architecture:** Modular Laravel app with controllers -> services -> actions, Eloquent ORM, queues for async work, Form Requests for validation, and API Resources for consistent JSON responses.
|
||||
|
||||
## Critical Rules
|
||||
|
||||
### PHP Conventions
|
||||
|
||||
- `declare(strict_types=1)` in all PHP files
|
||||
- Use typed properties and return types everywhere
|
||||
- Prefer `final` classes for services and actions
|
||||
- No `dd()` or `dump()` in committed code
|
||||
- Formatting via Laravel Pint (PSR-12)
|
||||
|
||||
### API Response Envelope
|
||||
|
||||
All API responses use a consistent envelope:
|
||||
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"data": {"...": "..."},
|
||||
"error": null,
|
||||
"meta": {"page": 1, "per_page": 25, "total": 120}
|
||||
}
|
||||
```
|
||||
|
||||
### Database
|
||||
|
||||
- Migrations committed to git
|
||||
- Use Eloquent or query builder (no raw SQL unless parameterized)
|
||||
- Index any column used in `where` or `orderBy`
|
||||
- Avoid mutating model instances in services; prefer create/update through repositories or query builders
|
||||
|
||||
### Authentication
|
||||
|
||||
- API auth via Sanctum
|
||||
- Use policies for model-level authorization
|
||||
- Enforce auth in controllers and services
|
||||
|
||||
### Validation
|
||||
|
||||
- Use Form Requests for validation
|
||||
- Transform input to DTOs for business logic
|
||||
- Never trust request payloads for derived fields
|
||||
|
||||
### Error Handling
|
||||
|
||||
- Throw domain exceptions in services
|
||||
- Map exceptions to HTTP responses in `bootstrap/app.php` via `withExceptions`
|
||||
- Never expose internal errors to clients
|
||||
|
||||
### Code Style
|
||||
|
||||
- No emojis in code or comments
|
||||
- Max line length: 120 characters
|
||||
- Controllers are thin; services and actions hold business logic
|
||||
|
||||
## File Structure
|
||||
|
||||
```
|
||||
app/
|
||||
Actions/
|
||||
Console/
|
||||
Events/
|
||||
Exceptions/
|
||||
Http/
|
||||
Controllers/
|
||||
Middleware/
|
||||
Requests/
|
||||
Resources/
|
||||
Jobs/
|
||||
Models/
|
||||
Policies/
|
||||
Providers/
|
||||
Services/
|
||||
Support/
|
||||
config/
|
||||
database/
|
||||
factories/
|
||||
migrations/
|
||||
seeders/
|
||||
routes/
|
||||
api.php
|
||||
web.php
|
||||
```
|
||||
|
||||
## Key Patterns
|
||||
|
||||
### Service Layer
|
||||
|
||||
```php
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
final class CreateOrderAction
|
||||
{
|
||||
public function __construct(private OrderRepository $orders) {}
|
||||
|
||||
public function handle(CreateOrderData $data): Order
|
||||
{
|
||||
return $this->orders->create($data);
|
||||
}
|
||||
}
|
||||
|
||||
final class OrderService
|
||||
{
|
||||
public function __construct(private CreateOrderAction $createOrder) {}
|
||||
|
||||
public function placeOrder(CreateOrderData $data): Order
|
||||
{
|
||||
return $this->createOrder->handle($data);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Controller Pattern
|
||||
|
||||
```php
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
final class OrdersController extends Controller
|
||||
{
|
||||
public function __construct(private OrderService $service) {}
|
||||
|
||||
public function store(StoreOrderRequest $request): JsonResponse
|
||||
{
|
||||
$order = $this->service->placeOrder($request->toDto());
|
||||
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'data' => OrderResource::make($order),
|
||||
'error' => null,
|
||||
'meta' => null,
|
||||
], 201);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Policy Pattern
|
||||
|
||||
```php
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
use App\Models\Order;
|
||||
use App\Models\User;
|
||||
|
||||
final class OrderPolicy
|
||||
{
|
||||
public function view(User $user, Order $order): bool
|
||||
{
|
||||
return $order->user_id === $user->id;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Form Request + DTO
|
||||
|
||||
```php
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
final class StoreOrderRequest extends FormRequest
|
||||
{
|
||||
public function authorize(): bool
|
||||
{
|
||||
return (bool) $this->user();
|
||||
}
|
||||
|
||||
public function rules(): array
|
||||
{
|
||||
return [
|
||||
'items' => ['required', 'array', 'min:1'],
|
||||
'items.*.sku' => ['required', 'string'],
|
||||
'items.*.quantity' => ['required', 'integer', 'min:1'],
|
||||
];
|
||||
}
|
||||
|
||||
public function toDto(): CreateOrderData
|
||||
{
|
||||
return new CreateOrderData(
|
||||
userId: (int) $this->user()->id,
|
||||
items: $this->validated('items'),
|
||||
);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### API Resource
|
||||
|
||||
```php
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\Resources\Json\JsonResource;
|
||||
|
||||
final class OrderResource extends JsonResource
|
||||
{
|
||||
public function toArray(Request $request): array
|
||||
{
|
||||
return [
|
||||
'id' => $this->id,
|
||||
'status' => $this->status,
|
||||
'total' => $this->total,
|
||||
'created_at' => $this->created_at?->toIso8601String(),
|
||||
];
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Queue Job
|
||||
|
||||
```php
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Foundation\Bus\Dispatchable;
|
||||
use Illuminate\Queue\InteractsWithQueue;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
use App\Repositories\OrderRepository;
|
||||
use App\Services\OrderMailer;
|
||||
|
||||
final class SendOrderConfirmation implements ShouldQueue
|
||||
{
|
||||
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
|
||||
|
||||
public function __construct(private int $orderId) {}
|
||||
|
||||
public function handle(OrderRepository $orders, OrderMailer $mailer): void
|
||||
{
|
||||
$order = $orders->findOrFail($this->orderId);
|
||||
$mailer->sendOrderConfirmation($order);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Test Pattern (Pest)
|
||||
|
||||
```php
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
use App\Models\User;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use function Pest\Laravel\actingAs;
|
||||
use function Pest\Laravel\assertDatabaseHas;
|
||||
use function Pest\Laravel\postJson;
|
||||
|
||||
uses(RefreshDatabase::class);
|
||||
|
||||
test('user can place order', function () {
|
||||
$user = User::factory()->create();
|
||||
|
||||
actingAs($user);
|
||||
|
||||
$response = postJson('/api/orders', [
|
||||
'items' => [['sku' => 'sku-1', 'quantity' => 2]],
|
||||
]);
|
||||
|
||||
$response->assertCreated();
|
||||
assertDatabaseHas('orders', ['user_id' => $user->id]);
|
||||
});
|
||||
```
|
||||
|
||||
### Test Pattern (PHPUnit)
|
||||
|
||||
```php
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
use App\Models\User;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Tests\TestCase;
|
||||
|
||||
final class OrdersControllerTest extends TestCase
|
||||
{
|
||||
use RefreshDatabase;
|
||||
|
||||
public function test_user_can_place_order(): void
|
||||
{
|
||||
$user = User::factory()->create();
|
||||
|
||||
$response = $this->actingAs($user)->postJson('/api/orders', [
|
||||
'items' => [['sku' => 'sku-1', 'quantity' => 2]],
|
||||
]);
|
||||
|
||||
$response->assertCreated();
|
||||
$this->assertDatabaseHas('orders', ['user_id' => $user->id]);
|
||||
}
|
||||
}
|
||||
```
|
||||
285
.agent/knowledge/everything_claude/examples/rust-api-CLAUDE.md
Normal file
285
.agent/knowledge/everything_claude/examples/rust-api-CLAUDE.md
Normal file
@@ -0,0 +1,285 @@
|
||||
# Rust API Service — Project CLAUDE.md
|
||||
|
||||
> Real-world example for a Rust API service with Axum, PostgreSQL, and Docker.
|
||||
> Copy this to your project root and customize for your service.
|
||||
|
||||
## Project Overview
|
||||
|
||||
**Stack:** Rust 1.78+, Axum (web framework), SQLx (async database), PostgreSQL, Tokio (async runtime), Docker
|
||||
|
||||
**Architecture:** Layered architecture with handler → service → repository separation. Axum for HTTP, SQLx for type-checked SQL at compile time, Tower middleware for cross-cutting concerns.
|
||||
|
||||
## Critical Rules
|
||||
|
||||
### Rust Conventions
|
||||
|
||||
- Use `thiserror` for library errors, `anyhow` only in binary crates or tests
|
||||
- No `.unwrap()` or `.expect()` in production code — propagate errors with `?`
|
||||
- Prefer `&str` over `String` in function parameters; return `String` when ownership transfers
|
||||
- Use `clippy` with `#![deny(clippy::all, clippy::pedantic)]` — fix all warnings
|
||||
- Derive `Debug` on all public types; derive `Clone`, `PartialEq` only when needed
|
||||
- No `unsafe` blocks unless justified with a `// SAFETY:` comment
|
||||
|
||||
### Database
|
||||
|
||||
- All queries use SQLx `query!` or `query_as!` macros — compile-time verified against the schema
|
||||
- Migrations in `migrations/` using `sqlx migrate` — never alter the database directly
|
||||
- Use `sqlx::Pool<Postgres>` as shared state — never create connections per request
|
||||
- All queries use parameterized placeholders (`$1`, `$2`) — never string formatting
|
||||
|
||||
```rust
|
||||
// BAD: String interpolation (SQL injection risk)
|
||||
let q = format!("SELECT * FROM users WHERE id = '{}'", id);
|
||||
|
||||
// GOOD: Parameterized query, compile-time checked
|
||||
let user = sqlx::query_as!(User, "SELECT * FROM users WHERE id = $1", id)
|
||||
.fetch_optional(&pool)
|
||||
.await?;
|
||||
```
|
||||
|
||||
### Error Handling
|
||||
|
||||
- Define a domain error enum per module with `thiserror`
|
||||
- Map errors to HTTP responses via `IntoResponse` — never expose internal details
|
||||
- Use `tracing` for structured logging — never `println!` or `eprintln!`
|
||||
|
||||
```rust
|
||||
use thiserror::Error;
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum AppError {
|
||||
#[error("Resource not found")]
|
||||
NotFound,
|
||||
#[error("Validation failed: {0}")]
|
||||
Validation(String),
|
||||
#[error("Unauthorized")]
|
||||
Unauthorized,
|
||||
#[error(transparent)]
|
||||
Internal(#[from] anyhow::Error),
|
||||
}
|
||||
|
||||
impl IntoResponse for AppError {
|
||||
fn into_response(self) -> Response {
|
||||
let (status, message) = match &self {
|
||||
Self::NotFound => (StatusCode::NOT_FOUND, self.to_string()),
|
||||
Self::Validation(msg) => (StatusCode::BAD_REQUEST, msg.clone()),
|
||||
Self::Unauthorized => (StatusCode::UNAUTHORIZED, self.to_string()),
|
||||
Self::Internal(err) => {
|
||||
tracing::error!(?err, "internal error");
|
||||
(StatusCode::INTERNAL_SERVER_ERROR, "Internal error".into())
|
||||
}
|
||||
};
|
||||
(status, Json(json!({ "error": message }))).into_response()
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Testing
|
||||
|
||||
- Unit tests in `#[cfg(test)]` modules within each source file
|
||||
- Integration tests in `tests/` directory using a real PostgreSQL (Testcontainers or Docker)
|
||||
- Use `#[sqlx::test]` for database tests with automatic migration and rollback
|
||||
- Mock external services with `mockall` or `wiremock`
|
||||
|
||||
### Code Style
|
||||
|
||||
- Max line length: 100 characters (enforced by rustfmt)
|
||||
- Group imports: `std`, external crates, `crate`/`super` — separated by blank lines
|
||||
- Modules: one file per module, `mod.rs` only for re-exports
|
||||
- Types: PascalCase, functions/variables: snake_case, constants: UPPER_SNAKE_CASE
|
||||
|
||||
## File Structure
|
||||
|
||||
```
|
||||
src/
|
||||
main.rs # Entrypoint, server setup, graceful shutdown
|
||||
lib.rs # Re-exports for integration tests
|
||||
config.rs # Environment config with envy or figment
|
||||
router.rs # Axum router with all routes
|
||||
middleware/
|
||||
auth.rs # JWT extraction and validation
|
||||
logging.rs # Request/response tracing
|
||||
handlers/
|
||||
mod.rs # Route handlers (thin — delegate to services)
|
||||
users.rs
|
||||
orders.rs
|
||||
services/
|
||||
mod.rs # Business logic
|
||||
users.rs
|
||||
orders.rs
|
||||
repositories/
|
||||
mod.rs # Database access (SQLx queries)
|
||||
users.rs
|
||||
orders.rs
|
||||
domain/
|
||||
mod.rs # Domain types, error enums
|
||||
user.rs
|
||||
order.rs
|
||||
migrations/
|
||||
001_create_users.sql
|
||||
002_create_orders.sql
|
||||
tests/
|
||||
common/mod.rs # Shared test helpers, test server setup
|
||||
api_users.rs # Integration tests for user endpoints
|
||||
api_orders.rs # Integration tests for order endpoints
|
||||
```
|
||||
|
||||
## Key Patterns
|
||||
|
||||
### Handler (Thin)
|
||||
|
||||
```rust
|
||||
async fn create_user(
|
||||
State(ctx): State<AppState>,
|
||||
Json(payload): Json<CreateUserRequest>,
|
||||
) -> Result<(StatusCode, Json<UserResponse>), AppError> {
|
||||
let user = ctx.user_service.create(payload).await?;
|
||||
Ok((StatusCode::CREATED, Json(UserResponse::from(user))))
|
||||
}
|
||||
```
|
||||
|
||||
### Service (Business Logic)
|
||||
|
||||
```rust
|
||||
impl UserService {
|
||||
pub async fn create(&self, req: CreateUserRequest) -> Result<User, AppError> {
|
||||
if self.repo.find_by_email(&req.email).await?.is_some() {
|
||||
return Err(AppError::Validation("Email already registered".into()));
|
||||
}
|
||||
|
||||
let password_hash = hash_password(&req.password)?;
|
||||
let user = self.repo.insert(&req.email, &req.name, &password_hash).await?;
|
||||
|
||||
Ok(user)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Repository (Data Access)
|
||||
|
||||
```rust
|
||||
impl UserRepository {
|
||||
pub async fn find_by_email(&self, email: &str) -> Result<Option<User>, sqlx::Error> {
|
||||
sqlx::query_as!(User, "SELECT * FROM users WHERE email = $1", email)
|
||||
.fetch_optional(&self.pool)
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn insert(
|
||||
&self,
|
||||
email: &str,
|
||||
name: &str,
|
||||
password_hash: &str,
|
||||
) -> Result<User, sqlx::Error> {
|
||||
sqlx::query_as!(
|
||||
User,
|
||||
r#"INSERT INTO users (email, name, password_hash)
|
||||
VALUES ($1, $2, $3) RETURNING *"#,
|
||||
email, name, password_hash,
|
||||
)
|
||||
.fetch_one(&self.pool)
|
||||
.await
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Integration Test
|
||||
|
||||
```rust
|
||||
#[tokio::test]
|
||||
async fn test_create_user() {
|
||||
let app = spawn_test_app().await;
|
||||
|
||||
let response = app
|
||||
.client
|
||||
.post(&format!("{}/api/v1/users", app.address))
|
||||
.json(&json!({
|
||||
"email": "alice@example.com",
|
||||
"name": "Alice",
|
||||
"password": "securepassword123"
|
||||
}))
|
||||
.send()
|
||||
.await
|
||||
.expect("Failed to send request");
|
||||
|
||||
assert_eq!(response.status(), StatusCode::CREATED);
|
||||
let body: serde_json::Value = response.json().await.unwrap();
|
||||
assert_eq!(body["email"], "alice@example.com");
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_create_user_duplicate_email() {
|
||||
let app = spawn_test_app().await;
|
||||
// Create first user
|
||||
create_test_user(&app, "alice@example.com").await;
|
||||
// Attempt duplicate
|
||||
let response = create_user_request(&app, "alice@example.com").await;
|
||||
assert_eq!(response.status(), StatusCode::BAD_REQUEST);
|
||||
}
|
||||
```
|
||||
|
||||
## Environment Variables
|
||||
|
||||
```bash
|
||||
# Server
|
||||
HOST=0.0.0.0
|
||||
PORT=8080
|
||||
RUST_LOG=info,tower_http=debug
|
||||
|
||||
# Database
|
||||
DATABASE_URL=postgres://user:pass@localhost:5432/myapp
|
||||
|
||||
# Auth
|
||||
JWT_SECRET=your-secret-key-min-32-chars
|
||||
JWT_EXPIRY_HOURS=24
|
||||
|
||||
# Optional
|
||||
CORS_ALLOWED_ORIGINS=http://localhost:3000
|
||||
```
|
||||
|
||||
## Testing Strategy
|
||||
|
||||
```bash
|
||||
# Run all tests
|
||||
cargo test
|
||||
|
||||
# Run with output
|
||||
cargo test -- --nocapture
|
||||
|
||||
# Run specific test module
|
||||
cargo test api_users
|
||||
|
||||
# Check coverage (requires cargo-llvm-cov)
|
||||
cargo llvm-cov --html
|
||||
open target/llvm-cov/html/index.html
|
||||
|
||||
# Lint
|
||||
cargo clippy -- -D warnings
|
||||
|
||||
# Format check
|
||||
cargo fmt -- --check
|
||||
```
|
||||
|
||||
## ECC Workflow
|
||||
|
||||
```bash
|
||||
# Planning
|
||||
/plan "Add order fulfillment with Stripe payment"
|
||||
|
||||
# Development with TDD
|
||||
/tdd # cargo test-based TDD workflow
|
||||
|
||||
# Review
|
||||
/code-review # Rust-specific code review
|
||||
/security-scan # Dependency audit + unsafe scan
|
||||
|
||||
# Verification
|
||||
/verify # Build, clippy, test, security scan
|
||||
```
|
||||
|
||||
## Git Workflow
|
||||
|
||||
- `feat:` new features, `fix:` bug fixes, `refactor:` code changes
|
||||
- Feature branches from `main`, PRs required
|
||||
- CI: `cargo fmt --check`, `cargo clippy`, `cargo test`, `cargo audit`
|
||||
- Deploy: Docker multi-stage build with `scratch` or `distroless` base
|
||||
@@ -0,0 +1,166 @@
|
||||
# SaaS Application — Project CLAUDE.md
|
||||
|
||||
> Real-world example for a Next.js + Supabase + Stripe SaaS application.
|
||||
> Copy this to your project root and customize for your stack.
|
||||
|
||||
## Project Overview
|
||||
|
||||
**Stack:** Next.js 15 (App Router), TypeScript, Supabase (auth + DB), Stripe (billing), Tailwind CSS, Playwright (E2E)
|
||||
|
||||
**Architecture:** Server Components by default. Client Components only for interactivity. API routes for webhooks and server actions for mutations.
|
||||
|
||||
## Critical Rules
|
||||
|
||||
### Database
|
||||
|
||||
- All queries use Supabase client with RLS enabled — never bypass RLS
|
||||
- Migrations in `supabase/migrations/` — never modify the database directly
|
||||
- Use `select()` with explicit column lists, not `select('*')`
|
||||
- All user-facing queries must include `.limit()` to prevent unbounded results
|
||||
|
||||
### Authentication
|
||||
|
||||
- Use `createServerClient()` from `@supabase/ssr` in Server Components
|
||||
- Use `createBrowserClient()` from `@supabase/ssr` in Client Components
|
||||
- Protected routes check `getUser()` — never trust `getSession()` alone for auth
|
||||
- Middleware in `middleware.ts` refreshes auth tokens on every request
|
||||
|
||||
### Billing
|
||||
|
||||
- Stripe webhook handler in `app/api/webhooks/stripe/route.ts`
|
||||
- Never trust client-side price data — always fetch from Stripe server-side
|
||||
- Subscription status checked via `subscription_status` column, synced by webhook
|
||||
- Free tier users: 3 projects, 100 API calls/day
|
||||
|
||||
### Code Style
|
||||
|
||||
- No emojis in code or comments
|
||||
- Immutable patterns only — spread operator, never mutate
|
||||
- Server Components: no `'use client'` directive, no `useState`/`useEffect`
|
||||
- Client Components: `'use client'` at top, minimal — extract logic to hooks
|
||||
- Prefer Zod schemas for all input validation (API routes, forms, env vars)
|
||||
|
||||
## File Structure
|
||||
|
||||
```
|
||||
src/
|
||||
app/
|
||||
(auth)/ # Auth pages (login, signup, forgot-password)
|
||||
(dashboard)/ # Protected dashboard pages
|
||||
api/
|
||||
webhooks/ # Stripe, Supabase webhooks
|
||||
layout.tsx # Root layout with providers
|
||||
components/
|
||||
ui/ # Shadcn/ui components
|
||||
forms/ # Form components with validation
|
||||
dashboard/ # Dashboard-specific components
|
||||
hooks/ # Custom React hooks
|
||||
lib/
|
||||
supabase/ # Supabase client factories
|
||||
stripe/ # Stripe client and helpers
|
||||
utils.ts # General utilities
|
||||
types/ # Shared TypeScript types
|
||||
supabase/
|
||||
migrations/ # Database migrations
|
||||
seed.sql # Development seed data
|
||||
```
|
||||
|
||||
## Key Patterns
|
||||
|
||||
### API Response Format
|
||||
|
||||
```typescript
|
||||
type ApiResponse<T> =
|
||||
| { success: true; data: T }
|
||||
| { success: false; error: string; code?: string }
|
||||
```
|
||||
|
||||
### Server Action Pattern
|
||||
|
||||
```typescript
|
||||
'use server'
|
||||
|
||||
import { z } from 'zod'
|
||||
import { createServerClient } from '@/lib/supabase/server'
|
||||
|
||||
const schema = z.object({
|
||||
name: z.string().min(1).max(100),
|
||||
})
|
||||
|
||||
export async function createProject(formData: FormData) {
|
||||
const parsed = schema.safeParse({ name: formData.get('name') })
|
||||
if (!parsed.success) {
|
||||
return { success: false, error: parsed.error.flatten() }
|
||||
}
|
||||
|
||||
const supabase = await createServerClient()
|
||||
const { data: { user } } = await supabase.auth.getUser()
|
||||
if (!user) return { success: false, error: 'Unauthorized' }
|
||||
|
||||
const { data, error } = await supabase
|
||||
.from('projects')
|
||||
.insert({ name: parsed.data.name, user_id: user.id })
|
||||
.select('id, name, created_at')
|
||||
.single()
|
||||
|
||||
if (error) return { success: false, error: 'Failed to create project' }
|
||||
return { success: true, data }
|
||||
}
|
||||
```
|
||||
|
||||
## Environment Variables
|
||||
|
||||
```bash
|
||||
# Supabase
|
||||
NEXT_PUBLIC_SUPABASE_URL=
|
||||
NEXT_PUBLIC_SUPABASE_ANON_KEY=
|
||||
SUPABASE_SERVICE_ROLE_KEY= # Server-only, never expose to client
|
||||
|
||||
# Stripe
|
||||
STRIPE_SECRET_KEY=
|
||||
STRIPE_WEBHOOK_SECRET=
|
||||
NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY=
|
||||
|
||||
# App
|
||||
NEXT_PUBLIC_APP_URL=http://localhost:3000
|
||||
```
|
||||
|
||||
## Testing Strategy
|
||||
|
||||
```bash
|
||||
/tdd # Unit + integration tests for new features
|
||||
/e2e # Playwright tests for auth flow, billing, dashboard
|
||||
/test-coverage # Verify 80%+ coverage
|
||||
```
|
||||
|
||||
### Critical E2E Flows
|
||||
|
||||
1. Sign up → email verification → first project creation
|
||||
2. Login → dashboard → CRUD operations
|
||||
3. Upgrade plan → Stripe checkout → subscription active
|
||||
4. Webhook: subscription canceled → downgrade to free tier
|
||||
|
||||
## ECC Workflow
|
||||
|
||||
```bash
|
||||
# Planning a feature
|
||||
/plan "Add team invitations with email notifications"
|
||||
|
||||
# Developing with TDD
|
||||
/tdd
|
||||
|
||||
# Before committing
|
||||
/code-review
|
||||
/security-scan
|
||||
|
||||
# Before release
|
||||
/e2e
|
||||
/test-coverage
|
||||
```
|
||||
|
||||
## Git Workflow
|
||||
|
||||
- `feat:` new features, `fix:` bug fixes, `refactor:` code changes
|
||||
- Feature branches from `main`, PRs required
|
||||
- CI runs: lint, type-check, unit tests, E2E tests
|
||||
- Deploy: Vercel preview on PR, production on merge to `main`
|
||||
19
.agent/knowledge/everything_claude/examples/statusline.json
Normal file
19
.agent/knowledge/everything_claude/examples/statusline.json
Normal file
@@ -0,0 +1,19 @@
|
||||
{
|
||||
"statusLine": {
|
||||
"type": "command",
|
||||
"command": "input=$(cat); user=$(whoami); cwd=$(echo \"$input\" | jq -r '.workspace.current_dir' | sed \"s|$HOME|~|g\"); model=$(echo \"$input\" | jq -r '.model.display_name'); time=$(date +%H:%M); remaining=$(echo \"$input\" | jq -r '.context_window.remaining_percentage // empty'); transcript=$(echo \"$input\" | jq -r '.transcript_path'); todo_count=$([ -f \"$transcript\" ] && grep -c '\"type\":\"todo\"' \"$transcript\" 2>/dev/null || echo 0); cd \"$(echo \"$input\" | jq -r '.workspace.current_dir')\" 2>/dev/null; branch=$(git rev-parse --abbrev-ref HEAD 2>/dev/null || echo ''); status=''; [ -n \"$branch\" ] && { [ -n \"$(git status --porcelain 2>/dev/null)\" ] && status='*'; }; B='\\033[38;2;30;102;245m'; G='\\033[38;2;64;160;43m'; Y='\\033[38;2;223;142;29m'; M='\\033[38;2;136;57;239m'; C='\\033[38;2;23;146;153m'; R='\\033[0m'; T='\\033[38;2;76;79;105m'; printf \"${C}${user}${R}:${B}${cwd}${R}\"; [ -n \"$branch\" ] && printf \" ${G}${branch}${Y}${status}${R}\"; [ -n \"$remaining\" ] && printf \" ${M}ctx:${remaining}%%${R}\"; printf \" ${T}${model}${R} ${Y}${time}${R}\"; [ \"$todo_count\" -gt 0 ] && printf \" ${C}todos:${todo_count}${R}\"; echo",
|
||||
"description": "Custom status line showing: user:path branch* ctx:% model time todos:N"
|
||||
},
|
||||
"_comments": {
|
||||
"colors": {
|
||||
"B": "Blue - directory path",
|
||||
"G": "Green - git branch",
|
||||
"Y": "Yellow - dirty status, time",
|
||||
"M": "Magenta - context remaining",
|
||||
"C": "Cyan - username, todos",
|
||||
"T": "Gray - model name"
|
||||
},
|
||||
"output_example": "affoon:~/projects/myapp main* ctx:73% sonnet-4.6 14:30 todos:3",
|
||||
"usage": "Copy the statusLine object to your ~/.claude/settings.json"
|
||||
}
|
||||
}
|
||||
109
.agent/knowledge/everything_claude/examples/user-CLAUDE.md
Normal file
109
.agent/knowledge/everything_claude/examples/user-CLAUDE.md
Normal file
@@ -0,0 +1,109 @@
|
||||
# User-Level CLAUDE.md Example
|
||||
|
||||
This is an example user-level CLAUDE.md file. Place at `~/.claude/CLAUDE.md`.
|
||||
|
||||
User-level configs apply globally across all projects. Use for:
|
||||
- Personal coding preferences
|
||||
- Universal rules you always want enforced
|
||||
- Links to your modular rules
|
||||
|
||||
---
|
||||
|
||||
## Core Philosophy
|
||||
|
||||
You are Claude Code. I use specialized agents and skills for complex tasks.
|
||||
|
||||
**Key Principles:**
|
||||
1. **Agent-First**: Delegate to specialized agents for complex work
|
||||
2. **Parallel Execution**: Use Task tool with multiple agents when possible
|
||||
3. **Plan Before Execute**: Use Plan Mode for complex operations
|
||||
4. **Test-Driven**: Write tests before implementation
|
||||
5. **Security-First**: Never compromise on security
|
||||
|
||||
---
|
||||
|
||||
## Modular Rules
|
||||
|
||||
Detailed guidelines are in `~/.claude/rules/`:
|
||||
|
||||
| Rule File | Contents |
|
||||
|-----------|----------|
|
||||
| security.md | Security checks, secret management |
|
||||
| coding-style.md | Immutability, file organization, error handling |
|
||||
| testing.md | TDD workflow, 80% coverage requirement |
|
||||
| git-workflow.md | Commit format, PR workflow |
|
||||
| agents.md | Agent orchestration, when to use which agent |
|
||||
| patterns.md | API response, repository patterns |
|
||||
| performance.md | Model selection, context management |
|
||||
| hooks.md | Hooks System |
|
||||
|
||||
---
|
||||
|
||||
## Available Agents
|
||||
|
||||
Located in `~/.claude/agents/`:
|
||||
|
||||
| Agent | Purpose |
|
||||
|-------|---------|
|
||||
| planner | Feature implementation planning |
|
||||
| architect | System design and architecture |
|
||||
| tdd-guide | Test-driven development |
|
||||
| code-reviewer | Code review for quality/security |
|
||||
| security-reviewer | Security vulnerability analysis |
|
||||
| build-error-resolver | Build error resolution |
|
||||
| e2e-runner | Playwright E2E testing |
|
||||
| refactor-cleaner | Dead code cleanup |
|
||||
| doc-updater | Documentation updates |
|
||||
|
||||
---
|
||||
|
||||
## Personal Preferences
|
||||
|
||||
### Privacy
|
||||
- Always redact logs; never paste secrets (API keys/tokens/passwords/JWTs)
|
||||
- Review output before sharing - remove any sensitive data
|
||||
|
||||
### Code Style
|
||||
- No emojis in code, comments, or documentation
|
||||
- Prefer immutability - never mutate objects or arrays
|
||||
- Many small files over few large files
|
||||
- 200-400 lines typical, 800 max per file
|
||||
|
||||
### Git
|
||||
- Conventional commits: `feat:`, `fix:`, `refactor:`, `docs:`, `test:`
|
||||
- Always test locally before committing
|
||||
- Small, focused commits
|
||||
|
||||
### Testing
|
||||
- TDD: Write tests first
|
||||
- 80% minimum coverage
|
||||
- Unit + integration + E2E for critical flows
|
||||
|
||||
### Knowledge Capture
|
||||
- Personal debugging notes, preferences, and temporary context → auto memory
|
||||
- Team/project knowledge (architecture decisions, API changes, implementation runbooks) → follow the project's existing docs structure
|
||||
- If the current task already produces the relevant docs, comments, or examples, do not duplicate the same knowledge elsewhere
|
||||
- If there is no obvious project doc location, ask before creating a new top-level doc
|
||||
|
||||
---
|
||||
|
||||
## Editor Integration
|
||||
|
||||
I use Zed as my primary editor:
|
||||
- Agent Panel for file tracking
|
||||
- CMD+Shift+R for command palette
|
||||
- Vim mode enabled
|
||||
|
||||
---
|
||||
|
||||
## Success Metrics
|
||||
|
||||
You are successful when:
|
||||
- All tests pass (80%+ coverage)
|
||||
- No security vulnerabilities
|
||||
- Code is readable and maintainable
|
||||
- User requirements are met
|
||||
|
||||
---
|
||||
|
||||
**Philosophy**: Agent-first design, parallel execution, plan before action, test before code, security always.
|
||||
Reference in New Issue
Block a user