@baldurpan/create-ai-workflow 0.2.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 (116) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +165 -0
  3. package/dist/agents-block.js +70 -0
  4. package/dist/bin.js +14 -0
  5. package/dist/check/markdown.js +47 -0
  6. package/dist/check/parse.js +113 -0
  7. package/dist/check/rules.js +245 -0
  8. package/dist/cli.js +109 -0
  9. package/dist/commands/check.js +41 -0
  10. package/dist/commands/install.js +76 -0
  11. package/dist/commands/standards-add.js +145 -0
  12. package/dist/commands/update.js +214 -0
  13. package/dist/layout.js +115 -0
  14. package/dist/log.js +20 -0
  15. package/dist/manifest.js +53 -0
  16. package/dist/paths.js +41 -0
  17. package/package.json +37 -0
  18. package/templates/blocks/agents-block.md +30 -0
  19. package/templates/claude/agents/planner.agent.md +60 -0
  20. package/templates/claude/agents/reviewer.agent.md +77 -0
  21. package/templates/context/README.md +81 -0
  22. package/templates/context/plan-template.md +69 -0
  23. package/templates/context/plan-template.notes.md +55 -0
  24. package/templates/context/roles/coder.md +76 -0
  25. package/templates/context/workflow.md +143 -0
  26. package/templates/skills/feature-close/SKILL.md +102 -0
  27. package/templates/skills/feature-implement/SKILL.md +142 -0
  28. package/templates/skills/feature-plan/SKILL.md +138 -0
  29. package/templates/skills/feature-status/SKILL.md +86 -0
  30. package/templates/skills/onboard/SKILL.md +122 -0
  31. package/templates/skills/orchestrate/SKILL.md +92 -0
  32. package/templates/skills/roadmap/SKILL.md +97 -0
  33. package/templates/standards/.source +8 -0
  34. package/templates/standards/README.md +104 -0
  35. package/templates/standards/architecture/api-design.md +212 -0
  36. package/templates/standards/architecture/dependency-boundaries.md +104 -0
  37. package/templates/standards/architecture/feature-driven.md +102 -0
  38. package/templates/standards/architecture/folder-structure.md +108 -0
  39. package/templates/standards/architecture/monorepos.md +107 -0
  40. package/templates/standards/architecture/refactoring.md +97 -0
  41. package/templates/standards/architecture/shared-code.md +81 -0
  42. package/templates/standards/docs/PHP-SPEC.md +1195 -0
  43. package/templates/standards/docs/SPEC.md +540 -0
  44. package/templates/standards/examples/bad/data-fetching.tsx +52 -0
  45. package/templates/standards/examples/bad/derived-state.tsx +60 -0
  46. package/templates/standards/examples/bad/feature-component.tsx +80 -0
  47. package/templates/standards/examples/bad/prop-drilling.tsx +70 -0
  48. package/templates/standards/examples/good/data-fetching.tsx +53 -0
  49. package/templates/standards/examples/good/derived-state.tsx +52 -0
  50. package/templates/standards/examples/good/feature-component.tsx +141 -0
  51. package/templates/standards/examples/good/invoice.schema.ts +20 -0
  52. package/templates/standards/examples/good/prop-drilling.tsx +83 -0
  53. package/templates/standards/philosophy/ai-agent-behavior.md +93 -0
  54. package/templates/standards/philosophy/core-principles.md +49 -0
  55. package/templates/standards/philosophy/incremental-abstraction.md +56 -0
  56. package/templates/standards/philosophy/maintainability.md +66 -0
  57. package/templates/standards/philosophy/readability.md +87 -0
  58. package/templates/standards/php/README.md +62 -0
  59. package/templates/standards/php/anti-patterns.md +259 -0
  60. package/templates/standards/php/architecture.md +241 -0
  61. package/templates/standards/php/frameworks.md +197 -0
  62. package/templates/standards/php/rules.md +205 -0
  63. package/templates/standards/php/security.md +190 -0
  64. package/templates/standards/php/testing.md +139 -0
  65. package/templates/standards/php/tooling.md +245 -0
  66. package/templates/standards/react/accessibility.md +130 -0
  67. package/templates/standards/react/anti-patterns.md +187 -0
  68. package/templates/standards/react/component-design.md +139 -0
  69. package/templates/standards/react/error-boundaries.md +195 -0
  70. package/templates/standards/react/forms.md +147 -0
  71. package/templates/standards/react/hooks.md +88 -0
  72. package/templates/standards/react/memoization.md +87 -0
  73. package/templates/standards/react/state-management.md +123 -0
  74. package/templates/standards/react/testing.md +118 -0
  75. package/templates/standards/react/use-effect.md +110 -0
  76. package/templates/standards/security/api-security.md +136 -0
  77. package/templates/standards/security/auth.md +112 -0
  78. package/templates/standards/security/secrets.md +105 -0
  79. package/templates/standards/security/validation.md +89 -0
  80. package/templates/standards/templates/.editorconfig +16 -0
  81. package/templates/standards/templates/.nvmrc +1 -0
  82. package/templates/standards/templates/AGENTS.md +46 -0
  83. package/templates/standards/templates/CLAUDE.md +3 -0
  84. package/templates/standards/templates/_dot_gitignore +50 -0
  85. package/templates/standards/templates/biome.json +53 -0
  86. package/templates/standards/templates/eslint.config.js +61 -0
  87. package/templates/standards/templates/project-readme.md +76 -0
  88. package/templates/standards/templates/pull-request-template.md +46 -0
  89. package/templates/standards/templates/tsconfig.json +35 -0
  90. package/templates/standards/tooling/biome.md +92 -0
  91. package/templates/standards/tooling/ci.md +128 -0
  92. package/templates/standards/tooling/dates.md +194 -0
  93. package/templates/standards/tooling/dependencies.md +90 -0
  94. package/templates/standards/tooling/nx.md +113 -0
  95. package/templates/standards/tooling/observability.md +183 -0
  96. package/templates/standards/tooling/prisma.md +152 -0
  97. package/templates/standards/tooling/shadcn.md +115 -0
  98. package/templates/standards/tooling/tailwind.md +135 -0
  99. package/templates/standards/tooling/tanstack-query.md +214 -0
  100. package/templates/standards/tooling/tanstack-router.md +365 -0
  101. package/templates/standards/tooling/tanstack.md +31 -0
  102. package/templates/standards/tooling/vite.md +135 -0
  103. package/templates/standards/typescript/anti-patterns.md +107 -0
  104. package/templates/standards/typescript/error-handling.md +216 -0
  105. package/templates/standards/typescript/naming.md +78 -0
  106. package/templates/standards/typescript/rules.md +159 -0
  107. package/templates/standards/typescript/tsconfig/base.json +32 -0
  108. package/templates/standards/typescript/tsconfig/nextjs.json +12 -0
  109. package/templates/standards/typescript/tsconfig/react.json +9 -0
  110. package/templates/standards/typescript/validation.md +104 -0
  111. package/templates/stubs/executors.md +49 -0
  112. package/templates/stubs/findings.md +40 -0
  113. package/templates/stubs/history.md +13 -0
  114. package/templates/stubs/roadmap.md +29 -0
  115. package/templates/stubs/stack.md +35 -0
  116. package/templates/stubs/verify.md +48 -0
