symfonia-ai-tools 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (74) hide show
  1. package/README.md +489 -0
  2. package/bin/cli.mjs +35 -0
  3. package/lib/installer.mjs +495 -0
  4. package/lib/questions.mjs +332 -0
  5. package/lib/ui.mjs +76 -0
  6. package/lib/utils.mjs +231 -0
  7. package/package.json +26 -0
  8. package/templates/base/CLAUDE.md +34 -0
  9. package/templates/base/_ai/_guidelines_header.md +70 -0
  10. package/templates/base/_ai/context/README.md +20 -0
  11. package/templates/base/_ai/prompts/codereview.prompt.md +324 -0
  12. package/templates/base/_ai/prompts/duplicate-code-analysis.prompt.md +128 -0
  13. package/templates/base/_ai/prompts/figma-analysis.prompt.md +155 -0
  14. package/templates/base/_ai/prompts/security-review.prompt.md +46 -0
  15. package/templates/base/_ai/skills/README.md +80 -0
  16. package/templates/base/_ai/skills/TEMPLATE.md +106 -0
  17. package/templates/base/_ai/skills/babysit-prs/SKILL.md +105 -0
  18. package/templates/base/_ai/skills/debug/SKILL.md +93 -0
  19. package/templates/base/_ai/skills/fill-worklogs/SKILL.md +158 -0
  20. package/templates/base/_ai/skills/hotfix/SKILL.md +52 -0
  21. package/templates/base/_ai/skills/jira-task/SKILL.md +170 -0
  22. package/templates/base/_ai/skills/my-prs/SKILL.md +78 -0
  23. package/templates/base/_ai/skills/pr-dashboard/SKILL.md +43 -0
  24. package/templates/base/_ai/skills/pr-prepare/SKILL.md +106 -0
  25. package/templates/base/_ai/skills/refactor/SKILL.md +87 -0
  26. package/templates/base/_ai/skills/write-tests/SKILL.md +109 -0
  27. package/templates/base/_claude/settings.local.json +37 -0
  28. package/templates/base/_cursor/rules/global.mdc +7 -0
  29. package/templates/base/_editorconfig +18 -0
  30. package/templates/base/_gemini/settings.json +3 -0
  31. package/templates/base/_github/copilot-instructions.md +1 -0
  32. package/templates/base/_github/pull_request_template.md +23 -0
  33. package/templates/base/_gitignore +22 -0
  34. package/templates/base/_junie/guidelines.md +1 -0
  35. package/templates/base/commit-instructions.md +92 -0
  36. package/templates/packs/docker/_ai/instructions/docker.instructions.md +193 -0
  37. package/templates/packs/docker/_guidelines.md +10 -0
  38. package/templates/packs/docker/pack.json +8 -0
  39. package/templates/packs/laravel/_ai/instructions/api-resource.instructions.md +251 -0
  40. package/templates/packs/laravel/_ai/instructions/module.instructions.md +133 -0
  41. package/templates/packs/laravel/_ai/instructions/service-repository.instructions.md +215 -0
  42. package/templates/packs/laravel/_ai/instructions/testing.instructions.md +278 -0
  43. package/templates/packs/laravel/_ai/skills/migration/SKILL.md +172 -0
  44. package/templates/packs/laravel/_ai/skills/new-endpoint/SKILL.md +165 -0
  45. package/templates/packs/laravel/_ai/skills/new-module/SKILL.md +208 -0
  46. package/templates/packs/laravel/_ai/skills/queued-job/SKILL.md +248 -0
  47. package/templates/packs/laravel/_ai/skills/testing-feature/SKILL.md +196 -0
  48. package/templates/packs/laravel/_ai/skills/testing-manual/SKILL.md +186 -0
  49. package/templates/packs/laravel/_ai/skills/testing-unit/SKILL.md +200 -0
  50. package/templates/packs/laravel/_guidelines.md +25 -0
  51. package/templates/packs/laravel/pack.json +6 -0
  52. package/templates/packs/playwright/_ai/instructions/playwright.instructions.md +219 -0
  53. package/templates/packs/playwright/_ai/skills/playwright/README.md +194 -0
  54. package/templates/packs/playwright/_ai/skills/playwright/SKILL.md +1245 -0
  55. package/templates/packs/playwright/_ai/skills/playwright-codereview/SKILL.md +642 -0
  56. package/templates/packs/playwright/_ai/skills/playwright-record/README.md +87 -0
  57. package/templates/packs/playwright/_ai/skills/playwright-record/SKILL.md +564 -0
  58. package/templates/packs/playwright/_guidelines.md +12 -0
  59. package/templates/packs/playwright/pack.json +9 -0
  60. package/templates/packs/storybook/_ai/instructions/storybook.instructions.md +181 -0
  61. package/templates/packs/storybook/pack.json +6 -0
  62. package/templates/packs/vitest/_ai/instructions/vitest.instructions.md +688 -0
  63. package/templates/packs/vitest/pack.json +6 -0
  64. package/templates/packs/vue3/_ai/instructions/api.instructions.md +163 -0
  65. package/templates/packs/vue3/_ai/instructions/coding-conventions.instructions.md +160 -0
  66. package/templates/packs/vue3/_ai/instructions/composables.instructions.md +218 -0
  67. package/templates/packs/vue3/_ai/instructions/forms.instructions.md +227 -0
  68. package/templates/packs/vue3/_ai/instructions/store.instructions.md +504 -0
  69. package/templates/packs/vue3/_ai/instructions/vue.instructions.md +339 -0
  70. package/templates/packs/vue3/_ai/skills/api-integration/SKILL.md +195 -0
  71. package/templates/packs/vue3/_ai/skills/new-component/SKILL.md +133 -0
  72. package/templates/packs/vue3/_ai/skills/new-module/SKILL.md +177 -0
  73. package/templates/packs/vue3/_guidelines.md +45 -0
  74. package/templates/packs/vue3/pack.json +11 -0
