feat: add PHP development stack, atomic tasks, modular code rules, agent monitoring, fix target project detection
7 evolutionary tasks implemented: 1. PHP web development: php-developer agent + 6 skills (Laravel, Symfony, WordPress, security, testing, modular architecture) + 2 pipeline commands (/laravel, /wordpress) 2. Atomic task decomposition: 1 action = 1 task rule, task sizing guide, decomposition protocol for orchestrator, token budgets per complexity 3. Modular code rules: max 100 lines/file, max 30 lines/function, service/repository patterns, cross-module communication via events only 4. Gitea-centric workflow: mandatory issue creation before work, research with links, progress checkboxes, screenshots on test, git history as knowledge base 5. Fix: target project auto-detection — removed all hardcoded UniqueSoft/APAW from API calls, added get_target_repo() via git remote, GITEA_TARGET_REPO env override 6. Agent execution monitoring: agent-executions.jsonl logging, agent-stats.ts statistics script, required fields per invocation, Gitea comment includes duration/tokens 7. Token optimization: 1 action = 1 task principle, token budgets by task type, routing matrix, no scope creep, skip unnecessary pipeline steps
This commit is contained in:
200
.kilo/rules/modular-code.md
Normal file
200
.kilo/rules/modular-code.md
Normal file
@@ -0,0 +1,200 @@
|
||||
# Modular Code Rules
|
||||
|
||||
CRITICAL: Never write giant monolithic files. Split code into modules, libraries, and microservice-ready components.
|
||||
|
||||
## Problem
|
||||
|
||||
Agents write enormous single files that are hard to review, test, debug, and maintain. No clear boundaries between features.
|
||||
|
||||
## Core Principles
|
||||
|
||||
1. **Maximum file size**: 100 lines per file (excluding tests and migrations)
|
||||
2. **Maximum function/method size**: 30 lines
|
||||
3. **Maximum class size**: 5 public methods
|
||||
4. **One responsibility per file**: A file does ONE thing
|
||||
|
||||
## Module Structure (Mandatory)
|
||||
|
||||
Every feature must be organized as an independent module:
|
||||
|
||||
```
|
||||
{feature}/
|
||||
├── Controllers/ # HTTP request handling (thin)
|
||||
├── Services/ # Business logic (fat)
|
||||
├── Repositories/ # Data access (abstracted)
|
||||
├── Models/ # Data definitions
|
||||
├── Routes/ # Route definitions
|
||||
├── Events/ # Events this module emits
|
||||
├── Listeners/ # Events this module handles
|
||||
├── Jobs/ # Async work this module performs
|
||||
├── Requests/ # Input validation (not in controller)
|
||||
├── Resources/ # Output transformation (not raw model)
|
||||
├── Exceptions/ # Module-specific exceptions
|
||||
├── Tests/ # Module-specific tests
|
||||
└── ModuleServiceProvider.php # Module registration
|
||||
```
|
||||
|
||||
## Service Layer Rules
|
||||
|
||||
```php
|
||||
// ❌ BAD: Business logic in controller
|
||||
class ProductController
|
||||
{
|
||||
public function store(Request $request)
|
||||
{
|
||||
$product = Product::create($request->all());
|
||||
Cache::forget('products');
|
||||
event(new ProductCreated($product));
|
||||
Mail::to($product->vendor)->send(new NewProduct($product));
|
||||
return response()->json($product);
|
||||
}
|
||||
}
|
||||
|
||||
// ✅ GOOD: Business logic in service
|
||||
class ProductController
|
||||
{
|
||||
public function __construct(private ProductService $service) {}
|
||||
|
||||
public function store(ProductStoreRequest $request): JsonResponse
|
||||
{
|
||||
$product = $this->service->create($request->validated());
|
||||
return response()->json(new ProductResource($product), 201);
|
||||
}
|
||||
}
|
||||
|
||||
class ProductService
|
||||
{
|
||||
public function create(array $data): Product
|
||||
{
|
||||
$product = $this->repository->create($data);
|
||||
$this->clearCache();
|
||||
ProductCreated::dispatch($product);
|
||||
$this->notifyVendor($product);
|
||||
return $product;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Repository Pattern (Mandatory for Data Access)
|
||||
|
||||
```php
|
||||
// ❌ BAD: Query in controller or service
|
||||
$products = Product::where('active', true)->paginate(20);
|
||||
|
||||
// ✅ GOOD: Query in repository
|
||||
interface ProductRepositoryInterface
|
||||
{
|
||||
public function listActive(int $perPage = 20): LengthAwarePaginator;
|
||||
}
|
||||
|
||||
class ProductRepository implements ProductRepositoryInterface
|
||||
{
|
||||
public function __construct(private Product $model) {}
|
||||
|
||||
public function listActive(int $perPage = 20): LengthAwarePaginator
|
||||
{
|
||||
return $this->model->query()
|
||||
->where('is_active', true)
|
||||
->orderBy('created_at', 'desc')
|
||||
->paginate($perPage);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Cross-Module Communication
|
||||
|
||||
Modules MUST NOT import models or repositories from other modules.
|
||||
|
||||
```
|
||||
❌ Product module imports Order model directly
|
||||
❌ Order module calls ProductRepository directly
|
||||
|
||||
✅ Product module dispatches ProductCreated event
|
||||
✅ Order module listens to ProductCreated event
|
||||
✅ Module boundaries enforced via interfaces
|
||||
```
|
||||
|
||||
## Microservice Readiness
|
||||
|
||||
Every module must be extractable as an independent service:
|
||||
|
||||
1. **Own database migrations**: Module manages its own tables
|
||||
2. **Own routes**: Module registers its own routes
|
||||
3. **Own config**: Module has its own configuration
|
||||
4. **Own tests**: Module tests run independently
|
||||
5. **Interface contracts**: Module exposes interfaces, not implementations
|
||||
|
||||
## File Splitting Rules
|
||||
|
||||
When a file exceeds 100 lines:
|
||||
|
||||
```
|
||||
Original: ProductController.php (250 lines)
|
||||
↓ Split into:
|
||||
ProductController.php # index, show (thin delegates)
|
||||
ProductStoreController.php # store endpoint (thin delegates)
|
||||
ProductUpdateController.php # update endpoint (thin delegates)
|
||||
ProductService.php # business logic (called by all)
|
||||
```
|
||||
|
||||
When a service exceeds 5 methods:
|
||||
|
||||
```
|
||||
Original: ProductService.php (8 methods)
|
||||
↓ Split into:
|
||||
ProductCrudService.php # create, update, delete
|
||||
ProductSearchService.php # list, search, filter
|
||||
ProductPricingService.php # calculatePrice, applyDiscount
|
||||
```
|
||||
|
||||
## Language-Specific Module Patterns
|
||||
|
||||
### Node.js
|
||||
```
|
||||
src/modules/product/
|
||||
├── routes.js
|
||||
├── controller.js
|
||||
├── service.js
|
||||
├── repository.js
|
||||
├── model.js
|
||||
├── validators.js
|
||||
└── __tests__/
|
||||
```
|
||||
|
||||
### Go
|
||||
```
|
||||
internal/product/
|
||||
├── handler.go
|
||||
├── service.go
|
||||
├── repository.go
|
||||
├── model.go
|
||||
└── handler_test.go
|
||||
```
|
||||
|
||||
### Flutter/Dart
|
||||
```
|
||||
lib/features/product/
|
||||
├── data/
|
||||
│ ├── repositories/
|
||||
│ └── models/
|
||||
├── domain/
|
||||
│ ├── entities/
|
||||
│ └── usecases/
|
||||
└── presentation/
|
||||
├── pages/
|
||||
├── widgets/
|
||||
└── providers/
|
||||
```
|
||||
|
||||
## Checklist
|
||||
|
||||
- [ ] Every file under 100 lines
|
||||
- [ ] Every function under 30 lines
|
||||
- [ ] Every class under 5 public methods
|
||||
- [ ] Features organized as modules
|
||||
- [ ] Service layer contains business logic
|
||||
- [ ] Repository layer abstracts data access
|
||||
- [ ] Controllers are thin (5-10 lines per method)
|
||||
- [ ] Cross-module communication via events
|
||||
- [ ] Each module testable independently
|
||||
- [ ] Each module extractable to microservice
|
||||
Reference in New Issue
Block a user