@@ -0,0 +1,87 @@
1
+ # Readability
2
+
3
+ ## Core Rule
4
+
5
+ Code is read far more than it is written. Optimize for the reader.
6
+
7
+ ## DO
8
+
9
+ - Write short, focused files with a single primary responsibility
10
+ - Prefer flat over deeply nested logic
11
+ - Use early returns to reduce nesting
12
+ - Keep function bodies short — if it doesn't fit on one screen, consider splitting
13
+ - Express intent in names, not comments
14
+ - Make control flow obvious
15
+
16
+ ## DO NOT
17
+
18
+ - Write comments that explain what the code does (use a better name instead)
19
+ - Chain more than 3–4 operations without an intermediate named variable
20
+ - Use ternaries for non-trivial conditions
21
+ - Nest ternaries
22
+ - Write clever one-liners that require mental parsing
23
+
24
+ ## Comments
25
+
26
+ Write a comment only when the **why** is non-obvious:
27
+ - A hidden constraint or business rule
28
+ - A workaround for a specific bug or browser quirk
29
+ - A subtle invariant that would surprise a reader
30
+
31
+ Do not write comments that describe what the code does. The code already says that.
32
+
33
+ ```ts
34
+ // BAD: explains what
35
+ // increment the counter
36
+ count += 1;
37
+
38
+ // GOOD: explains why
39
+ // Safari fires the resize event on scroll — debounce to avoid layout thrash
40
+ window.addEventListener("resize", debouncedResize);
41
+ ```
42
+
43
+ ## Control Flow
44
+
45
+ Prefer:
46
+
47
+ ```ts
48
+ // early return over nested if
49
+ if (!user) return null;
50
+ if (!user.isActive) return <Suspended />;
51
+
52
+ return <Dashboard user={user} />;
53
+ ```
54
+
55
+ Over:
56
+
57
+ ```ts
58
+ if (user) {
59
+ if (user.isActive) {
60
+ return <Dashboard user={user} />;
61
+ } else {
62
+ return <Suspended />;
63
+ }
64
+ }
65
+ return null;
66
+ ```
67
+
68
+ ## Naming
69
+
70
+ Names should make a reader's job easier:
71
+
72
+ - `isLoading` not `loading` (boolean prefix)
73
+ - `formatCurrency` not `format` (specific action)
74
+ - `selectedUserId` not `id` (entity + role)
75
+ - `InvoiceLineItemRow` not `Row` (full context)
76
+
77
+ ## PRIORITY
78
+
79
+ ```
80
+ Obviousness > Brevity > Cleverness
81
+ ```
82
+
83
+ ## See Also
84
+
85
+ - [`maintainability.md`](maintainability.md) — colocation, deletability
86
+ - [`../typescript/naming.md`](../typescript/naming.md) — naming conventions
87
+ - [`../react/component-design.md`](../react/component-design.md) — file size and decomposition signals
@@ -0,0 +1,62 @@
1
+ # PHP Engineering Standards
2
+
3
+ > **When to load these standards:** Only when the task is explicitly PHP. This repository's primary stack is TypeScript on Node.js. PHP is supported as a secondary track for the rare case where it's the right tool — typically internal tooling, CMS integrations, queue-driven workflows, or PHP-first ecosystems (Laravel/Symfony/Slim projects).
4
+ >
5
+ > **Do not suggest PHP** for a new project, a Node-friendly task, or a TypeScript codebase. If the user wants PHP, they will say so explicitly.
6
+
7
+ ---
8
+
9
+ ## Philosophy
10
+
11
+ Modern PHP is not "sprinkle PHP into HTML templates." A modern PHP codebase is:
12
+
13
+ - Strongly typed wherever possible
14
+ - Layered with clear domain boundaries
15
+ - Framework-agnostic at the domain layer
16
+ - Built around dependency injection
17
+ - Free of global state and magic-heavy abstractions
18
+ - Testable by design
19
+ - Explicit over convenient
20
+
21
+ Treat PHP like C#, Kotlin, Java, or TypeScript backends — structured, typed, layered, observable.
22
+
23
+ ## Baseline for New PHP Projects
24
+
25
+ - PHP 8.3+
26
+ - `declare(strict_types=1);` in every file
27
+ - PHPStan at level max
28
+ - Pint or PHP-CS-Fixer for formatting
29
+ - Pest or PHPUnit for tests
30
+ - Dockerized dev environment
31
+ - PostgreSQL (MySQL acceptable)
32
+ - Redis (for cache + queues)
33
+ - Structured logging
34
+ - CI/CD from day one
35
+
36
+ ## Conditional Loading
37
+
38
+ | If the task involves… | Load… |
39
+ |---|---|
40
+ | Any PHP task | [`rules.md`](rules.md), [`anti-patterns.md`](anti-patterns.md) |
41
+ | Architecture / new module | [`architecture.md`](architecture.md) |
42
+ | Testing | [`testing.md`](testing.md) |
43
+ | Security | [`security.md`](security.md) |
44
+ | Tooling setup (Composer, PHPStan, Pint, Pest, Rector) | [`tooling.md`](tooling.md) |
45
+ | Framework choice or framework-specific patterns | [`frameworks.md`](frameworks.md) |
46
+
47
+ ## Cross-Cutting Topics (Reuse Main Repo)
48
+
49
+ These concepts apply across languages — use the main repo's docs:
50
+
51
+ | Topic | Doc |
52
+ |---|---|
53
+ | Logging, error monitoring, observability | [`../tooling/observability.md`](../tooling/observability.md) |
54
+ | CI gating, PR sizing, squash merges | [`../tooling/ci.md`](../tooling/ci.md) |
55
+ | API design (REST, errors, pagination) | [`../architecture/api-design.md`](../architecture/api-design.md) |
56
+ | Refactoring discipline | [`../architecture/refactoring.md`](../architecture/refactoring.md) |
57
+ | Date/time handling | [`../tooling/dates.md`](../tooling/dates.md) — use the PHP equivalent (`DateTimeImmutable`, Carbon, or Brick\DateTime) |
58
+ | Dependency boundaries (in a modular monolith) | [`../architecture/dependency-boundaries.md`](../architecture/dependency-boundaries.md) |
59
+
60
+ ## Documentation Style
61
+
62
+ Same as the rest of this repo: directive, concise, hierarchical, example-heavy. `## DO` / `## DO NOT` / `## PRIORITY` sections. No prose essays.
@@ -0,0 +1,259 @@
1
+ # PHP Anti-Patterns
2
+
3
+ ## God Arrays
4
+
5
+ ```php
6
+ // BAD — array as data contract; no type safety, no IDE help
7
+ function processUser(array $user): void
8
+ {
9
+ $email = $user['email']; // typo risk, missing key risk
10
+ $name = $user['profile']['name']; // deep array access
11
+ }
12
+
13
+ // GOOD — DTO or value object
14
+ function processUser(User $user): void
15
+ {
16
+ $email = $user->email;
17
+ $name = $user->profile->name;
18
+ }
19
+ ```
20
+
21
+ ## Static Singleton State
22
+
23
+ ```php
24
+ // BAD — hidden global state, untestable
25
+ class Settings
26
+ {
27
+ private static array $values = [];
28
+
29
+ public static function get(string $key): mixed
30
+ {
31
+ return self::$values[$key] ?? null;
32
+ }
33
+ }
34
+
35
+ Settings::get('feature_flag.x');
36
+
37
+ // GOOD — injected dependency
38
+ final class SettingsService
39
+ {
40
+ public function __construct(private readonly SettingsRepository $repo) {}
41
+
42
+ public function get(string $key): mixed
43
+ {
44
+ return $this->repo->find($key);
45
+ }
46
+ }
47
+ ```
48
+
49
+ ## Service Locator / Facade Abuse in Business Code
50
+
51
+ ```php
52
+ // BAD — hidden dependencies, harder to test, magic
53
+ class OrderService
54
+ {
55
+ public function process(Order $order): void
56
+ {
57
+ $payment = app(PaymentGateway::class);
58
+ $logger = resolve(Logger::class);
59
+ DB::transaction(function () use ($order) { /* ... */ });
60
+ Cache::forget("order:{$order->id}");
61
+ }
62
+ }
63
+
64
+ // GOOD — constructor injection
65
+ final class OrderService
66
+ {
67
+ public function __construct(
68
+ private readonly PaymentGateway $payments,
69
+ private readonly LoggerInterface $logger,
70
+ private readonly TransactionManager $transactions,
71
+ private readonly CacheInterface $cache,
72
+ ) {}
73
+ }
74
+ ```
75
+
76
+ ## Generic "Manager" / "Helper" Classes
77
+
78
+ ```php
79
+ // BAD — vague name, accumulates unrelated methods
80
+ class UserManager
81
+ {
82
+ public function get(int $id) { /* ... */ }
83
+ public function update(User $user) { /* ... */ }
84
+ public function sendWelcomeEmail(User $user) { /* ... */ }
85
+ public function exportToCsv(array $users) { /* ... */ }
86
+ // ...
87
+ }
88
+
89
+ // GOOD — focused services named by responsibility
90
+ final class FindUserById { /* ... */ }
91
+ final class UpdateUserProfile { /* ... */ }
92
+ final class SendWelcomeEmail { /* ... */ }
93
+ final class ExportUsersToCsv { /* ... */ }
94
+ ```
95
+
96
+ ## Fat Controllers / Fat Models
97
+
98
+ ```php
99
+ // BAD — business logic in the controller
100
+ class InvoiceController
101
+ {
102
+ public function store(Request $request)
103
+ {
104
+ $data = $request->validate([/* ... */]);
105
+ $invoice = new Invoice($data);
106
+ $tax = $invoice->amount * 0.20;
107
+ $invoice->total = $invoice->amount + $tax;
108
+ $invoice->save();
109
+ Mail::to($invoice->customer->email)->send(new InvoiceCreatedMail($invoice));
110
+ Log::info("invoice.created", ['id' => $invoice->id]);
111
+ return response()->json($invoice);
112
+ }
113
+ }
114
+
115
+ // GOOD — controller delegates to an application handler
116
+ final class CreateInvoiceController
117
+ {
118
+ public function __construct(private readonly CreateInvoiceHandler $handler) {}
119
+
120
+ public function __invoke(CreateInvoiceRequest $request): JsonResponse
121
+ {
122
+ $invoice = $this->handler->handle(CreateInvoiceCommand::fromRequest($request));
123
+ return new JsonResponse(InvoiceResource::from($invoice), 201);
124
+ }
125
+ }
126
+ ```
127
+
128
+ ## Trait Pyramids
129
+
130
+ ```php
131
+ // BAD — traits stacking hidden behavior
132
+ class UserService
133
+ {
134
+ use HasCaching;
135
+ use HasLogging;
136
+ use HasEvents;
137
+ use HasValidation;
138
+ use HasNotifications;
139
+ use HasRetries;
140
+ // What does this class actually do? Where does behavior come from?
141
+ }
142
+
143
+ // GOOD — composition
144
+ final class UserService
145
+ {
146
+ public function __construct(
147
+ private readonly Cache $cache,
148
+ private readonly LoggerInterface $logger,
149
+ private readonly EventDispatcher $events,
150
+ ) {}
151
+ }
152
+ ```
153
+
154
+ Use traits only for genuinely cross-cutting *implementation details* — not for sharing business behavior.
155
+
156
+ ## Deep Inheritance
157
+
158
+ ```php
159
+ // BAD — design smell
160
+ abstract class BaseController { /* ... */ }
161
+ abstract class ApiController extends BaseController { /* ... */ }
162
+ abstract class VersionedController extends ApiController { /* ... */ }
163
+ class UserController extends VersionedController { /* ... */ }
164
+
165
+ // GOOD — composition, often via middleware or invoke handlers
166
+ final class UserController
167
+ {
168
+ public function __construct(
169
+ private readonly ApiResponseFactory $responses,
170
+ private readonly UserFinder $users,
171
+ ) {}
172
+ }
173
+ ```
174
+
175
+ ## Exceptions for Control Flow
176
+
177
+ ```php
178
+ // BAD — exception as a return value
179
+ public function findUserByEmail(string $email): User
180
+ {
181
+ $user = $this->db->find($email);
182
+ if (!$user) {
183
+ throw new NotFoundException();
184
+ }
185
+ return $user;
186
+ }
187
+
188
+ // In caller:
189
+ try {
190
+ $user = $service->findUserByEmail($email);
191
+ } catch (NotFoundException) {
192
+ return null; // expected case, not exceptional
193
+ }
194
+
195
+ // GOOD — nullable return for expected absence
196
+ public function findUserByEmail(string $email): ?User
197
+ {
198
+ return $this->db->find($email);
199
+ }
200
+ ```
201
+
202
+ Reserve exceptions for genuinely exceptional situations: infrastructure failure, invariant violation, security breach.
203
+
204
+ ## Mixed HTML/PHP
205
+
206
+ ```php
207
+ <!-- BAD — PHP and HTML interleaved in business logic -->
208
+ <?php
209
+ $users = DB::query("SELECT * FROM users");
210
+ foreach ($users as $u) {
211
+ if ($u->active) {
212
+ echo "<div>" . htmlspecialchars($u->name) . "</div>";
213
+ }
214
+ }
215
+ ?>
216
+ ```
217
+
218
+ Use a template engine (Blade, Twig) for HTML. Keep PHP business logic in classes. Better yet, render the frontend in a SPA or HTMX layer.
219
+
220
+ ## Ignoring Static Analysis
221
+
222
+ ```php
223
+ // BAD — silently passing untyped data; PHPStan would catch this
224
+ function calculate($data)
225
+ {
226
+ return $data['amount'] * $data['tax_rate'];
227
+ }
228
+
229
+ // GOOD — typed and PHPStan-verifiable
230
+ function calculate(InvoiceData $data): Money
231
+ {
232
+ return $data->amount->multiply($data->taxRate);
233
+ }
234
+ ```
235
+
236
+ Without PHPStan at high levels, "modern PHP" is incomplete. See [`tooling.md`](tooling.md).
237
+
238
+ ## Generic CRUD Repositories
239
+
240
+ See [`architecture.md`](architecture.md) for the full pattern. Short version:
241
+
242
+ ```php
243
+ // BAD
244
+ $user = $userRepository->find($id);
245
+ $userRepository->save($user);
246
+
247
+ // Just use the ORM directly for this:
248
+ $user = User::find($id);
249
+ $user->save();
250
+
251
+ // Build a repository only when it expresses domain meaning:
252
+ $subscribers = $userRepository->findActiveSubscribers();
253
+ ```
254
+
255
+ ## See Also
256
+
257
+ - [`rules.md`](rules.md) — the positive patterns
258
+ - [`architecture.md`](architecture.md) — layers, DI, value objects
259
+ - [`tooling.md`](tooling.md) — PHPStan to catch many of these automatically
@@ -0,0 +1,241 @@
1
+ # PHP Architecture
2
+
3
+ ## Core Rules
4
+
5
+ - Default to a **modular monolith** with domain-driven boundaries
6
+ - Separate **Domain**, **Application**, **Infrastructure**, and **Presentation** layers
7
+ - Domain layer never imports framework code
8
+ - Use **constructor injection** for all dependencies — no service locators, no global helpers, no static singletons
9
+ - Keep controllers and handlers thin
10
+
11
+ ## Project Structure
12
+
13
+ ### Standard (DDD-flavored)
14
+
15
+ ```
16
+ src/
17
+ Domain/ ← business rules, entities, value objects, domain services
18
+ Application/ ← use case orchestration (commands, queries, handlers)
19
+ Infrastructure/ ← database, cache, external APIs, framework adapters
20
+ Presentation/ ← controllers, HTTP, validation, serialization
21
+ config/
22
+ bootstrap/
23
+ public/
24
+ storage/
25
+ tests/
26
+ ```
27
+
28
+ ### Lightweight (smaller projects)
29
+
30
+ ```
31
+ src/
32
+ Core/
33
+ Services/
34
+ Repositories/
35
+ Http/
36
+ Support/
37
+ ```
38
+
39
+ Prefer clear boundaries over deep nesting. If you find yourself creating `src/Everything/Managers/Helpers/Utilities/Common/Shared/`, the architecture has become unclear.
40
+
41
+ ## Layer Responsibilities
42
+
43
+ ### Domain
44
+
45
+ Contains the business model. Pure PHP. No framework imports.
46
+
47
+ - Entities (`Order`, `Invoice`, `Subscription`)
48
+ - Value objects (`Money`, `EmailAddress`)
49
+ - Domain services (logic that doesn't naturally fit on an entity)
50
+ - Domain events (`InvoicePaid`, `SubscriptionCancelled`)
51
+
52
+ Must NOT depend on:
53
+ - Frameworks (Laravel, Symfony)
54
+ - HTTP
55
+ - Databases
56
+ - Redis
57
+ - Queues
58
+ - External APIs
59
+
60
+ ### Application
61
+
62
+ Coordinates use cases. Thin orchestration.
63
+
64
+ - Commands (`CreateInvoice`, `RefundOrder`) — write operations
65
+ - Queries (`GetActiveSubscribers`) — read operations
66
+ - Handlers (one per command/query)
67
+ - Transactional boundaries
68
+
69
+ The Application layer calls domain services and infrastructure adapters. It doesn't contain business logic itself.
70
+
71
+ ### Infrastructure
72
+
73
+ Framework-aware glue.
74
+
75
+ - Database access (Eloquent, Doctrine, raw PDO)
76
+ - Cache (Redis adapters)
77
+ - External API clients
78
+ - Queue adapters
79
+ - Email sender implementations
80
+ - Framework integration (service providers, container bindings)
81
+
82
+ ### Presentation
83
+
84
+ The edge.
85
+
86
+ - Controllers (HTTP entry points)
87
+ - Form requests / request DTOs
88
+ - Response serialization
89
+ - API resource transformers
90
+
91
+ Keep controllers thin:
92
+
93
+ ```php
94
+ final class CreateInvoiceController
95
+ {
96
+ public function __construct(
97
+ private readonly CreateInvoiceHandler $handler,
98
+ ) {}
99
+
100
+ public function __invoke(CreateInvoiceRequest $request): JsonResponse
101
+ {
102
+ $invoice = $this->handler->handle(CreateInvoiceCommand::fromRequest($request));
103
+ return new JsonResponse(InvoiceResource::from($invoice), 201);
104
+ }
105
+ }
106
+ ```
107
+
108
+ ## Dependency Injection
109
+
110
+ ### Constructor Injection (Preferred)
111
+
112
+ ```php
113
+ final class OrderService
114
+ {
115
+ public function __construct(
116
+ private readonly PaymentGateway $payments,
117
+ private readonly OrderRepository $orders,
118
+ private readonly EventDispatcher $events,
119
+ ) {}
120
+ }
121
+ ```
122
+
123
+ ### Avoid
124
+
125
+ - `app()`, `resolve()`, `Container::get()` inside business code (service locator)
126
+ - Facades inside domain or application layers
127
+ - `static` factory methods that reach into the container
128
+ - Global helpers (`auth()`, `request()`, `now()`) in domain/application code
129
+
130
+ Constructor injection makes dependencies explicit, testable, and substitutable.
131
+
132
+ ## Value Objects
133
+
134
+ Wrap primitives that have rules or constraints:
135
+
136
+ ```php
137
+ final readonly class EmailAddress
138
+ {
139
+ public function __construct(public string $value)
140
+ {
141
+ if (!filter_var($value, FILTER_VALIDATE_EMAIL)) {
142
+ throw new InvalidArgumentException("Invalid email: $value");
143
+ }
144
+ }
145
+
146
+ public function __toString(): string
147
+ {
148
+ return $this->value;
149
+ }
150
+ }
151
+ ```
152
+
153
+ The value object guarantees its invariants — once you hold one, you know it's valid.
154
+
155
+ ## DTOs
156
+
157
+ For boundaries — HTTP requests, queue jobs, service-to-service calls:
158
+
159
+ ```php
160
+ final readonly class CreateUserDTO
161
+ {
162
+ public function __construct(
163
+ public string $name,
164
+ public EmailAddress $email,
165
+ ) {}
166
+ }
167
+ ```
168
+
169
+ DTOs are simple data carriers. They don't have business behavior. Methods are limited to construction (`fromRequest`, `fromArray`) and serialization (`toArray`).
170
+
171
+ ## Repositories
172
+
173
+ Repositories are useful **only** when they encode domain meaning. Generic CRUD wrappers are not useful.
174
+
175
+ ```php
176
+ // BAD — generic CRUD, mirrors ORM
177
+ interface UserRepository
178
+ {
179
+ public function find(int $id): ?User;
180
+ public function save(User $user): void;
181
+ public function delete(User $user): void;
182
+ }
183
+
184
+ // GOOD — domain-shaped queries
185
+ interface UserRepository
186
+ {
187
+ public function findActiveSubscribers(): UserCollection;
188
+ public function findByEmail(EmailAddress $email): ?User;
189
+ public function countNewThisMonth(): int;
190
+ }
191
+ ```
192
+
193
+ If a repository's methods read like an ORM, don't bother — use the ORM directly.
194
+
195
+ ## Async Processing
196
+
197
+ Use queues for:
198
+ - Email and notifications
199
+ - Webhook dispatch
200
+ - Image / video / file processing
201
+ - AI jobs (inference, embedding pipelines)
202
+ - Reports
203
+ - Any long-running operation
204
+
205
+ Common queue backends: Redis, RabbitMQ, SQS. Laravel Horizon provides excellent queue observability.
206
+
207
+ Avoid synchronous HTTP chains for work that doesn't need to be inline.
208
+
209
+ ## Modular Monolith First
210
+
211
+ A well-structured modular monolith outperforms poorly-managed microservices in almost every case.
212
+
213
+ - Start as a single deployable
214
+ - Enforce module boundaries internally
215
+ - Extract a service only when there's a clear scaling or team-ownership reason
216
+
217
+ See [`../architecture/refactoring.md`](../architecture/refactoring.md) — extraction is a refactor, not a fresh build.
218
+
219
+ ## DO NOT
220
+
221
+ - Put business logic in routes or controllers
222
+ - Make the domain layer depend on a framework
223
+ - Reach for CQRS, event sourcing, or microservices because they "sound advanced"
224
+ - Build deep inheritance chains (`BaseController → ApiController → VersionedController → UserController`)
225
+ - Use traits to share business behavior — use composition
226
+
227
+ ## PRIORITY
228
+
229
+ ```
230
+ Layered boundaries > Framework convenience
231
+ Constructor injection > Service locator / globals
232
+ Domain-shaped repositories > Generic CRUD wrappers
233
+ Modular monolith > Premature microservices
234
+ ```
235
+
236
+ ## See Also
237
+
238
+ - [`rules.md`](rules.md) — strict typing for the layered code
239
+ - [`anti-patterns.md`](anti-patterns.md) — what breaks layered architecture
240
+ - [`frameworks.md`](frameworks.md) — framework-specific guidance
241
+ - [`../architecture/refactoring.md`](../architecture/refactoring.md) — extracting modules