@@ -0,0 +1,172 @@
1
+ # Skill: Database Migration (Laravel)
2
+
3
+ ## Trigger
4
+ Use when creating or modifying database schema.
5
+
6
+ ## Input
7
+ - Operation: create table / add columns / modify column / rename / drop
8
+ - Table name
9
+ - Column definitions
10
+ - Foreign keys / indexes
11
+
12
+ ## Steps
13
+
14
+ ### 1. Analyze current schema
15
+
16
+ ```bash
17
+ # Check existing table structure
18
+ docker exec {{DOCKER_CONTAINER}} php artisan db:show --table=[table_name]
19
+
20
+ # Check existing migrations for context
21
+ docker exec {{DOCKER_CONTAINER}} find Modules/*/Database/Migrations -name "*.php" | sort
22
+ ```
23
+
24
+ Review the related Model to understand current column constants and casts.
25
+
26
+ ### 2. Create migration
27
+
28
+ ```bash
29
+ docker exec {{DOCKER_CONTAINER}} php artisan make:migration [action]_[table]_table --path=Modules/[Module]/Database/Migrations
30
+ ```
31
+
32
+ Naming conventions:
33
+ - `create_invoices_table` — new table
34
+ - `add_status_to_invoices_table` — add columns
35
+ - `modify_amount_in_invoices_table` — change column type
36
+ - `drop_legacy_field_from_invoices_table` — remove column
37
+
38
+ ### 3. Write migration
39
+
40
+ ```php
41
+ declare(strict_types=1);
42
+
43
+ use Illuminate\Database\Migrations\Migration;
44
+ use Illuminate\Database\Schema\Blueprint;
45
+ use Illuminate\Support\Facades\Schema;
46
+
47
+ return new class extends Migration
48
+ {
49
+ public function up(): void
50
+ {
51
+ // Use Model constants for table/column names
52
+ Schema::create(InvoiceModel::TABLE_NAME, function (Blueprint $table) {
53
+ $table->id();
54
+ $table->string(InvoiceModel::COLUMN_TITLE);
55
+ $table->decimal(InvoiceModel::COLUMN_AMOUNT, 12, 2);
56
+ $table->foreignId(InvoiceModel::COLUMN_USER_ID)
57
+ ->constrained('users')
58
+ ->cascadeOnDelete();
59
+ $table->timestamps();
60
+ $table->softDeletes();
61
+
62
+ // Indexes for frequent queries
63
+ $table->index([InvoiceModel::COLUMN_USER_ID, InvoiceModel::COLUMN_STATUS]);
64
+ });
65
+ }
66
+
67
+ public function down(): void
68
+ {
69
+ Schema::dropIfExists(InvoiceModel::TABLE_NAME);
70
+ }
71
+ };
72
+ ```
73
+
74
+ Rules:
75
+ - Always include `down()` that fully reverses `up()`
76
+ - Use Model column constants (not raw strings)
77
+ - Add `timestamps()` and `softDeletes()` on new tables
78
+ - Add indexes for columns used in WHERE/ORDER BY
79
+ - Use `constrained()` for foreign keys
80
+ - `decimal(name, precision, scale)` for money — never float
81
+
82
+ ### 4. Test migration runs both ways
83
+
84
+ ```bash
85
+ # Run migration
86
+ docker exec {{DOCKER_CONTAINER}} php artisan migrate
87
+
88
+ # Verify table structure
89
+ docker exec {{DOCKER_CONTAINER}} php artisan db:show --table=[table_name]
90
+
91
+ # Rollback
92
+ docker exec {{DOCKER_CONTAINER}} php artisan migrate:rollback --step=1
93
+
94
+ # Run again (confirms both up and down work)
95
+ docker exec {{DOCKER_CONTAINER}} php artisan migrate
96
+ ```
97
+
98
+ ### 5. Update Model
99
+
100
+ Add/update in the Model:
101
+ - Column constants (`COLUMN_*`)
102
+ - `$fillable` array
103
+ - `$casts` array
104
+ - Getter methods
105
+ - Relation methods (if foreign key added)
106
+
107
+ ```php
108
+ // New constants
109
+ public const COLUMN_STATUS = 'status';
110
+
111
+ // Update $fillable
112
+ protected $fillable = [
113
+ // ... existing
114
+ self::COLUMN_STATUS,
115
+ ];
116
+
117
+ // Update $casts
118
+ protected $casts = [
119
+ // ... existing
120
+ self::COLUMN_STATUS => InvoiceStatus::class,
121
+ ];
122
+
123
+ // New getter
124
+ public function getStatus(): InvoiceStatus
125
+ {
126
+ return $this->getAttribute(self::COLUMN_STATUS);
127
+ }
128
+ ```
129
+
130
+ ### 6. Update Factory
131
+
132
+ Add the new columns to the Factory definition:
133
+
134
+ ```php
135
+ public function definition(): array
136
+ {
137
+ return [
138
+ // ... existing
139
+ InvoiceModel::COLUMN_STATUS => $this->faker->randomElement(InvoiceStatus::cases()),
140
+ ];
141
+ }
142
+
143
+ // Add state for specific values
144
+ public function active(): static
145
+ {
146
+ return $this->state(fn () => [
147
+ InvoiceModel::COLUMN_STATUS => InvoiceStatus::ACTIVE,
148
+ ]);
149
+ }
150
+ ```
151
+
152
+ ### 7. Run tests
153
+
154
+ ```bash
155
+ # Full test suite — migration changes can break anything
156
+ docker exec {{DOCKER_CONTAINER}} php artisan test
157
+ ```
158
+
159
+ Fix any broken tests (missing columns in factories, changed types, etc.).
160
+
161
+ ### 8. Verification checklist
162
+
163
+ - [ ] Migration has `declare(strict_types=1)`
164
+ - [ ] `down()` fully reverses `up()`
165
+ - [ ] Uses Model column constants
166
+ - [ ] Foreign keys use `constrained()` with cascade rules
167
+ - [ ] Indexes added for queried columns
168
+ - [ ] Money uses `decimal`, never `float`
169
+ - [ ] Migration runs and rollback works
170
+ - [ ] Model updated: constants, fillable, casts, getters
171
+ - [ ] Factory updated with new columns + states
172
+ - [ ] All tests pass
@@ -0,0 +1,165 @@
1
+ # Skill: New API Endpoint (Laravel)
2
+
3
+ ## Trigger
4
+ Use when adding a new API endpoint to an existing module.
5
+
6
+ ## Input
7
+ - Module name
8
+ - HTTP method + URL (e.g. POST /api/invoices/export)
9
+ - Request payload
10
+ - Response format
11
+ - Authorization rules
12
+
13
+ ## Steps
14
+
15
+ ### 1. Create Form Request
16
+
17
+ ```bash
18
+ docker exec {{DOCKER_CONTAINER}} php artisan make:request [Action][Entity]Request --path=Modules/[Module]/Http/Requests
19
+ ```
20
+
21
+ Define `authorize()` and `rules()`. Use `Rule::in()` for enums, `exists:` for foreign keys.
22
+
23
+ ### 2. Create/Update Controller method
24
+
25
+ If action fits CRUD (index/store/show/update/destroy) → add to existing controller.
26
+ If custom action → create new controller:
27
+
28
+ ```php
29
+ class Export[Entity]Controller extends Controller
30
+ {
31
+ public function __invoke(Export[Entity]Request $request): JsonResponse
32
+ {
33
+ $dto = Export[Entity]DTO::fromRequest($request);
34
+ $result = $this->service->export($dto);
35
+ return Export[Entity]Resource::make($result)->response();
36
+ }
37
+ }
38
+ ```
39
+
40
+ For non-CRUD: prefer single-action controller with `__invoke`.
41
+
42
+ ### 3. Create DTO (if needed)
43
+
44
+ ```php
45
+ readonly class Export[Entity]DTO
46
+ {
47
+ public function __construct(
48
+ public int $userId,
49
+ public Carbon $dateFrom,
50
+ public Carbon $dateTo,
51
+ public string $format,
52
+ ) {}
53
+
54
+ public static function fromRequest(Export[Entity]Request $request): self
55
+ {
56
+ return new self(
57
+ userId: $request->user()->getId(),
58
+ dateFrom: Carbon::parse($request->validated('date_from')),
59
+ dateTo: Carbon::parse($request->validated('date_to')),
60
+ format: $request->validated('format'),
61
+ );
62
+ }
63
+ }
64
+ ```
65
+
66
+ ### 4. Add Service method
67
+
68
+ Add method to existing service. Keep it focused on one operation.
69
+
70
+ ```php
71
+ public function export(Export[Entity]DTO $dto): ExportResult
72
+ {
73
+ $items = $this->queryRepository->getByDateRange(
74
+ $dto->userId,
75
+ $dto->dateFrom,
76
+ $dto->dateTo,
77
+ );
78
+
79
+ // Business logic...
80
+
81
+ return new ExportResult($items, $dto->format);
82
+ }
83
+ ```
84
+
85
+ ### 5. Create Resource (if new response format)
86
+
87
+ ```php
88
+ class Export[Entity]Resource extends JsonResource
89
+ {
90
+ public function toArray($request): array
91
+ {
92
+ return [
93
+ 'url' => $this->getUrl(),
94
+ 'filename' => $this->getFilename(),
95
+ 'size' => $this->getSize(),
96
+ ];
97
+ }
98
+ }
99
+ ```
100
+
101
+ ### 6. Update Policy (if new permission)
102
+
103
+ Add method to existing policy. Register in ServiceProvider via `Gate::define()`.
104
+
105
+ ### 7. Add Route
106
+
107
+ ```php
108
+ // In existing Routes/api.php group
109
+ Route::post('/export', [Export[Entity]Controller::class, '__invoke'])
110
+ ->can('export', [Entity]::class);
111
+ ```
112
+
113
+ ### 8. Write Feature Test
114
+
115
+ ```php
116
+ public function test_user_can_export(): void
117
+ {
118
+ $response = $this->actingAs($this->user)
119
+ ->postJson('/api/[module]/export', [
120
+ 'date_from' => '2025-01-01',
121
+ 'date_to' => '2025-12-31',
122
+ 'format' => 'pdf',
123
+ ]);
124
+
125
+ $response->assertOk()
126
+ ->assertJsonStructure(['data' => ['url', 'filename', 'size']]);
127
+ }
128
+
129
+ public function test_export_validates_input(): void
130
+ {
131
+ $response = $this->actingAs($this->user)
132
+ ->postJson('/api/[module]/export', []);
133
+
134
+ $response->assertUnprocessable()
135
+ ->assertJsonValidationErrors(['date_from', 'date_to', 'format']);
136
+ }
137
+
138
+ public function test_unauthorized_user_cannot_export(): void
139
+ {
140
+ $response = $this->actingAs($this->unauthorizedUser)
141
+ ->postJson('/api/[module]/export', $this->validPayload());
142
+
143
+ $response->assertForbidden();
144
+ }
145
+ ```
146
+
147
+ ### 9. Verify
148
+
149
+ ```bash
150
+ docker exec {{DOCKER_CONTAINER}} php artisan route:list --path=[module]/export
151
+ docker exec {{DOCKER_CONTAINER}} php artisan test --filter=test_user_can_export
152
+ docker exec {{DOCKER_CONTAINER}} php artisan optimize:clear
153
+ ```
154
+
155
+ ### 10. Verification checklist
156
+
157
+ - [ ] Form Request validates all fields
158
+ - [ ] Controller delegates to service (no business logic)
159
+ - [ ] DTO used for data transfer (not raw arrays)
160
+ - [ ] Service method is focused and testable
161
+ - [ ] Resource formats response (no raw model)
162
+ - [ ] Policy checks authorization
163
+ - [ ] Route uses `->can()` for authorization
164
+ - [ ] 3 tests minimum: happy path, validation, authorization
165
+ - [ ] `declare(strict_types=1)` in all new files
@@ -0,0 +1,208 @@
1
+ # Skill: New Module (Laravel)
2
+
3
+ ## Trigger
4
+ Use when creating a new business domain module.
5
+
6
+ ## Input
7
+ - Module name (PascalCase, e.g. "Invoice")
8
+ - Main entity name
9
+ - API endpoints needed
10
+ - Relations to other modules
11
+
12
+ ## Steps
13
+
14
+ ### 1. Generate module skeleton
15
+
16
+ ```bash
17
+ docker exec {{DOCKER_CONTAINER}} php artisan module:make [ModuleName]
18
+ ```
19
+
20
+ ### 2. Create directory structure
21
+
22
+ ```
23
+ Modules/[ModuleName]/
24
+ ├── Config/
25
+ │ └── config.php
26
+ ├── Console/
27
+ ├── Database/
28
+ │ ├── Filters/
29
+ │ ├── Migrations/
30
+ │ ├── Repositories/
31
+ │ │ ├── [Entity]CommandRepository.php # Interface
32
+ │ │ ├── [Entity]QueryRepository.php # Interface
33
+ │ │ ├── Eloquent[Entity]CommandRepository.php
34
+ │ │ └── Eloquent[Entity]QueryRepository.php
35
+ │ ├── Factories/
36
+ │ │ └── [Entity]Factory.php
37
+ │ └── Scopes/
38
+ ├── Domain/
39
+ │ ├── DTO/
40
+ │ │ └── [Entity]DTO.php
41
+ │ ├── Services/
42
+ │ │ └── [Entity]Service.php
43
+ │ ├── Events/
44
+ │ └── ValueObjects/
45
+ ├── Entities/
46
+ │ └── [Entity]Model.php
47
+ ├── Http/
48
+ │ ├── Controllers/
49
+ │ │ └── [Entity]Controller.php
50
+ │ ├── Policies/
51
+ │ │ └── [Entity]Policy.php
52
+ │ ├── Requests/
53
+ │ │ ├── Store[Entity]Request.php
54
+ │ │ ├── Update[Entity]Request.php
55
+ │ │ └── Index[Entity]Request.php
56
+ │ └── Resources/
57
+ │ ├── [Entity]Resource.php
58
+ │ └── [Entity]Collection.php
59
+ ├── Providers/
60
+ │ ├── [ModuleName]ServiceProvider.php
61
+ │ └── RouteServiceProvider.php
62
+ ├── Routes/
63
+ │ └── api.php
64
+ ├── Tests/
65
+ │ ├── Feature/
66
+ │ │ └── [Entity]ControllerTest.php
67
+ │ ├── Unit/
68
+ │ │ └── [Entity]ServiceTest.php
69
+ │ └── Fixtures/
70
+ │ └── [Entity]Fixtures.php
71
+ └── module.json
72
+ ```
73
+
74
+ ### 3. Create Eloquent Model
75
+
76
+ ```php
77
+ declare(strict_types=1);
78
+
79
+ namespace Modules\[ModuleName]\Entities;
80
+
81
+ use Illuminate\Database\Eloquent\Model;
82
+ use Illuminate\Database\Eloquent\SoftDeletes;
83
+ use Illuminate\Database\Eloquent\Factories\HasFactory;
84
+
85
+ class [Entity]Model extends Model
86
+ {
87
+ use HasFactory;
88
+ use SoftDeletes;
89
+
90
+ public const TABLE_NAME = '[table_name]';
91
+ public const COLUMN_ID = 'id';
92
+ public const COLUMN_NAME = 'name';
93
+ // ... column constants
94
+
95
+ public const RELATION_AUTHOR = 'author';
96
+
97
+ protected $table = self::TABLE_NAME;
98
+
99
+ protected $fillable = [
100
+ self::COLUMN_NAME,
101
+ // ...
102
+ ];
103
+
104
+ protected $casts = [
105
+ 'created_at' => 'datetime',
106
+ ];
107
+
108
+ // Getters
109
+ public function getName(): string { return $this->getAttribute(self::COLUMN_NAME); }
110
+
111
+ // Relations
112
+ public function author(): BelongsTo { return $this->belongsTo(User::class, 'user_id'); }
113
+
114
+ // Allowed filters (Spatie)
115
+ public static function allowedFilters(): array { return []; }
116
+ public static function allowedSorts(): array { return []; }
117
+ }
118
+ ```
119
+
120
+ ### 4. Create Migration
121
+
122
+ ```bash
123
+ docker exec {{DOCKER_CONTAINER}} php artisan make:migration create_[table]_table --path=Modules/[ModuleName]/Database/Migrations
124
+ ```
125
+
126
+ Use column constants from model. Always include `timestamps()` and `softDeletes()`.
127
+
128
+ ### 5. Create Repository interfaces + implementations
129
+
130
+ Follow CQRS pattern - separate Command (write) and Query (read) repositories.
131
+ See `service-repository.instructions.md` for patterns.
132
+
133
+ ### 6. Create Service
134
+
135
+ `readonly class` with constructor injection. Business logic only - no HTTP concerns.
136
+
137
+ ### 7. Create DTO
138
+
139
+ `readonly class` with `static fromRequest()` factory method.
140
+
141
+ ### 8. Create Controller
142
+
143
+ CRUD methods only: `index`, `store`, `show`, `update`, `destroy`.
144
+ Delegate to service, return Resources.
145
+
146
+ ### 9. Create Form Requests
147
+
148
+ - `Store[Entity]Request` - create validation
149
+ - `Update[Entity]Request` - update validation
150
+ - `Index[Entity]Request` - list/filter validation
151
+
152
+ ### 10. Create Resources
153
+
154
+ - `[Entity]Resource` - single entity
155
+ - `[Entity]Collection` - paginated list
156
+
157
+ ### 11. Create Policy
158
+
159
+ CRUD methods: `viewAny`, `view`, `create`, `update`, `delete`, `admin`.
160
+
161
+ ### 12. Create Routes
162
+
163
+ ```php
164
+ Route::middleware(['auth:api'])->prefix('[module]')->group(function () {
165
+ Route::get('/', [[Entity]Controller::class, 'index']);
166
+ Route::post('/', [[Entity]Controller::class, 'store']);
167
+ Route::get('/{id}', [[Entity]Controller::class, 'show']);
168
+ Route::put('/{id}', [[Entity]Controller::class, 'update']);
169
+ Route::delete('/{id}', [[Entity]Controller::class, 'destroy']);
170
+ });
171
+ ```
172
+
173
+ ### 13. Register ServiceProvider
174
+
175
+ - Bind repository interfaces to implementations
176
+ - Register policies via Gate
177
+ - Register artisan commands
178
+ - Load migrations
179
+
180
+ ### 14. Create Tests
181
+
182
+ - Feature test for each endpoint (CRUD)
183
+ - Unit test for service logic
184
+ - Use `DatabaseTransactions` trait
185
+ - Create `[Entity]Fixtures` trait with helpers
186
+
187
+ ### 15. Run and verify
188
+
189
+ ```bash
190
+ docker exec {{DOCKER_CONTAINER}} php artisan migrate
191
+ docker exec {{DOCKER_CONTAINER}} php artisan test --filter=[ModuleName]
192
+ docker exec {{DOCKER_CONTAINER}} php artisan route:list --path=[module]
193
+ ```
194
+
195
+ ### 16. Verification checklist
196
+
197
+ - [ ] `declare(strict_types=1)` in all PHP files
198
+ - [ ] Model uses column constants, getters, relation constants
199
+ - [ ] CQRS: separate Command and Query repositories
200
+ - [ ] Service is `readonly class` with constructor injection
201
+ - [ ] DTO is `readonly class` with `fromRequest()`
202
+ - [ ] Controller delegates to service, returns Resources
203
+ - [ ] Form Requests validate all input
204
+ - [ ] Policy covers all CRUD operations
205
+ - [ ] Routes use tuple notation `[Controller::class, 'method']`
206
+ - [ ] ServiceProvider binds interfaces and registers everything
207
+ - [ ] Feature + Unit tests pass
208
+ - [ ] `php artisan optimize:clear` after changes