autoworkflow 3.1.5 → 3.5.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 (123) hide show
  1. package/.claude/commands/analyze.md +19 -0
  2. package/.claude/commands/audit.md +26 -0
  3. package/.claude/commands/build.md +39 -0
  4. package/.claude/commands/commit.md +25 -0
  5. package/.claude/commands/fix.md +23 -0
  6. package/.claude/commands/plan.md +18 -0
  7. package/.claude/commands/suggest.md +23 -0
  8. package/.claude/commands/verify.md +18 -0
  9. package/.claude/hooks/post-bash-router.sh +20 -0
  10. package/.claude/hooks/post-commit.sh +140 -0
  11. package/.claude/hooks/pre-edit.sh +129 -0
  12. package/.claude/hooks/session-check.sh +79 -0
  13. package/.claude/settings.json +40 -6
  14. package/.claude/settings.local.json +3 -1
  15. package/.claude/skills/actix.md +337 -0
  16. package/.claude/skills/alembic.md +504 -0
  17. package/.claude/skills/angular.md +237 -0
  18. package/.claude/skills/api-design.md +187 -0
  19. package/.claude/skills/aspnet-core.md +377 -0
  20. package/.claude/skills/astro.md +245 -0
  21. package/.claude/skills/auth-clerk.md +327 -0
  22. package/.claude/skills/auth-firebase.md +367 -0
  23. package/.claude/skills/auth-nextauth.md +359 -0
  24. package/.claude/skills/auth-supabase.md +368 -0
  25. package/.claude/skills/axum.md +386 -0
  26. package/.claude/skills/blazor.md +456 -0
  27. package/.claude/skills/chi.md +348 -0
  28. package/.claude/skills/code-review.md +133 -0
  29. package/.claude/skills/csharp.md +296 -0
  30. package/.claude/skills/css-modules.md +325 -0
  31. package/.claude/skills/cypress.md +343 -0
  32. package/.claude/skills/debugging.md +133 -0
  33. package/.claude/skills/diesel.md +392 -0
  34. package/.claude/skills/django.md +301 -0
  35. package/.claude/skills/docker.md +319 -0
  36. package/.claude/skills/doctrine.md +473 -0
  37. package/.claude/skills/documentation.md +182 -0
  38. package/.claude/skills/dotnet.md +409 -0
  39. package/.claude/skills/drizzle.md +293 -0
  40. package/.claude/skills/echo.md +321 -0
  41. package/.claude/skills/eloquent.md +256 -0
  42. package/.claude/skills/emotion.md +426 -0
  43. package/.claude/skills/entity-framework.md +370 -0
  44. package/.claude/skills/express.md +316 -0
  45. package/.claude/skills/fastapi.md +329 -0
  46. package/.claude/skills/fastify.md +299 -0
  47. package/.claude/skills/fiber.md +315 -0
  48. package/.claude/skills/flask.md +322 -0
  49. package/.claude/skills/gin.md +342 -0
  50. package/.claude/skills/git.md +116 -0
  51. package/.claude/skills/github-actions.md +353 -0
  52. package/.claude/skills/go.md +377 -0
  53. package/.claude/skills/gorm.md +409 -0
  54. package/.claude/skills/graphql.md +478 -0
  55. package/.claude/skills/hibernate.md +379 -0
  56. package/.claude/skills/hono.md +306 -0
  57. package/.claude/skills/java.md +400 -0
  58. package/.claude/skills/jest.md +313 -0
  59. package/.claude/skills/jpa.md +282 -0
  60. package/.claude/skills/kotlin.md +347 -0
  61. package/.claude/skills/kubernetes.md +363 -0
  62. package/.claude/skills/laravel.md +414 -0
  63. package/.claude/skills/mcp-browser.md +320 -0
  64. package/.claude/skills/mcp-database.md +219 -0
  65. package/.claude/skills/mcp-fetch.md +241 -0
  66. package/.claude/skills/mcp-filesystem.md +204 -0
  67. package/.claude/skills/mcp-github.md +217 -0
  68. package/.claude/skills/mcp-memory.md +240 -0
  69. package/.claude/skills/mcp-search.md +218 -0
  70. package/.claude/skills/mcp-slack.md +262 -0
  71. package/.claude/skills/micronaut.md +388 -0
  72. package/.claude/skills/mongodb.md +319 -0
  73. package/.claude/skills/mongoose.md +355 -0
  74. package/.claude/skills/mysql.md +281 -0
  75. package/.claude/skills/nestjs.md +335 -0
  76. package/.claude/skills/nextjs-app-router.md +260 -0
  77. package/.claude/skills/nextjs-pages.md +172 -0
  78. package/.claude/skills/nuxt.md +202 -0
  79. package/.claude/skills/openapi.md +489 -0
  80. package/.claude/skills/performance.md +199 -0
  81. package/.claude/skills/php.md +398 -0
  82. package/.claude/skills/playwright.md +371 -0
  83. package/.claude/skills/postgresql.md +257 -0
  84. package/.claude/skills/prisma.md +293 -0
  85. package/.claude/skills/pydantic.md +304 -0
  86. package/.claude/skills/pytest.md +313 -0
  87. package/.claude/skills/python.md +272 -0
  88. package/.claude/skills/quarkus.md +377 -0
  89. package/.claude/skills/react.md +230 -0
  90. package/.claude/skills/redis.md +391 -0
  91. package/.claude/skills/refactoring.md +143 -0
  92. package/.claude/skills/remix.md +246 -0
  93. package/.claude/skills/rest-api.md +490 -0
  94. package/.claude/skills/rocket.md +366 -0
  95. package/.claude/skills/rust.md +341 -0
  96. package/.claude/skills/sass.md +380 -0
  97. package/.claude/skills/sea-orm.md +382 -0
  98. package/.claude/skills/security.md +167 -0
  99. package/.claude/skills/sequelize.md +395 -0
  100. package/.claude/skills/spring-boot.md +416 -0
  101. package/.claude/skills/sqlalchemy.md +269 -0
  102. package/.claude/skills/sqlx-rust.md +408 -0
  103. package/.claude/skills/state-jotai.md +346 -0
  104. package/.claude/skills/state-mobx.md +353 -0
  105. package/.claude/skills/state-pinia.md +431 -0
  106. package/.claude/skills/state-redux.md +337 -0
  107. package/.claude/skills/state-tanstack-query.md +434 -0
  108. package/.claude/skills/state-zustand.md +340 -0
  109. package/.claude/skills/styled-components.md +403 -0
  110. package/.claude/skills/svelte.md +238 -0
  111. package/.claude/skills/sveltekit.md +207 -0
  112. package/.claude/skills/symfony.md +437 -0
  113. package/.claude/skills/tailwind.md +279 -0
  114. package/.claude/skills/terraform.md +394 -0
  115. package/.claude/skills/testing-library.md +371 -0
  116. package/.claude/skills/trpc.md +426 -0
  117. package/.claude/skills/typeorm.md +368 -0
  118. package/.claude/skills/vitest.md +330 -0
  119. package/.claude/skills/vue.md +202 -0
  120. package/.claude/skills/warp.md +365 -0
  121. package/README.md +135 -52
  122. package/package.json +1 -1
  123. package/system/triggers.md +152 -11
