cc-codeconductor 0.2.9 → 0.3.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 (143) hide show
  1. package/README.md +105 -25
  2. package/dist/index.js +662 -291
  3. package/package.json +1 -1
  4. package/presets/agy/AGENTS.md +365 -0
  5. package/presets/agy/README.md +47 -0
  6. package/presets/agy/hooks.json +30 -0
  7. package/presets/agy/mcp_config.json +3 -0
  8. package/presets/agy/rules/commit-style.md +1 -0
  9. package/presets/agy/rules/graphify.md +14 -0
  10. package/presets/agy/scripts/post-tool.sh +25 -0
  11. package/presets/agy/scripts/pre-tool.sh +56 -0
  12. package/presets/agy/settings.json +8 -0
  13. package/presets/agy/skills/cc-api-contract/SKILL.md +71 -0
  14. package/presets/agy/skills/cc-db-migration/SKILL.md +70 -0
  15. package/presets/agy/skills/cc-feature/SKILL.md +115 -0
  16. package/presets/agy/skills/cc-fix/SKILL.md +124 -0
  17. package/presets/agy/skills/cc-pagespeed/SKILL.md +101 -0
  18. package/presets/agy/skills/cc-refactor/SKILL.md +149 -0
  19. package/presets/agy/skills/cc-review/SKILL.md +142 -0
  20. package/presets/agy/skills/cc-tdd-cycle/SKILL.md +226 -0
  21. package/presets/agy/skills/cc-test-plan/SKILL.md +145 -0
  22. package/presets/agy/skills/commit/SKILL.md +5 -0
  23. package/presets/agy/workflows/cc-api-contract.md +71 -0
  24. package/presets/agy/workflows/cc-db-migration.md +70 -0
  25. package/presets/agy/workflows/cc-feature.md +115 -0
  26. package/presets/agy/workflows/cc-fix.md +124 -0
  27. package/presets/agy/workflows/cc-pagespeed.md +101 -0
  28. package/presets/agy/workflows/cc-refactor.md +149 -0
  29. package/presets/agy/workflows/cc-review.md +142 -0
  30. package/presets/agy/workflows/cc-tdd-cycle.md +226 -0
  31. package/presets/agy/workflows/cc-test-plan.md +145 -0
  32. package/presets/agy/workflows/commit.md +1 -0
  33. package/presets/claude/CLAUDE.md +47 -3
  34. package/presets/claude/claude.json +6 -0
  35. package/presets/claude/commands/cc/pagespeed.md +103 -0
  36. package/presets/claude/settings.json +249 -2
  37. package/presets/claude/skills/android/SKILL.md +119 -0
  38. package/presets/claude/skills/conductor-setup/SKILL.md +125 -0
  39. package/presets/claude/skills/find-skills/SKILL.md +142 -0
  40. package/presets/claude/skills/laravel-specialist/SKILL.md +264 -0
  41. package/presets/claude/skills/laravel-specialist/references/eloquent.md +351 -0
  42. package/presets/claude/skills/laravel-specialist/references/livewire.md +512 -0
  43. package/presets/claude/skills/laravel-specialist/references/queues.md +423 -0
  44. package/presets/claude/skills/laravel-specialist/references/routing.md +362 -0
  45. package/presets/claude/skills/laravel-specialist/references/testing.md +522 -0
  46. package/presets/claude/skills/multi-agent-orchestration/README.md +144 -0
  47. package/presets/claude/skills/multi-agent-orchestration/SKILL.md +579 -0
  48. package/presets/claude/skills/multi-agent-orchestration/examples/framework_implementations.py +362 -0
  49. package/presets/claude/skills/multi-agent-orchestration/examples/orchestration_patterns.py +411 -0
  50. package/presets/claude/skills/multi-agent-orchestration/scripts/agent_communication.py +334 -0
  51. package/presets/claude/skills/multi-agent-orchestration/scripts/benchmarking.py +341 -0
  52. package/presets/claude/skills/multi-agent-orchestration/scripts/workflow_management.py +334 -0
  53. package/presets/claude/skills/pagespeed-insights/SKILL.md +443 -0
  54. package/presets/claude/skills/pagespeed-insights/reference.md +50 -0
  55. package/presets/claude/skills/pagespeed-perf/SKILL.md +279 -0
  56. package/presets/claude/skills/php-pro/SKILL.md +208 -0
  57. package/presets/claude/skills/php-pro/references/async-patterns.md +412 -0
  58. package/presets/claude/skills/php-pro/references/laravel-patterns.md +377 -0
  59. package/presets/claude/skills/php-pro/references/modern-php-features.md +323 -0
  60. package/presets/claude/skills/php-pro/references/symfony-patterns.md +466 -0
  61. package/presets/claude/skills/php-pro/references/testing-quality.md +466 -0
  62. package/presets/claude/skills/workflow-orchestration-patterns/SKILL.md +98 -0
  63. package/presets/claude/skills/workflow-orchestration-patterns/references/details.md +223 -0
  64. package/presets/codex/AGENTS.md +38 -14
  65. package/presets/codex/skills/android/SKILL.md +119 -0
  66. package/presets/codex/skills/conductor-setup/SKILL.md +125 -0
  67. package/presets/codex/skills/find-skills/SKILL.md +142 -0
  68. package/presets/codex/skills/laravel-specialist/SKILL.md +264 -0
  69. package/presets/codex/skills/laravel-specialist/references/eloquent.md +351 -0
  70. package/presets/codex/skills/laravel-specialist/references/livewire.md +512 -0
  71. package/presets/codex/skills/laravel-specialist/references/queues.md +423 -0
  72. package/presets/codex/skills/laravel-specialist/references/routing.md +362 -0
  73. package/presets/codex/skills/laravel-specialist/references/testing.md +522 -0
  74. package/presets/codex/skills/multi-agent-orchestration/README.md +144 -0
  75. package/presets/codex/skills/multi-agent-orchestration/SKILL.md +579 -0
  76. package/presets/codex/skills/multi-agent-orchestration/examples/framework_implementations.py +362 -0
  77. package/presets/codex/skills/multi-agent-orchestration/examples/orchestration_patterns.py +411 -0
  78. package/presets/codex/skills/multi-agent-orchestration/scripts/agent_communication.py +334 -0
  79. package/presets/codex/skills/multi-agent-orchestration/scripts/benchmarking.py +341 -0
  80. package/presets/codex/skills/multi-agent-orchestration/scripts/workflow_management.py +334 -0
  81. package/presets/codex/skills/pagespeed-insights/SKILL.md +443 -0
  82. package/presets/codex/skills/pagespeed-insights/reference.md +50 -0
  83. package/presets/codex/skills/pagespeed-perf/SKILL.md +279 -0
  84. package/presets/codex/skills/php-pro/SKILL.md +208 -0
  85. package/presets/codex/skills/php-pro/references/async-patterns.md +412 -0
  86. package/presets/codex/skills/php-pro/references/laravel-patterns.md +377 -0
  87. package/presets/codex/skills/php-pro/references/modern-php-features.md +323 -0
  88. package/presets/codex/skills/php-pro/references/symfony-patterns.md +466 -0
  89. package/presets/codex/skills/php-pro/references/testing-quality.md +466 -0
  90. package/presets/codex/skills/workflow-orchestration-patterns/SKILL.md +98 -0
  91. package/presets/codex/skills/workflow-orchestration-patterns/references/details.md +223 -0
  92. package/presets/opencode/README.md +11 -10
  93. package/presets/opencode/agents/orchestrator.md +121 -1
  94. package/presets/opencode/agents/reviewer.md +31 -0
  95. package/presets/opencode/commands/cc-pagespeed.md +100 -0
  96. package/presets/opencode/prompts/v0.3.0/architect.md +221 -0
  97. package/presets/opencode/prompts/v0.3.0/docs.md +189 -0
  98. package/presets/opencode/prompts/v0.3.0/implementer.md +162 -0
  99. package/presets/opencode/prompts/v0.3.0/orchestrator.md +360 -0
  100. package/presets/opencode/prompts/v0.3.0/repo-explorer.md +110 -0
  101. package/presets/opencode/prompts/v0.3.0/reviewer.md +225 -0
  102. package/presets/opencode/prompts/v0.3.0/task-coach.md +155 -0
  103. package/presets/opencode/prompts/v0.3.0/tester.md +251 -0
  104. package/presets/opencode/skills/android/SKILL.md +119 -0
  105. package/presets/opencode/skills/conductor-setup/SKILL.md +125 -0
  106. package/presets/opencode/skills/find-skills/SKILL.md +142 -0
  107. package/presets/opencode/skills/laravel-specialist/SKILL.md +264 -0
  108. package/presets/opencode/skills/laravel-specialist/references/eloquent.md +351 -0
  109. package/presets/opencode/skills/laravel-specialist/references/livewire.md +512 -0
  110. package/presets/opencode/skills/laravel-specialist/references/queues.md +423 -0
  111. package/presets/opencode/skills/laravel-specialist/references/routing.md +362 -0
  112. package/presets/opencode/skills/laravel-specialist/references/testing.md +522 -0
  113. package/presets/opencode/skills/multi-agent-orchestration/README.md +144 -0
  114. package/presets/opencode/skills/multi-agent-orchestration/SKILL.md +579 -0
  115. package/presets/opencode/skills/multi-agent-orchestration/examples/framework_implementations.py +362 -0
  116. package/presets/opencode/skills/multi-agent-orchestration/examples/orchestration_patterns.py +411 -0
  117. package/presets/opencode/skills/multi-agent-orchestration/scripts/agent_communication.py +334 -0
  118. package/presets/opencode/skills/multi-agent-orchestration/scripts/benchmarking.py +341 -0
  119. package/presets/opencode/skills/multi-agent-orchestration/scripts/workflow_management.py +334 -0
  120. package/presets/opencode/skills/pagespeed-insights/SKILL.md +443 -0
  121. package/presets/opencode/skills/pagespeed-insights/reference.md +50 -0
  122. package/presets/opencode/skills/pagespeed-perf/SKILL.md +279 -0
  123. package/presets/opencode/skills/php-pro/SKILL.md +208 -0
  124. package/presets/opencode/skills/php-pro/references/async-patterns.md +412 -0
  125. package/presets/opencode/skills/php-pro/references/laravel-patterns.md +377 -0
  126. package/presets/opencode/skills/php-pro/references/modern-php-features.md +323 -0
  127. package/presets/opencode/skills/php-pro/references/symfony-patterns.md +466 -0
  128. package/presets/opencode/skills/php-pro/references/testing-quality.md +466 -0
  129. package/presets/opencode/skills/workflow-orchestration-patterns/SKILL.md +98 -0
  130. package/presets/opencode/skills/workflow-orchestration-patterns/references/details.md +223 -0
  131. package/presets/seo-hotel/commands/cc-seo-audit.md +17 -9
  132. package/presets/seo-hotel/settings.json +225 -0
  133. package/presets/seo-hotel/skills/find-skills/SKILL.md +142 -0
  134. package/presets/seo-hotel/skills/pagespeed-insights/SKILL.md +443 -0
  135. package/presets/seo-hotel/skills/pagespeed-insights/reference.md +50 -0
  136. package/src/presets/manifests/agy.yml +38 -3
  137. package/src/presets/manifests/claude.yml +8 -2
  138. package/src/presets/manifests/codex.yml +3 -2
  139. package/src/presets/manifests/cursor.yml +3 -2
  140. package/src/presets/manifests/gemini.yml +3 -2
  141. package/src/presets/manifests/opencode.yml +7 -2
  142. package/src/presets/models/agy.yml +16 -0
  143. package/src/presets/models/opencode.yml +6 -6