@@ -0,0 +1,398 @@
1
+ # PHP Skill (PHP 8.2+)
2
+
3
+ ## Constructor Property Promotion
4
+ \`\`\`php
5
+ <?php
6
+
7
+ declare(strict_types=1);
8
+
9
+ // Modern PHP 8+ syntax
10
+ readonly class User
11
+ {
12
+ public function __construct(
13
+ public string $id,
14
+ public string $email,
15
+ public string $name,
16
+ public bool $isActive = true,
17
+ public ?DateTimeImmutable $createdAt = null,
18
+ ) {
19
+ $this->createdAt ??= new DateTimeImmutable();
20
+ }
21
+ }
22
+
23
+ // Service with dependency injection
24
+ final readonly class UserService
25
+ {
26
+ public function __construct(
27
+ private UserRepositoryInterface $repository,
28
+ private PasswordHasherInterface $hasher,
29
+ private LoggerInterface $logger,
30
+ ) {}
31
+
32
+ public function findById(string $id): ?User
33
+ {
34
+ return $this->repository->find($id);
35
+ }
36
+ }
37
+ \`\`\`
38
+
39
+ ## Enums
40
+ \`\`\`php
41
+ <?php
42
+
43
+ // Backed enum
44
+ enum UserStatus: string
45
+ {
46
+ case Active = 'active';
47
+ case Pending = 'pending';
48
+ case Suspended = 'suspended';
49
+ case Deleted = 'deleted';
50
+
51
+ public function label(): string
52
+ {
53
+ return match($this) {
54
+ self::Active => 'Active User',
55
+ self::Pending => 'Awaiting Verification',
56
+ self::Suspended => 'Account Suspended',
57
+ self::Deleted => 'Account Deleted',
58
+ };
59
+ }
60
+
61
+ public function canLogin(): bool
62
+ {
63
+ return $this === self::Active;
64
+ }
65
+ }
66
+
67
+ // Usage
68
+ $status = UserStatus::Active;
69
+ $status->value; // 'active'
70
+ $status->label(); // 'Active User'
71
+
72
+ // From string
73
+ $status = UserStatus::from('active'); // Throws if invalid
74
+ $status = UserStatus::tryFrom('invalid'); // Returns null
75
+ \`\`\`
76
+
77
+ ## Attributes
78
+ \`\`\`php
79
+ <?php
80
+
81
+ use Attribute;
82
+
83
+ // Define attribute
84
+ #[Attribute(Attribute::TARGET_PROPERTY)]
85
+ final readonly class Validate
86
+ {
87
+ public function __construct(
88
+ public string $rule,
89
+ public ?string $message = null,
90
+ ) {}
91
+ }
92
+
93
+ #[Attribute(Attribute::TARGET_METHOD)]
94
+ final readonly class Route
95
+ {
96
+ public function __construct(
97
+ public string $path,
98
+ public string $method = 'GET',
99
+ public array $middleware = [],
100
+ ) {}
101
+ }
102
+
103
+ // Usage
104
+ final class UserController
105
+ {
106
+ #[Route('/users/{id}', 'GET')]
107
+ public function show(string $id): JsonResponse
108
+ {
109
+ // ...
110
+ }
111
+
112
+ #[Route('/users', 'POST', middleware: ['auth'])]
113
+ public function store(Request $request): JsonResponse
114
+ {
115
+ // ...
116
+ }
117
+ }
118
+
119
+ // DTO with validation attributes
120
+ final readonly class CreateUserRequest
121
+ {
122
+ public function __construct(
123
+ #[Validate('email', 'Invalid email format')]
124
+ public string $email,
125
+
126
+ #[Validate('min:2|max:100')]
127
+ public string $name,
128
+
129
+ #[Validate('min:8')]
130
+ public string $password,
131
+ ) {}
132
+ }
133
+ \`\`\`
134
+
135
+ ## Match Expressions
136
+ \`\`\`php
137
+ <?php
138
+
139
+ // Match expression (exhaustive, returns value)
140
+ $message = match($status) {
141
+ UserStatus::Active => 'Welcome back!',
142
+ UserStatus::Pending => 'Please verify your email',
143
+ UserStatus::Suspended => 'Account suspended',
144
+ UserStatus::Deleted => 'Account not found',
145
+ };
146
+
147
+ // With conditions
148
+ $discount = match(true) {
149
+ $total >= 1000 => 0.20,
150
+ $total >= 500 => 0.15,
151
+ $total >= 100 => 0.10,
152
+ default => 0,
153
+ };
154
+
155
+ // Multiple conditions
156
+ $category = match($code) {
157
+ 200, 201, 204 => 'success',
158
+ 400, 401, 403, 404 => 'client_error',
159
+ 500, 502, 503 => 'server_error',
160
+ default => 'unknown',
161
+ };
162
+ \`\`\`
163
+
164
+ ## Null Safety and Error Handling
165
+ \`\`\`php
166
+ <?php
167
+
168
+ // Nullsafe operator
169
+ $country = $user?->address?->country?->name;
170
+
171
+ // Null coalescing
172
+ $name = $user->name ?? 'Anonymous';
173
+ $name ??= 'Default'; // Assignment
174
+
175
+ // Named arguments
176
+ $user = new User(
177
+ id: Uuid::uuid4()->toString(),
178
+ email: $email,
179
+ name: $name,
180
+ isActive: false,
181
+ );
182
+
183
+ // Result pattern for expected failures
184
+ final readonly class Result
185
+ {
186
+ private function __construct(
187
+ public bool $success,
188
+ public mixed $value = null,
189
+ public ?Error $error = null,
190
+ ) {}
191
+
192
+ public static function success(mixed $value): self
193
+ {
194
+ return new self(success: true, value: $value);
195
+ }
196
+
197
+ public static function failure(Error $error): self
198
+ {
199
+ return new self(success: false, error: $error);
200
+ }
201
+
202
+ public function isSuccess(): bool
203
+ {
204
+ return $this->success;
205
+ }
206
+
207
+ public function getOrThrow(): mixed
208
+ {
209
+ if (!$this->success) {
210
+ throw new RuntimeException($this->error->message);
211
+ }
212
+ return $this->value;
213
+ }
214
+ }
215
+
216
+ // Usage
217
+ public function createUser(CreateUserRequest $request): Result
218
+ {
219
+ if ($this->repository->existsByEmail($request->email)) {
220
+ return Result::failure(new Error('email_taken', 'Email already exists'));
221
+ }
222
+
223
+ $user = new User(
224
+ id: Uuid::uuid4()->toString(),
225
+ email: $request->email,
226
+ name: $request->name,
227
+ );
228
+
229
+ $this->repository->save($user);
230
+
231
+ return Result::success($user);
232
+ }
233
+ \`\`\`
234
+
235
+ ## Collections
236
+ \`\`\`php
237
+ <?php
238
+
239
+ // Array functions with arrow functions
240
+ $emails = array_map(fn(User $u) => $u->email, $users);
241
+
242
+ $active = array_filter($users, fn(User $u) => $u->isActive);
243
+
244
+ $total = array_reduce(
245
+ $items,
246
+ fn(float $sum, Item $item) => $sum + $item->price,
247
+ 0.0
248
+ );
249
+
250
+ // Using Collection class (Laravel or custom)
251
+ $users = collect($users)
252
+ ->filter(fn(User $u) => $u->isActive)
253
+ ->map(fn(User $u) => new UserDto($u))
254
+ ->sortByDesc(fn(UserDto $u) => $u->createdAt)
255
+ ->values()
256
+ ->all();
257
+
258
+ // Generator for large datasets
259
+ function processUsers(iterable $users): Generator
260
+ {
261
+ foreach ($users as $user) {
262
+ yield processUser($user);
263
+ }
264
+ }
265
+ \`\`\`
266
+
267
+ ## Interfaces and Traits
268
+ \`\`\`php
269
+ <?php
270
+
271
+ // Interface
272
+ interface UserRepositoryInterface
273
+ {
274
+ public function find(string $id): ?User;
275
+ public function findByEmail(string $email): ?User;
276
+ public function save(User $user): void;
277
+ public function delete(string $id): void;
278
+ }
279
+
280
+ // Trait for common functionality
281
+ trait Timestamps
282
+ {
283
+ public ?DateTimeImmutable $createdAt = null;
284
+ public ?DateTimeImmutable $updatedAt = null;
285
+
286
+ public function touch(): void
287
+ {
288
+ $this->updatedAt = new DateTimeImmutable();
289
+ }
290
+
291
+ public function setCreatedAt(): void
292
+ {
293
+ $this->createdAt ??= new DateTimeImmutable();
294
+ }
295
+ }
296
+
297
+ // Usage
298
+ class Post
299
+ {
300
+ use Timestamps;
301
+
302
+ public function __construct(
303
+ public string $id,
304
+ public string $title,
305
+ public string $content,
306
+ ) {
307
+ $this->setCreatedAt();
308
+ }
309
+ }
310
+ \`\`\`
311
+
312
+ ## Testing with PHPUnit
313
+ \`\`\`php
314
+ <?php
315
+
316
+ use PHPUnit\\Framework\\TestCase;
317
+ use PHPUnit\\Framework\\Attributes\\Test;
318
+ use PHPUnit\\Framework\\Attributes\\DataProvider;
319
+
320
+ final class UserServiceTest extends TestCase
321
+ {
322
+ private UserRepositoryInterface $repository;
323
+ private UserService $service;
324
+
325
+ protected function setUp(): void
326
+ {
327
+ $this->repository = $this->createMock(UserRepositoryInterface::class);
328
+ $this->service = new UserService($this->repository);
329
+ }
330
+
331
+ #[Test]
332
+ public function findsUserById(): void
333
+ {
334
+ $user = new User(id: '1', email: 'test@example.com', name: 'Test');
335
+
336
+ $this->repository
337
+ ->expects($this->once())
338
+ ->method('find')
339
+ ->with('1')
340
+ ->willReturn($user);
341
+
342
+ $result = $this->service->findById('1');
343
+
344
+ $this->assertSame($user, $result);
345
+ }
346
+
347
+ #[Test]
348
+ public function returnsNullWhenUserNotFound(): void
349
+ {
350
+ $this->repository
351
+ ->method('find')
352
+ ->willReturn(null);
353
+
354
+ $result = $this->service->findById('999');
355
+
356
+ $this->assertNull($result);
357
+ }
358
+
359
+ #[Test]
360
+ #[DataProvider('invalidEmailProvider')]
361
+ public function rejectsInvalidEmails(string $email): void
362
+ {
363
+ $this->expectException(ValidationException::class);
364
+
365
+ $this->service->create(new CreateUserRequest(
366
+ email: $email,
367
+ name: 'Test',
368
+ password: 'password123',
369
+ ));
370
+ }
371
+
372
+ public static function invalidEmailProvider(): array
373
+ {
374
+ return [
375
+ 'empty' => [''],
376
+ 'no at sign' => ['invalid'],
377
+ 'no domain' => ['test@'],
378
+ ];
379
+ }
380
+ }
381
+ \`\`\`
382
+
383
+ ## ✅ DO
384
+ - Use \`declare(strict_types=1)\` in all files
385
+ - Use \`readonly\` classes for immutable data
386
+ - Use constructor property promotion
387
+ - Use enums for fixed sets of values
388
+ - Use match expressions instead of switch
389
+ - Use attributes for metadata
390
+ - Follow PSR-12 coding standards
391
+
392
+ ## ❌ DON'T
393
+ - Don't use \`@var\` annotations when types are declared
394
+ - Don't use arrays for typed data (use DTOs/value objects)
395
+ - Don't use \`mixed\` when specific types are possible
396
+ - Don't suppress errors with \`@\`
397
+ - Don't use globals or static state
398
+ - Don't catch \`Exception\` without rethrowing or logging