@@ -0,0 +1,466 @@
1
+ # Testing & Quality Assurance
2
+
3
+ ## PHPUnit with Strict Types
4
+
5
+ ```php
6
+ <?php
7
+
8
+ declare(strict_types=1);
9
+
10
+ namespace Tests\Unit\Service;
11
+
12
+ use App\Repository\UserRepositoryInterface;
13
+ use App\Service\UserService;
14
+ use App\Service\EmailService;
15
+ use PHPUnit\Framework\TestCase;
16
+ use PHPUnit\Framework\MockObject\MockObject;
17
+
18
+ final class UserServiceTest extends TestCase
19
+ {
20
+ private UserRepositoryInterface&MockObject $userRepository;
21
+ private EmailService&MockObject $emailService;
22
+ private UserService $userService;
23
+
24
+ protected function setUp(): void
25
+ {
26
+ $this->userRepository = $this->createMock(UserRepositoryInterface::class);
27
+ $this->emailService = $this->createMock(EmailService::class);
28
+ $this->userService = new UserService(
29
+ $this->userRepository,
30
+ $this->emailService
31
+ );
32
+ }
33
+
34
+ public function testCreateUserSuccessfully(): void
35
+ {
36
+ $email = 'test@example.com';
37
+ $password = 'SecurePass123!';
38
+
39
+ $this->userRepository
40
+ ->expects($this->once())
41
+ ->method('findByEmail')
42
+ ->with($email)
43
+ ->willReturn(null);
44
+
45
+ $this->userRepository
46
+ ->expects($this->once())
47
+ ->method('create')
48
+ ->willReturn($this->createUser($email));
49
+
50
+ $this->emailService
51
+ ->expects($this->once())
52
+ ->method('sendWelcomeEmail');
53
+
54
+ $user = $this->userService->createUser($email, $password);
55
+
56
+ $this->assertSame($email, $user->email);
57
+ }
58
+
59
+ public function testCreateUserThrowsExceptionWhenEmailExists(): void
60
+ {
61
+ $this->expectException(\DomainException::class);
62
+ $this->expectExceptionMessage('Email already exists');
63
+
64
+ $this->userRepository
65
+ ->method('findByEmail')
66
+ ->willReturn($this->createUser('test@example.com'));
67
+
68
+ $this->userService->createUser('test@example.com', 'password');
69
+ }
70
+
71
+ private function createUser(string $email): User
72
+ {
73
+ return new User(
74
+ id: 1,
75
+ email: $email,
76
+ password: password_hash('password', PASSWORD_ARGON2ID),
77
+ );
78
+ }
79
+ }
80
+ ```
81
+
82
+ ## Data Providers
83
+
84
+ ```php
85
+ <?php
86
+
87
+ declare(strict_types=1);
88
+
89
+ namespace Tests\Unit\Validator;
90
+
91
+ use App\Validator\EmailValidator;
92
+ use PHPUnit\Framework\Attributes\DataProvider;
93
+ use PHPUnit\Framework\Attributes\Test;
94
+ use PHPUnit\Framework\TestCase;
95
+
96
+ final class EmailValidatorTest extends TestCase
97
+ {
98
+ #[Test]
99
+ #[DataProvider('validEmailProvider')]
100
+ public function itValidatesCorrectEmails(string $email): void
101
+ {
102
+ $validator = new EmailValidator();
103
+ $this->assertTrue($validator->isValid($email));
104
+ }
105
+
106
+ #[Test]
107
+ #[DataProvider('invalidEmailProvider')]
108
+ public function itRejectsInvalidEmails(string $email): void
109
+ {
110
+ $validator = new EmailValidator();
111
+ $this->assertFalse($validator->isValid($email));
112
+ }
113
+
114
+ public static function validEmailProvider(): array
115
+ {
116
+ return [
117
+ ['user@example.com'],
118
+ ['john.doe@company.co.uk'],
119
+ ['test+filter@domain.org'],
120
+ ];
121
+ }
122
+
123
+ public static function invalidEmailProvider(): array
124
+ {
125
+ return [
126
+ ['invalid'],
127
+ ['@example.com'],
128
+ ['user@'],
129
+ ['user space@example.com'],
130
+ ];
131
+ }
132
+ }
133
+ ```
134
+
135
+ ## Laravel Feature Tests
136
+
137
+ ```php
138
+ <?php
139
+
140
+ declare(strict_types=1);
141
+
142
+ namespace Tests\Feature;
143
+
144
+ use App\Models\User;
145
+ use Illuminate\Foundation\Testing\RefreshDatabase;
146
+ use Illuminate\Foundation\Testing\WithFaker;
147
+ use Tests\TestCase;
148
+
149
+ final class UserControllerTest extends TestCase
150
+ {
151
+ use RefreshDatabase, WithFaker;
152
+
153
+ public function testUserCanViewTheirProfile(): void
154
+ {
155
+ $user = User::factory()->create();
156
+
157
+ $response = $this->actingAs($user)->get('/api/users/me');
158
+
159
+ $response->assertOk()
160
+ ->assertJson([
161
+ 'data' => [
162
+ 'id' => $user->id,
163
+ 'email' => $user->email,
164
+ ],
165
+ ]);
166
+ }
167
+
168
+ public function testUserCanUpdateTheirProfile(): void
169
+ {
170
+ $user = User::factory()->create();
171
+ $newName = $this->faker->name();
172
+
173
+ $response = $this->actingAs($user)->putJson('/api/users/me', [
174
+ 'name' => $newName,
175
+ ]);
176
+
177
+ $response->assertOk();
178
+
179
+ $this->assertDatabaseHas('users', [
180
+ 'id' => $user->id,
181
+ 'name' => $newName,
182
+ ]);
183
+ }
184
+
185
+ public function testUnauthorizedUserCannotAccessProfile(): void
186
+ {
187
+ $response = $this->getJson('/api/users/me');
188
+
189
+ $response->assertUnauthorized();
190
+ }
191
+
192
+ public function testValidationFailsWithInvalidData(): void
193
+ {
194
+ $user = User::factory()->create();
195
+
196
+ $response = $this->actingAs($user)->putJson('/api/users/me', [
197
+ 'email' => 'not-an-email',
198
+ ]);
199
+
200
+ $response->assertUnprocessable()
201
+ ->assertJsonValidationErrors(['email']);
202
+ }
203
+ }
204
+ ```
205
+
206
+ ## Pest Testing (Modern Alternative)
207
+
208
+ ```php
209
+ <?php
210
+
211
+ declare(strict_types=1);
212
+
213
+ use App\Models\User;
214
+ use App\Services\UserService;
215
+
216
+ beforeEach(function () {
217
+ $this->userService = app(UserService::class);
218
+ });
219
+
220
+ it('creates a user successfully', function () {
221
+ $user = $this->userService->createUser(
222
+ email: 'test@example.com',
223
+ password: 'SecurePass123!'
224
+ );
225
+
226
+ expect($user)
227
+ ->toBeInstanceOf(User::class)
228
+ ->email->toBe('test@example.com');
229
+ });
230
+
231
+ it('validates email format', function (string $email, bool $valid) {
232
+ $validator = new EmailValidator();
233
+
234
+ expect($validator->isValid($email))->toBe($valid);
235
+ })->with([
236
+ ['test@example.com', true],
237
+ ['invalid', false],
238
+ ['@example.com', false],
239
+ ]);
240
+
241
+ test('authenticated user can view profile', function () {
242
+ $user = User::factory()->create();
243
+
244
+ $this->actingAs($user)
245
+ ->get('/api/users/me')
246
+ ->assertOk()
247
+ ->assertJson(['data' => ['email' => $user->email]]);
248
+ });
249
+
250
+ test('guest cannot access protected routes', function () {
251
+ $this->getJson('/api/users/me')
252
+ ->assertUnauthorized();
253
+ });
254
+ ```
255
+
256
+ ## PHPStan Configuration
257
+
258
+ ```neon
259
+ # phpstan.neon
260
+ parameters:
261
+ level: 9
262
+ paths:
263
+ - src
264
+ - tests
265
+ excludePaths:
266
+ - src/bootstrap.php
267
+ - vendor
268
+ checkMissingIterableValueType: true
269
+ checkGenericClassInNonGenericObjectType: true
270
+ reportUnmatchedIgnoredErrors: true
271
+ tmpDir: var/cache/phpstan
272
+
273
+ ignoreErrors:
274
+ # Ignore specific Laravel magic
275
+ - '#Call to an undefined method Illuminate\\Database\\Eloquent\\Builder#'
276
+
277
+ type_coverage:
278
+ return_type: 100
279
+ param_type: 100
280
+ property_type: 100
281
+
282
+ includes:
283
+ - vendor/phpstan/phpstan-strict-rules/rules.neon
284
+ - vendor/phpstan/phpstan-deprecation-rules/rules.neon
285
+ ```
286
+
287
+ ## PHPStan Annotations
288
+
289
+ ```php
290
+ <?php
291
+
292
+ declare(strict_types=1);
293
+
294
+ namespace App\Repository;
295
+
296
+ use App\Entity\User;
297
+ use Doctrine\ORM\EntityRepository;
298
+
299
+ /**
300
+ * @extends EntityRepository<User>
301
+ */
302
+ final class UserRepository extends EntityRepository
303
+ {
304
+ /**
305
+ * @return User[]
306
+ */
307
+ public function findActive(): array
308
+ {
309
+ return $this->createQueryBuilder('u')
310
+ ->where('u.status = :status')
311
+ ->setParameter('status', 'active')
312
+ ->getQuery()
313
+ ->getResult();
314
+ }
315
+
316
+ /**
317
+ * @param int[] $ids
318
+ * @return User[]
319
+ */
320
+ public function findByIds(array $ids): array
321
+ {
322
+ return $this->createQueryBuilder('u')
323
+ ->where('u.id IN (:ids)')
324
+ ->setParameter('ids', $ids)
325
+ ->getQuery()
326
+ ->getResult();
327
+ }
328
+ }
329
+
330
+ /**
331
+ * @template T
332
+ */
333
+ final readonly class Result
334
+ {
335
+ /**
336
+ * @param T $data
337
+ */
338
+ public function __construct(
339
+ public mixed $data,
340
+ public bool $success,
341
+ ) {}
342
+
343
+ /**
344
+ * @return T
345
+ */
346
+ public function getData(): mixed
347
+ {
348
+ return $this->data;
349
+ }
350
+ }
351
+ ```
352
+
353
+ ## Mockery (Advanced Mocking)
354
+
355
+ ```php
356
+ <?php
357
+
358
+ declare(strict_types=1);
359
+
360
+ namespace Tests\Unit\Service;
361
+
362
+ use App\Repository\UserRepository;
363
+ use App\Service\NotificationService;
364
+ use Mockery;
365
+ use Mockery\Adapter\Phpunit\MockeryPHPUnitIntegration;
366
+ use PHPUnit\Framework\TestCase;
367
+
368
+ final class NotificationServiceTest extends TestCase
369
+ {
370
+ use MockeryPHPUnitIntegration;
371
+
372
+ public function testSendsNotificationToActiveUsers(): void
373
+ {
374
+ $repository = Mockery::mock(UserRepository::class);
375
+ $repository->shouldReceive('findActive')
376
+ ->once()
377
+ ->andReturn([
378
+ $this->createUser('user1@example.com'),
379
+ $this->createUser('user2@example.com'),
380
+ ]);
381
+
382
+ $service = new NotificationService($repository);
383
+ $result = $service->notifyActiveUsers('Important message');
384
+
385
+ $this->assertSame(2, $result->count());
386
+ }
387
+
388
+ public function testHandlesEmailServiceFailure(): void
389
+ {
390
+ $emailService = Mockery::mock(EmailService::class);
391
+ $emailService->shouldReceive('send')
392
+ ->once()
393
+ ->andThrow(new \RuntimeException('Email service down'));
394
+
395
+ $service = new NotificationService($emailService);
396
+
397
+ $this->expectException(\RuntimeException::class);
398
+ $service->sendNotification('test@example.com', 'Hello');
399
+ }
400
+
401
+ private function createUser(string $email): User
402
+ {
403
+ return new User(id: 1, email: $email, password: 'hashed');
404
+ }
405
+ }
406
+ ```
407
+
408
+ ## Code Coverage
409
+
410
+ ```xml
411
+ <!-- phpunit.xml -->
412
+ <?xml version="1.0" encoding="UTF-8"?>
413
+ <phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
414
+ xsi:noNamespaceSchemaLocation="vendor/phpunit/phpunit/phpunit.xsd"
415
+ bootstrap="vendor/autoload.php"
416
+ colors="true"
417
+ failOnRisky="true"
418
+ failOnWarning="true"
419
+ stopOnFailure="false">
420
+ <testsuites>
421
+ <testsuite name="Unit">
422
+ <directory>tests/Unit</directory>
423
+ </testsuite>
424
+ <testsuite name="Feature">
425
+ <directory>tests/Feature</directory>
426
+ </testsuite>
427
+ </testsuites>
428
+ <coverage>
429
+ <include>
430
+ <directory suffix=".php">src</directory>
431
+ </include>
432
+ <exclude>
433
+ <directory>src/bootstrap</directory>
434
+ <file>src/Kernel.php</file>
435
+ </exclude>
436
+ <report>
437
+ <html outputDirectory="coverage/html"/>
438
+ <clover outputFile="coverage/clover.xml"/>
439
+ </report>
440
+ </coverage>
441
+ <php>
442
+ <env name="APP_ENV" value="testing"/>
443
+ <env name="DB_CONNECTION" value="sqlite"/>
444
+ <env name="DB_DATABASE" value=":memory:"/>
445
+ </php>
446
+ </phpunit>
447
+ ```
448
+
449
+ ## Quick Reference
450
+
451
+ | Tool | Purpose | Command |
452
+ |------|---------|---------|
453
+ | PHPUnit | Unit/Feature tests | `./vendor/bin/phpunit` |
454
+ | Pest | Modern testing | `./vendor/bin/pest` |
455
+ | PHPStan | Static analysis | `./vendor/bin/phpstan analyse` |
456
+ | Psalm | Alternative static analysis | `./vendor/bin/psalm` |
457
+ | PHP-CS-Fixer | Code style | `./vendor/bin/php-cs-fixer fix` |
458
+ | PHPMD | Mess detector | `./vendor/bin/phpmd src text cleancode` |
459
+
460
+ | Assertion | PHPUnit | Pest |
461
+ |-----------|---------|------|
462
+ | Equality | `$this->assertSame()` | `expect()->toBe()` |
463
+ | Type | `$this->assertInstanceOf()` | `expect()->toBeInstanceOf()` |
464
+ | Array | `$this->assertContains()` | `expect()->toContain()` |
465
+ | Exception | `$this->expectException()` | `expect()->toThrow()` |
466
+ | Count | `$this->assertCount()` | `expect()->toHaveCount()` |
@@ -0,0 +1,98 @@
1
+ ---
2
+ name: workflow-orchestration-patterns
3
+ description: Design durable workflows with Temporal for distributed systems. Covers workflow vs activity separation, saga patterns, state management, and determinism constraints. Use when building long-running processes, distributed transactions, or microservice orchestration.
4
+ ---
5
+
6
+ # Workflow Orchestration Patterns
7
+
8
+ Master workflow orchestration architecture with Temporal, covering fundamental design decisions, resilience patterns, and best practices for building reliable distributed systems.
9
+
10
+ ## When to Use Workflow Orchestration
11
+
12
+ ### Ideal Use Cases (Source: docs.temporal.io)
13
+
14
+ - **Multi-step processes** spanning machines/services/databases
15
+ - **Distributed transactions** requiring all-or-nothing semantics
16
+ - **Long-running workflows** (hours to years) with automatic state persistence
17
+ - **Failure recovery** that must resume from last successful step
18
+ - **Business processes**: bookings, orders, campaigns, approvals
19
+ - **Entity lifecycle management**: inventory tracking, account management, cart workflows
20
+ - **Infrastructure automation**: CI/CD pipelines, provisioning, deployments
21
+ - **Human-in-the-loop** systems requiring timeouts and escalations
22
+
23
+ ### When NOT to Use
24
+
25
+ - Simple CRUD operations (use direct API calls)
26
+ - Pure data processing pipelines (use Airflow, batch processing)
27
+ - Stateless request/response (use standard APIs)
28
+ - Real-time streaming (use Kafka, event processors)
29
+
30
+ ## Detailed patterns and worked examples
31
+
32
+ Detailed pattern documentation lives in `references/details.md`. Read that file when the navigation tier above is insufficient.
33
+
34
+ ## Best Practices
35
+
36
+ ### Workflow Design
37
+
38
+ 1. **Keep workflows focused** - Single responsibility per workflow
39
+ 2. **Small workflows** - Use child workflows for scalability
40
+ 3. **Clear boundaries** - Workflow orchestrates, activities execute
41
+ 4. **Test locally** - Use time-skipping test environment
42
+
43
+ ### Activity Design
44
+
45
+ 1. **Idempotent operations** - Safe to retry
46
+ 2. **Short-lived** - Seconds to minutes, not hours
47
+ 3. **Timeout configuration** - Always set timeouts
48
+ 4. **Heartbeat for long tasks** - Report progress
49
+ 5. **Error handling** - Distinguish retryable vs non-retryable
50
+
51
+ ### Common Pitfalls
52
+
53
+ **Workflow Violations**:
54
+
55
+ - Using `datetime.now()` instead of `workflow.now()`
56
+ - Threading or async operations in workflow code
57
+ - Calling external APIs directly from workflow
58
+ - Non-deterministic logic in workflows
59
+
60
+ **Activity Mistakes**:
61
+
62
+ - Non-idempotent operations (can't handle retries)
63
+ - Missing timeouts (activities run forever)
64
+ - No error classification (retry validation errors)
65
+ - Ignoring payload limits (2MB per argument)
66
+
67
+ ### Operational Considerations
68
+
69
+ **Monitoring**:
70
+
71
+ - Workflow execution duration
72
+ - Activity failure rates
73
+ - Retry attempts and backoff
74
+ - Pending workflow counts
75
+
76
+ **Scalability**:
77
+
78
+ - Horizontal scaling with workers
79
+ - Task queue partitioning
80
+ - Child workflow decomposition
81
+ - Activity batching when appropriate
82
+
83
+ ## Additional Resources
84
+
85
+ **Official Documentation**:
86
+
87
+ - Temporal Core Concepts: docs.temporal.io/workflows
88
+ - Workflow Patterns: docs.temporal.io/evaluate/use-cases-design-patterns
89
+ - Best Practices: docs.temporal.io/develop/best-practices
90
+ - Saga Pattern: temporal.io/blog/saga-pattern-made-easy
91
+
92
+ **Key Principles**:
93
+
94
+ 1. Workflows = orchestration, Activities = external calls
95
+ 2. Determinism is non-negotiable for workflows
96
+ 3. Idempotency is critical for activities
97
+ 4. State preservation is automatic
98
+ 5. Design for failure and recovery