diff --git a/.github/prompts/actions.prompt.yml b/.github/prompts/actions.prompt.yml deleted file mode 100644 index 8365cbe..0000000 --- a/.github/prompts/actions.prompt.yml +++ /dev/null @@ -1,16 +0,0 @@ -messages: - - role: system - content: | - You are a Laravel developer. Apply these guidelines exactly: - - {{skill_content}} - - Respond with only the requested code. No explanations unless asked. - - role: user - content: | - Write a CreateInvoice Action class. It receives an Order, creates an Invoice, and returns it. - Use execute() method and constructor dependency injection. No HTTP concerns. -model: openai/gpt-4o-mini -modelParameters: - temperature: 0.2 - maxCompletionTokens: 512 diff --git a/.github/prompts/albatros.prompt.yml b/.github/prompts/albatros.prompt.yml deleted file mode 100644 index a7f257d..0000000 --- a/.github/prompts/albatros.prompt.yml +++ /dev/null @@ -1,16 +0,0 @@ -messages: - - role: system - content: | - You are a Laravel developer. Apply these guidelines exactly: - - {{skill_content}} - - Respond with only the requested code. No explanations unless asked. - - role: user - content: | - Write an AlbatrosConnector extending Saloon Connector. Use config('albatros.base_url'), Mandant header, Bearer token. - Use Cache for reference data. German domain terms in DTOs are acceptable. -model: openai/gpt-4o-mini -modelParameters: - temperature: 0.2 - maxCompletionTokens: 512 diff --git a/.github/prompts/blade.prompt.yml b/.github/prompts/blade.prompt.yml deleted file mode 100644 index 4f7402f..0000000 --- a/.github/prompts/blade.prompt.yml +++ /dev/null @@ -1,16 +0,0 @@ -messages: - - role: system - content: | - You are a Laravel developer. Apply these guidelines exactly: - - {{skill_content}} - - Respond with only the requested code. No explanations unless asked. - - role: user - content: | - Write a Blade component that displays a user's name and email. Use {{ }} for escaped output. - No inline style or script tags. Use x-component syntax. -model: openai/gpt-4o-mini -modelParameters: - temperature: 0.2 - maxCompletionTokens: 384 diff --git a/.github/prompts/commands.prompt.yml b/.github/prompts/commands.prompt.yml deleted file mode 100644 index 7339676..0000000 --- a/.github/prompts/commands.prompt.yml +++ /dev/null @@ -1,16 +0,0 @@ -messages: - - role: system - content: | - You are a Laravel developer. Apply these guidelines exactly: - - {{skill_content}} - - Respond with only the requested code. No explanations unless asked. - - role: user - content: | - Write an Artisan command invoices:send-reminders with required email argument and --dry-run option. - Delegate to SendInvoiceReminderAction. Return self::SUCCESS or self::FAILURE. Validate input. -model: openai/gpt-4o-mini -modelParameters: - temperature: 0.2 - maxCompletionTokens: 512 diff --git a/.github/prompts/controllers.prompt.yml b/.github/prompts/controllers.prompt.yml deleted file mode 100644 index 0b30014..0000000 --- a/.github/prompts/controllers.prompt.yml +++ /dev/null @@ -1,16 +0,0 @@ -messages: - - role: system - content: | - You are a Laravel developer. Apply these guidelines exactly: - - {{skill_content}} - - Respond with only the requested code. No explanations unless asked. - - role: user - content: | - Write an invokable StoreInvoiceController that receives StoreInvoiceRequest, calls a CreateInvoice action, - and returns a JsonResponse with InvoiceResource. No business logic in the controller. -model: openai/gpt-4o-mini -modelParameters: - temperature: 0.2 - maxCompletionTokens: 512 diff --git a/.github/prompts/design.prompt.yml b/.github/prompts/design.prompt.yml deleted file mode 100644 index f658312..0000000 --- a/.github/prompts/design.prompt.yml +++ /dev/null @@ -1,16 +0,0 @@ -messages: - - role: system - content: | - You are a Laravel developer. Apply these guidelines exactly: - - {{skill_content}} - - Respond with only the requested code. No explanations unless asked. - - role: user - content: | - Write an anonymous Blade button component with @props for variant and size. Merge $attributes with defaults. - Use min-h-[44px] for touch target, focus-visible:ring-2. Mobile-first. -model: openai/gpt-4o-mini -modelParameters: - temperature: 0.2 - maxCompletionTokens: 512 diff --git a/.github/prompts/docuware.prompt.yml b/.github/prompts/docuware.prompt.yml deleted file mode 100644 index 513e1c3..0000000 --- a/.github/prompts/docuware.prompt.yml +++ /dev/null @@ -1,16 +0,0 @@ -messages: - - role: system - content: | - You are a Laravel developer. Apply these guidelines exactly: - - {{skill_content}} - - Respond with only the requested code. No explanations unless asked. - - role: user - content: | - Write a DocuWareService that wraps the DocuWare connector. Constructor accepts optional connector for testability. - Use config('laravel-docuware.credentials.*') not env(). Include fetchDocument or similar method signature. -model: openai/gpt-4o-mini -modelParameters: - temperature: 0.2 - maxCompletionTokens: 512 diff --git a/.github/prompts/dto.prompt.yml b/.github/prompts/dto.prompt.yml deleted file mode 100644 index 5579d6b..0000000 --- a/.github/prompts/dto.prompt.yml +++ /dev/null @@ -1,16 +0,0 @@ -messages: - - role: system - content: | - You are a Laravel developer. Apply these guidelines exactly: - - {{skill_content}} - - Respond with only the requested code. No explanations unless asked. - - role: user - content: | - Write a readonly CustomerData DTO with id, name, email. Include fromArray() factory that handles - PascalCase and snake_case API field names. Use nullable for optional fields. -model: openai/gpt-4o-mini -modelParameters: - temperature: 0.2 - maxCompletionTokens: 512 diff --git a/.github/prompts/dusk.prompt.yml b/.github/prompts/dusk.prompt.yml deleted file mode 100644 index 8f92d68..0000000 --- a/.github/prompts/dusk.prompt.yml +++ /dev/null @@ -1,16 +0,0 @@ -messages: - - role: system - content: | - You are a Laravel developer. Apply these guidelines exactly: - - {{skill_content}} - - Respond with only the requested code. No explanations unless asked. - - role: user - content: | - Write a Dusk test that logs in, visits /invoices/create, uses dusk="" selectors, calls assertNoJavaScriptErrors(). - Use DatabaseTruncation. Use loginAs(), waitForText, never pause(). -model: openai/gpt-4o-mini -modelParameters: - temperature: 0.2 - maxCompletionTokens: 512 diff --git a/.github/prompts/enums.prompt.yml b/.github/prompts/enums.prompt.yml deleted file mode 100644 index 85984b1..0000000 --- a/.github/prompts/enums.prompt.yml +++ /dev/null @@ -1,16 +0,0 @@ -messages: - - role: system - content: | - You are a Laravel developer. Apply these guidelines exactly: - - {{skill_content}} - - Respond with only the requested code. No explanations unless asked. - - role: user - content: | - Write a Status enum with Draft, Active, Archived. Include label() and color() methods using match expressions. - Use backed string enum. -model: openai/gpt-4o-mini -modelParameters: - temperature: 0.2 - maxCompletionTokens: 512 diff --git a/.github/prompts/events.prompt.yml b/.github/prompts/events.prompt.yml deleted file mode 100644 index 2c67ac5..0000000 --- a/.github/prompts/events.prompt.yml +++ /dev/null @@ -1,16 +0,0 @@ -messages: - - role: system - content: | - You are a Laravel developer. Apply these guidelines exactly: - - {{skill_content}} - - Respond with only the requested code. No explanations unless asked. - - role: user - content: | - Write an InvoicePaid event (plain data container with Invoice) and a SendInvoicePaidNotification listener. - Event uses Dispatchable, SerializesModels. Listener has single responsibility. Use past-tense for event name. -model: openai/gpt-4o-mini -modelParameters: - temperature: 0.2 - maxCompletionTokens: 512 diff --git a/.github/prompts/exceptions.prompt.yml b/.github/prompts/exceptions.prompt.yml deleted file mode 100644 index 493c99b..0000000 --- a/.github/prompts/exceptions.prompt.yml +++ /dev/null @@ -1,16 +0,0 @@ -messages: - - role: system - content: | - You are a Laravel developer. Apply these guidelines exactly: - - {{skill_content}} - - Respond with only the requested code. No explanations unless asked. - - role: user - content: | - Write an InvoiceAlreadyPaidException that extends RuntimeException. It receives an Invoice as readonly property - and sets a clear message via parent::__construct(). Use a named failure state. -model: openai/gpt-4o-mini -modelParameters: - temperature: 0.2 - maxCompletionTokens: 384 diff --git a/.github/prompts/formrequests.prompt.yml b/.github/prompts/formrequests.prompt.yml deleted file mode 100644 index 50dd9f9..0000000 --- a/.github/prompts/formrequests.prompt.yml +++ /dev/null @@ -1,17 +0,0 @@ -messages: - - role: system - content: | - You are a Laravel developer. Apply these guidelines exactly: - - {{skill_content}} - - Respond with only the requested code. No explanations unless asked. - - role: user - content: | - Write a StoreInvoiceRequest with authorize() and rules() returning array-based rules. - Rules: order_id required exists in orders, amount required numeric min 0. - Add PHPDoc @return for rules(). -model: openai/gpt-4o-mini -modelParameters: - temperature: 0.2 - maxCompletionTokens: 512 diff --git a/.github/prompts/general.prompt.yml b/.github/prompts/general.prompt.yml deleted file mode 100644 index eb0559e..0000000 --- a/.github/prompts/general.prompt.yml +++ /dev/null @@ -1,16 +0,0 @@ -messages: - - role: system - content: | - You are a Laravel developer. Apply these guidelines exactly: - - {{skill_content}} - - Respond with only the requested code. No explanations unless asked. - - role: user - content: | - Add a Stripe API key to the Laravel config and show how to read it in a controller. - Use the correct helper for config access. Show the config file addition and one line of controller code. -model: openai/gpt-4o-mini -modelParameters: - temperature: 0.2 - maxCompletionTokens: 512 diff --git a/.github/prompts/helperfunctions.prompt.yml b/.github/prompts/helperfunctions.prompt.yml deleted file mode 100644 index 9106477..0000000 --- a/.github/prompts/helperfunctions.prompt.yml +++ /dev/null @@ -1,16 +0,0 @@ -messages: - - role: system - content: | - You are a Laravel developer. Apply these guidelines exactly: - - {{skill_content}} - - Respond with only the requested code. No explanations unless asked. - - role: user - content: | - Write PHP code to filter an array of users to only active ones, then get their email addresses as a comma-separated string. - Use Laravel Arr and Str helpers instead of native PHP functions. -model: openai/gpt-4o-mini -modelParameters: - temperature: 0.2 - maxCompletionTokens: 512 diff --git a/.github/prompts/helpers.prompt.yml b/.github/prompts/helpers.prompt.yml deleted file mode 100644 index 9916643..0000000 --- a/.github/prompts/helpers.prompt.yml +++ /dev/null @@ -1,16 +0,0 @@ -messages: - - role: system - content: | - You are a Laravel developer. Apply these guidelines exactly: - - {{skill_content}} - - Respond with only the requested code. No explanations unless asked. - - role: user - content: | - Write a DateHelper class with a static format() method that accepts a date and format string, returns formatted string or null. - Use Carbon. No business logic, no database queries. PascalCase with Helper suffix. -model: openai/gpt-4o-mini -modelParameters: - temperature: 0.2 - maxCompletionTokens: 384 diff --git a/.github/prompts/interfaces.prompt.yml b/.github/prompts/interfaces.prompt.yml deleted file mode 100644 index 1474d0a..0000000 --- a/.github/prompts/interfaces.prompt.yml +++ /dev/null @@ -1,16 +0,0 @@ -messages: - - role: system - content: | - You are a Laravel developer. Apply these guidelines exactly: - - {{skill_content}} - - Respond with only the requested code. No explanations unless asked. - - role: user - content: | - Write a PaymentGateway interface in app/Contracts/ with charge(Order, int) and refund(string, int) methods. - Return a PaymentResult. No implementation. Clear noun describing the capability. -model: openai/gpt-4o-mini -modelParameters: - temperature: 0.2 - maxCompletionTokens: 384 diff --git a/.github/prompts/jobs.prompt.yml b/.github/prompts/jobs.prompt.yml deleted file mode 100644 index 49b05f9..0000000 --- a/.github/prompts/jobs.prompt.yml +++ /dev/null @@ -1,16 +0,0 @@ -messages: - - role: system - content: | - You are a Laravel developer. Apply these guidelines exactly: - - {{skill_content}} - - Respond with only the requested code. No explanations unless asked. - - role: user - content: | - Write a ProcessInvoicePaymentJob that implements ShouldQueue. Delegate to ProcessInvoicePayment action. - Use Dispatchable, InteractsWithQueue, Queueable, SerializesModels. Set tries, backoff, queue. Add failed() method. -model: openai/gpt-4o-mini -modelParameters: - temperature: 0.2 - maxCompletionTokens: 512 diff --git a/.github/prompts/livewire.prompt.yml b/.github/prompts/livewire.prompt.yml deleted file mode 100644 index 54e63c7..0000000 --- a/.github/prompts/livewire.prompt.yml +++ /dev/null @@ -1,16 +0,0 @@ -messages: - - role: system - content: | - You are a Laravel developer. Apply these guidelines exactly: - - {{skill_content}} - - Respond with only the requested code. No explanations unless asked. - - role: user - content: | - Write a Livewire InvoiceList component with search property, #[Computed] invoices(), and wire:model/wire:click. - Keep logic in PHP, template declarative. Use wire:model for search binding. -model: openai/gpt-4o-mini -modelParameters: - temperature: 0.2 - maxCompletionTokens: 512 diff --git a/.github/prompts/middleware.prompt.yml b/.github/prompts/middleware.prompt.yml deleted file mode 100644 index 290c471..0000000 --- a/.github/prompts/middleware.prompt.yml +++ /dev/null @@ -1,16 +0,0 @@ -messages: - - role: system - content: | - You are a Laravel developer. Apply these guidelines exactly: - - {{skill_content}} - - Respond with only the requested code. No explanations unless asked. - - role: user - content: | - Write an EnsureUserIsSubscribed middleware. If user is not subscribed, return 403 JSON response. - Otherwise call $next($request). Clear descriptive name. No business logic inside. -model: openai/gpt-4o-mini -modelParameters: - temperature: 0.2 - maxCompletionTokens: 384 diff --git a/.github/prompts/migrations.prompt.yml b/.github/prompts/migrations.prompt.yml deleted file mode 100644 index da7aeb7..0000000 --- a/.github/prompts/migrations.prompt.yml +++ /dev/null @@ -1,16 +0,0 @@ -messages: - - role: system - content: | - You are a Laravel developer. Apply these guidelines exactly: - - {{skill_content}} - - Respond with only the requested code. No explanations unless asked. - - role: user - content: | - Write a migration to create an invoices table with id, order_id (foreign key), status (string default draft), amount (decimal), timestamps. - Use foreignId()->constrained()->cascadeOnDelete(). Include both up() and down() methods. -model: openai/gpt-4o-mini -modelParameters: - temperature: 0.2 - maxCompletionTokens: 512 diff --git a/.github/prompts/models.prompt.yml b/.github/prompts/models.prompt.yml deleted file mode 100644 index 3ad494e..0000000 --- a/.github/prompts/models.prompt.yml +++ /dev/null @@ -1,16 +0,0 @@ -messages: - - role: system - content: | - You are a Laravel developer. Apply these guidelines exactly: - - {{skill_content}} - - Respond with only the requested code. No explanations unless asked. - - role: user - content: | - Write a minimal Invoice Eloquent model with guarded, casts as method, and a belongsTo Order relationship. - Use typed return type on the relationship. Include section comment headers. -model: openai/gpt-4o-mini -modelParameters: - temperature: 0.2 - maxCompletionTokens: 512 diff --git a/.github/prompts/observers.prompt.yml b/.github/prompts/observers.prompt.yml deleted file mode 100644 index 6596e0b..0000000 --- a/.github/prompts/observers.prompt.yml +++ /dev/null @@ -1,16 +0,0 @@ -messages: - - role: system - content: | - You are a Laravel developer. Apply these guidelines exactly: - - {{skill_content}} - - Respond with only the requested code. No explanations unless asked. - - role: user - content: | - Write a UserObserver with created() that sends WelcomeNotification, and updated()/deleted() that clear cache. - Use Observer suffix. Only define methods you need. No business logic. -model: openai/gpt-4o-mini -modelParameters: - temperature: 0.2 - maxCompletionTokens: 384 diff --git a/.github/prompts/pesttesting.prompt.yml b/.github/prompts/pesttesting.prompt.yml deleted file mode 100644 index 15faa12..0000000 --- a/.github/prompts/pesttesting.prompt.yml +++ /dev/null @@ -1,16 +0,0 @@ -messages: - - role: system - content: | - You are a Laravel developer. Apply these guidelines exactly: - - {{skill_content}} - - Respond with only the requested code. No explanations unless asked. - - role: user - content: | - Write a Pest test it('creates an invoice for the given order') with AAA pattern and Arrange/Act/Assert comments. - Use uses(RefreshDatabase::class), postJson, assertCreated(), expect()->toBe(). Plain English description. -model: openai/gpt-4o-mini -modelParameters: - temperature: 0.2 - maxCompletionTokens: 512 diff --git a/.github/prompts/php.prompt.yml b/.github/prompts/php.prompt.yml deleted file mode 100644 index e46c1b9..0000000 --- a/.github/prompts/php.prompt.yml +++ /dev/null @@ -1,16 +0,0 @@ -messages: - - role: system - content: | - You are a Laravel developer. Apply these guidelines exactly: - - {{skill_content}} - - Respond with only the requested code. No explanations unless asked. - - role: user - content: | - Write a process(Order $order) method with early returns. If !$order->isPaid() throw exception and return. - If !$order->hasItems() throw and return. Then happy-path logic. No else/elseif. Use guard clauses. -model: openai/gpt-4o-mini -modelParameters: - temperature: 0.2 - maxCompletionTokens: 512 diff --git a/.github/prompts/phpstan.prompt.yml b/.github/prompts/phpstan.prompt.yml deleted file mode 100644 index 4bcab75..0000000 --- a/.github/prompts/phpstan.prompt.yml +++ /dev/null @@ -1,16 +0,0 @@ -messages: - - role: system - content: | - You are a Laravel developer. Apply these guidelines exactly: - - {{skill_content}} - - Respond with only the requested code. No explanations unless asked. - - role: user - content: | - Write a method process(Order $order): Invoice with full type hints. Add PHPDoc @return array> for a rules() method. - Use union types instead of mixed. No @phpstan-ignore. -model: openai/gpt-4o-mini -modelParameters: - temperature: 0.2 - maxCompletionTokens: 512 diff --git a/.github/prompts/phpunit.prompt.yml b/.github/prompts/phpunit.prompt.yml deleted file mode 100644 index 4f079f8..0000000 --- a/.github/prompts/phpunit.prompt.yml +++ /dev/null @@ -1,16 +0,0 @@ -messages: - - role: system - content: | - You are a Laravel developer. Apply these guidelines exactly: - - {{skill_content}} - - Respond with only the requested code. No explanations unless asked. - - role: user - content: | - Write a feature test test_user_can_create_invoice. Use RefreshDatabase, factories, actingAs. - Assert 201 and assertDatabaseHas. Use test_ prefix and : void return type. -model: openai/gpt-4o-mini -modelParameters: - temperature: 0.2 - maxCompletionTokens: 512 diff --git a/.github/prompts/policies.prompt.yml b/.github/prompts/policies.prompt.yml deleted file mode 100644 index fdfb351..0000000 --- a/.github/prompts/policies.prompt.yml +++ /dev/null @@ -1,16 +0,0 @@ -messages: - - role: system - content: | - You are a Laravel developer. Apply these guidelines exactly: - - {{skill_content}} - - Respond with only the requested code. No explanations unless asked. - - role: user - content: | - Write an InvoicePolicy with viewAny (admin only), view (owner or admin), create (authenticated). - Use Policy suffix. Standard ability names. -model: openai/gpt-4o-mini -modelParameters: - temperature: 0.2 - maxCompletionTokens: 512 diff --git a/.github/prompts/requests.prompt.yml b/.github/prompts/requests.prompt.yml deleted file mode 100644 index 4584210..0000000 --- a/.github/prompts/requests.prompt.yml +++ /dev/null @@ -1,16 +0,0 @@ -messages: - - role: system - content: | - You are a Laravel developer. Apply these guidelines exactly: - - {{skill_content}} - - Respond with only the requested code. No explanations unless asked. - - role: user - content: | - Write a StoreInvoiceRequest with authorize() using can('create', Invoice::class) and rules() with array-based definitions. - Add PHPDoc @return for rules(). Never use $request->validate() in controller. -model: openai/gpt-4o-mini -modelParameters: - temperature: 0.2 - maxCompletionTokens: 512 diff --git a/.github/prompts/resources.prompt.yml b/.github/prompts/resources.prompt.yml deleted file mode 100644 index c7e6db8..0000000 --- a/.github/prompts/resources.prompt.yml +++ /dev/null @@ -1,16 +0,0 @@ -messages: - - role: system - content: | - You are a Laravel developer. Apply these guidelines exactly: - - {{skill_content}} - - Respond with only the requested code. No explanations unless asked. - - role: user - content: | - Write a UserResource extending JsonResource. Return id, name, email, posts (whenLoaded), created_at (formatted). - Use whenLoaded for relations. Use when() for conditional admin-only secret field. -model: openai/gpt-4o-mini -modelParameters: - temperature: 0.2 - maxCompletionTokens: 512 diff --git a/.github/prompts/routing.prompt.yml b/.github/prompts/routing.prompt.yml deleted file mode 100644 index 5265a06..0000000 --- a/.github/prompts/routing.prompt.yml +++ /dev/null @@ -1,16 +0,0 @@ -messages: - - role: system - content: | - You are a Laravel developer. Apply these guidelines exactly: - - {{skill_content}} - - Respond with only the requested code. No explanations unless asked. - - role: user - content: | - Write API routes for invoices: index and store. Use auth:sanctum middleware, apiResource, and resourceful route names. - Group them properly. Use kebab-case for URL. -model: openai/gpt-4o-mini -modelParameters: - temperature: 0.2 - maxCompletionTokens: 384 diff --git a/.github/prompts/saloon.prompt.yml b/.github/prompts/saloon.prompt.yml deleted file mode 100644 index 9d01368..0000000 --- a/.github/prompts/saloon.prompt.yml +++ /dev/null @@ -1,16 +0,0 @@ -messages: - - role: system - content: | - You are a Laravel developer. Apply these guidelines exactly: - - {{skill_content}} - - Respond with only the requested code. No explanations unless asked. - - role: user - content: | - Write a StripeConnector extending Saloon Connector with resolveBaseUrl and defaultHeaders. - Write a ListChargesRequest for GET. No Http::get() or raw HTTP. Use Saloon pattern. -model: openai/gpt-4o-mini -modelParameters: - temperature: 0.2 - maxCompletionTokens: 512 diff --git a/.github/prompts/services.prompt.yml b/.github/prompts/services.prompt.yml deleted file mode 100644 index f8524a3..0000000 --- a/.github/prompts/services.prompt.yml +++ /dev/null @@ -1,16 +0,0 @@ -messages: - - role: system - content: | - You are a Laravel developer. Apply these guidelines exactly: - - {{skill_content}} - - Respond with only the requested code. No explanations unless asked. - - role: user - content: | - Write a PaymentService that orchestrates CreateInvoice, ChargePaymentMethod, SendPaymentConfirmation actions. - Method processOrderPayment(Order) uses DB::transaction. Inject actions via constructor. No Manager/Handler suffix. -model: openai/gpt-4o-mini -modelParameters: - temperature: 0.2 - maxCompletionTokens: 512 diff --git a/.github/prompts/tailwind.prompt.yml b/.github/prompts/tailwind.prompt.yml deleted file mode 100644 index 460c1e7..0000000 --- a/.github/prompts/tailwind.prompt.yml +++ /dev/null @@ -1,16 +0,0 @@ -messages: - - role: system - content: | - You are a Laravel developer. Apply these guidelines exactly: - - {{skill_content}} - - Respond with only the requested code. No explanations unless asked. - - role: user - content: | - Write the resources/css/app.css for Tailwind v4 with @theme directive setting --color-primary-500 and --font-sans. - Include @source for views and Livewire. No custom CSS classes. -model: openai/gpt-4o-mini -modelParameters: - temperature: 0.2 - maxCompletionTokens: 384 diff --git a/.github/prompts/traits.prompt.yml b/.github/prompts/traits.prompt.yml deleted file mode 100644 index dcf4a2e..0000000 --- a/.github/prompts/traits.prompt.yml +++ /dev/null @@ -1,16 +0,0 @@ -messages: - - role: system - content: | - You are a Laravel developer. Apply these guidelines exactly: - - {{skill_content}} - - Respond with only the requested code. No explanations unless asked. - - role: user - content: | - Write an Archivable trait with archive(), unarchive(), isArchived() methods for models with archived_at. - Use -able suffix. Single responsibility. No complex business logic. -model: openai/gpt-4o-mini -modelParameters: - temperature: 0.2 - maxCompletionTokens: 384 diff --git a/.github/prompts/translations.prompt.yml b/.github/prompts/translations.prompt.yml deleted file mode 100644 index b9ca04c..0000000 --- a/.github/prompts/translations.prompt.yml +++ /dev/null @@ -1,16 +0,0 @@ -messages: - - role: system - content: | - You are a Laravel developer. Apply these guidelines exactly: - - {{skill_content}} - - Respond with only the requested code. No explanations unless asked. - - role: user - content: | - Write lang/en/invoices.php with create_success key using :name placeholder. - Show usage with __('invoices.create_success', ['name' => $name]). Use namespaced keys. -model: openai/gpt-4o-mini -modelParameters: - temperature: 0.2 - maxCompletionTokens: 384 diff --git a/.github/scripts/validate-skill-response.sh b/.github/scripts/validate-skill-response.sh deleted file mode 100755 index 2de934a..0000000 --- a/.github/scripts/validate-skill-response.sh +++ /dev/null @@ -1,133 +0,0 @@ -#!/bin/bash -# Validates AI response against skill-specific rules. -# Usage: validate-skill-response.sh -# Exits 0 if valid, 1 if invalid. - -skill="$1" -response="$2" - -if [ -z "$response" ]; then - echo "::error::[$skill] Empty response" - exit 1 -fi - -case "$skill" in - general) - echo "$response" | grep -q 'env(' && { echo "::error::[$skill] Should use config() not env()"; exit 1; } - echo "$response" | grep -q 'config(' || { echo "::error::[$skill] Missing config()"; exit 1; } - ;; - helperfunctions) - echo "$response" | grep -qE 'Arr::|Str::|collect\(' || { echo "::error::[$skill] Should use Laravel helpers"; exit 1; } - ;; - models) - echo "$response" | grep -qE 'extends Model|BelongsTo|HasMany|HasOne' || { echo "::error::[$skill] Needs Model with relationship"; exit 1; } - ;; - controllers) - echo "$response" | grep -qE '__invoke|JsonResponse' || { echo "::error::[$skill] Needs invokable or JsonResponse"; exit 1; } - ;; - migrations) - echo "$response" | grep -qE 'foreignId|constrained|cascadeOnDelete' || { echo "::error::[$skill] Needs proper foreign key"; exit 1; } - echo "$response" | grep -qE 'function (up|down)\s*\(\)' || { echo "::error::[$skill] Needs up() and down()"; exit 1; } - ;; - routing) - echo "$response" | grep -qE 'Route::|Route::apiResource|middleware' || { echo "::error::[$skill] Needs Route definitions"; exit 1; } - ;; - formrequests|requests) - echo "$response" | grep -qE 'authorize\(\)|rules\(\)' || { echo "::error::[$skill] Needs authorize and rules"; exit 1; } - ;; - actions) - echo "$response" | grep -q 'execute(' || { echo "::error::[$skill] Action needs execute()"; exit 1; } - echo "$response" | grep -qE 'InvoiceAction|UserHandler' && { echo "::error::[$skill] Avoid vague names"; exit 1; } || true - ;; - commands) - echo "$response" | grep -qE 'self::SUCCESS|self::FAILURE' || { echo "::error::[$skill] Must return SUCCESS or FAILURE"; exit 1; } - ;; - dto) - echo "$response" | grep -q 'fromArray' || { echo "::error::[$skill] DTO needs fromArray()"; exit 1; } - echo "$response" | grep -q 'readonly' || { echo "::error::[$skill] DTO should be readonly"; exit 1; } - ;; - enums) - echo "$response" | grep -qE 'label\(\)|color\(\)' || { echo "::error::[$skill] Enum needs label() and color()"; exit 1; } - echo "$response" | grep -q 'match' || true - ;; - events) - echo "$response" | grep -qE 'Dispatchable|SerializesModels' || true - ;; - exceptions) - echo "$response" | grep -q 'Exception' || { echo "::error::[$skill] Needs Exception suffix"; exit 1; } - ;; - helpers) - echo "$response" | grep -qE 'Helper|format' || true - ;; - interfaces) - echo "$response" | grep -q 'interface' || { echo "::error::[$skill] Needs interface"; exit 1; } - ;; - jobs) - echo "$response" | grep -qE 'ShouldQueue|Dispatchable|Queueable' || { echo "::error::[$skill] Job needs queue traits"; exit 1; } - ;; - middleware) - echo "$response" | grep -q '\$next(\$request)' || { echo "::error::[$skill] Middleware must call next"; exit 1; } - ;; - observers) - echo "$response" | grep -qE 'Observer|created|updated' || { echo "::error::[$skill] Needs Observer and lifecycle methods"; exit 1; } - ;; - policies) - echo "$response" | grep -qE 'viewAny|view|create' || { echo "::error::[$skill] Policy needs ability methods"; exit 1; } - ;; - resources) - echo "$response" | grep -qE 'whenLoaded|when\(|JsonResource' || { echo "::error::[$skill] Resource needs whenLoaded/when"; exit 1; } - ;; - services) - echo "$response" | grep -qE 'DB::transaction|Service' || { echo "::error::[$skill] Service needs DB::transaction or Service class"; exit 1; } - ;; - traits) - echo "$response" | grep -q 'trait' || { echo "::error::[$skill] Needs trait"; exit 1; } - ;; - blade) - echo "$response" | grep -q '{{' || { echo "::error::[$skill] Blade needs {{ }} escaping"; exit 1; } - ;; - design) - echo "$response" | grep -qE '\$attributes|@props|min-h-\[44px\]' || true - ;; - livewire) - echo "$response" | grep -qE 'wire:model|wire:click|Computed' || { echo "::error::[$skill] Livewire needs wire: or Computed"; exit 1; } - ;; - tailwind) - echo "$response" | grep -qE '@theme|@source|tailwind' || { echo "::error::[$skill] Needs @theme or Tailwind setup"; exit 1; } - ;; - translations) - echo "$response" | grep -qE '__\(|trans\(' || { echo "::error::[$skill] Needs __() or trans()"; exit 1; } - ;; - phpunit) - echo "$response" | grep -qE 'test_|assertStatus|assertDatabaseHas|RefreshDatabase' || { echo "::error::[$skill] Needs test structure"; exit 1; } - ;; - pesttesting) - echo "$response" | grep -qE 'it\(|expect\(|assertCreated|Arrange|Act|Assert' || { echo "::error::[$skill] Needs Pest syntax"; exit 1; } - ;; - phpstan) - echo "$response" | grep -qE 'array mainAgent[MainAgent] + mainAgent --> architectAgent[ArchitectAgent] + mainAgent --> backendImpl[BackendImplementationAgent] + mainAgent --> frontendImpl[FrontendImplementationAgent] + mainAgent --> implementationAgent[ImplementationAgent] + mainAgent --> refactorAgent[RefactorAgent] + mainAgent --> testAgent[TestAgent] + mainAgent --> reviewAgent[ReviewAgent] + mainAgent --> documentationAgent[DocumentationAgent] + architectAgent --> mainAgent + backendImpl --> mainAgent + frontendImpl --> mainAgent + implementationAgent --> mainAgent + refactorAgent --> mainAgent + testAgent --> mainAgent + reviewAgent --> mainAgent + documentationAgent --> mainAgent + mainAgent --> outputNode["Output (code/plan/review/docs)"] +``` + +- **MainAgent** is typically Claude Desktop, Claude Terminal, or an internal orchestrator. +- Each role is a **prompted mode** of the same underlying model, not a separate codebase. +- All roles query the same Boost MCP index; they just apply different responsibilities when reading and editing code. + +--- + +### Example Prompts + +You can adapt these snippets directly in Claude Desktop/Terminal or other agents: + +- **ArchitectAgent** + - “Act as **ArchitectAgent** for this Laravel project. Using `RULES.md` and the `general`, `models`, `migrations`, `routing`, `actions`, and `services` skills from `codebar-ag/coding-guidelines`, design the architecture for this feature: …” + +- **BackendImplementationAgent** + - “Act as **BackendImplementationAgent**. Follow the `controllers`, `actions`, `services`, `models`, `formrequests`, `middleware`, and `phpstan` skills to implement the backend for this feature design without changing Blade, Livewire, or Tailwind unless explicitly requested: …” + +- **FrontendImplementationAgent** + - “Act as **FrontendImplementationAgent**. Using the `controllers` (response shaping only), `resources`, `blade`, `design`, `livewire`, `tailwind`, and `translations` skills, implement or update the frontend for this feature, assuming the backend contracts are already in place. If a minimal backend adjustment is required, describe it but do not implement it: …” + +- **ImplementationAgent** + - “Act as **ImplementationAgent**. Implement this small, self-contained feature end-to-end using the relevant skills, keeping changes tightly scoped and aligned with the existing architecture: …” + +- **RefactorAgent** + - “Act as **RefactorAgent**. Using the `controllers`, `actions`, `services`, and `models` skills, refactor this legacy code to match the guidelines. Keep behaviour the same and work in small, reviewable steps: …” + +- **TestAgent** + - “Act as **TestAgent**. Apply the `phpunit`, `pesttesting`, and `phpstan` skills to improve test coverage and static analysis for these changes: …” + +- **ReviewAgent** + - “Act as **ReviewAgent**. Using `RULES.md` and all skills, review this diff and produce: (1) a short assessment, (2) a file‑grouped refactor plan, and (3) a few copy‑pasteable suggestions.” + +- **DocumentationAgent** + - “Act as **DocumentationAgent**. Using `RULES.md`, the `documentation` skill, and any relevant feature skills, update `README.md` and other docs to reflect this change. Focus on behaviour, examples, and how to apply the guidelines in practice, not internal implementation details: …” + diff --git a/README.md b/README.md index 5938257..44540be 100644 --- a/README.md +++ b/README.md @@ -1,89 +1,194 @@ # codebar Solutions AG Coding Guidelines -Shared Laravel coding guidelines and skills for codebar-ag projects. A Composer package that ships 36 skills for consistent conventions across PHP, Laravel, testing, frontend, and services. +Shared Laravel coding and architecture guidelines for codebar-ag projects, optimized for AI-assisted development with Laravel Boost, Claude CI, and Claude Desktop/Terminal. **Rule index:** See [RULES.md](RULES.md) for the full rule structure and file reference. --- -## Skills Overview +## Requirements -Skills are reusable convention guides that assistants use when working with your codebase. Each skill includes Rules, Examples, Anti-Patterns, and References. - -| Category | Skills | Description | -|----------|--------|-------------| -| **Laravel** | General, HelperFunctions, Models, Controllers, Migrations, Routing, FormRequests | Framework conventions, config/logging, Eloquent, routes, validation | -| **Backend** | Actions, Commands, DTO, Enums, Events, Exceptions, Helpers, Interfaces, Jobs, Middleware, Observers, Policies, Requests, Resources, Services, Traits | PHP architecture, single-purpose classes, API resources, queue jobs | -| **Frontend** | Blade, Design, Livewire, Tailwind, Translations | Templates, design system, components, Tailwind CSS, i18n | -| **Testing** | PHPUnit, PestTesting, PHPStan, Dusk | Unit/feature tests, static analysis, browser tests | -| **Services** | Saloon, DocuWare, Albatros | External API integrations (Saloon, DocuWare, Albatros) | - -**Total: 36 skills.** +- **PHP:** ^8.4 +- **Laravel:** 12.x (Illuminate 12 components) +- **Laravel Boost:** ^2.2 (installed automatically as a dependency) --- -## Implementation Guide - -### Prerequisites - -- A Laravel project where you want to use these guidelines -- [Laravel Boost](https://github.com/laravel/boost) (required for skill discovery) +## Installation -### Step 1: Install Laravel Boost +### 1. Require the package In your Laravel project: -```bash -composer require laravel/boost --dev -php artisan boost:install -``` - -### Step 2: Add this package - ```bash composer require codebar-ag/coding-guidelines --dev ``` -### Step 3: Sync skills +This will also install `laravel/boost` as a dependency. + +### 2. Install and sync Boost ```bash +php artisan boost:install php artisan boost:update ``` -Boost automatically discovers skills from `vendor/codebar-ag/coding-guidelines/resources/boost/skills/` when the package is installed. +Laravel Boost automatically discovers skills from `vendor/codebar-ag/coding-guidelines/resources/boost/skills/` when the package is installed. -### Step 4: Activate MCP (optional) +--- -If your editor supports MCP (Model Context Protocol), configure it to use the Boost MCP server for full context. See the [Laravel Boost documentation](https://laravel.com/docs/boost) for your editor's setup. +## Usage + +Once the package is installed and `boost:update` has run: + +- **Laravel Boost** exposes all skills under `resources/boost/skills/**/SKILL.md` to AI assistants that integrate with Boost. +- **Claude CI** can use these skills and `RULES.md` when reviewing pull requests. +- **Claude Desktop & Claude Terminal (PhpStorm or other editors)** can follow the same guidelines when you point them at this package. + +No extra configuration is required beyond installing the package and running the Boost commands. + +--- + +## Multi‑agent usage with Laravel Boost + +Laravel Boost acts as the **index** between your Laravel project and AI agents. +This package provides the **skills and rules** for that index; the agents are *personas* you prompt in your tools. + +See `AGENTS.md` for full details. In short, the current role set includes: -### Step 5: Refactor command (Cursor) +- **ArchitectAgent**: designs features (routes, models, actions, services, events). +- **BackendImplementationAgent**: implements backend code from approved designs. +- **FrontendImplementationAgent**: implements frontend-facing pieces from backend contracts. +- **ImplementationAgent**: handles small, self-contained full-stack changes. +- **RefactorAgent**: brings existing code into guideline compliance safely. +- **TestAgent**: improves tests and static analysis. +- **ReviewAgent**: reviews changes and proposes refactors (used in CI). +- **DocumentationAgent**: keeps docs and guidance aligned with the current architecture. -To run a full codebase refactor against all guidelines: +### Example prompts (Claude Desktop / Terminal) -1. Install or update this package with Composer -2. The package automatically syncs `refactor.md` to `.cursor/commands/refactor.md` -3. In Cursor, type `/refactor` and run the command +Copy-paste and adapt these when talking to Claude Desktop/Terminal with Boost enabled. The examples below are common starting points; for full role coverage see `AGENTS.md`. -The prompt instructs the AI to discover all skills, map them to your codebase, analyze for violations, and refactor for full compliance. Use it when newly adopting guidelines or to cross-check AI implementations. +- **ArchitectAgent** -If Composer plugins are restricted in your environment, run the fallback command manually: + ```text + Act as ArchitectAgent for this Laravel project. + + Use RULES.md and the skills under resources/boost/skills/**/SKILL.md from codebar-ag/coding-guidelines. + + For this feature, especially apply the general, models, migrations, routing, actions, and services skills. + Design the routes, models, actions, and services needed to implement this ticket: + - [paste ticket or description] + ``` + +- **ImplementationAgent** + + ```text + Act as ImplementationAgent. + + Use RULES.md and the controllers, formrequests, actions, services, resources, blade, livewire, tailwind, and translations skills. + + Starting from this design, implement the feature without changing unrelated behaviour: + - [paste design or current code] + ``` + +- **RefactorAgent** + + ```text + Act as RefactorAgent. + + Using the controllers, actions, services, models, and helpers skills, refactor this legacy code to follow the guidelines. + Keep behaviour the same, work in small, reviewable steps, and explain each batch of changes briefly: + - [paste code or file paths] + ``` + +- **TestAgent** + + ```text + Act as TestAgent. + + Apply the phpunit, pesttesting, phpstan, and dusk skills to improve tests and static analysis for these changes. + Propose concrete test files and assertions, and any PHPStan configuration updates needed: + - [paste diff or files] + ``` + +- **ReviewAgent** + + ```text + Act as ReviewAgent. + + Using RULES.md and all skills under resources/boost/skills/**/SKILL.md, review this diff and produce: + 1) a short assessment, + 2) a file‑grouped refactor plan, and + 3) a few copy‑pasteable suggestions. + + - [paste diff or PR description] + ``` + + +--- + +## What’s included + +Conceptually, this package covers: + +- **Laravel conventions**: routes, controllers, configuration, models, migrations, form requests, helper functions. +- **Backend architecture**: actions, services, DTOs, enums, events, exceptions, helpers, interfaces, jobs, middleware, observers, policies, requests, resources, traits. +- **Frontend & UI**: Blade templates, design system, Livewire components, Tailwind CSS, translations. +- **Testing & quality**: PHPUnit, Pest, PHPStan, Dusk and testing best practices. +- **External services**: Saloon integrations, DocuWare, Albatros and other service boundaries. + +Each area is implemented as a dedicated skill so AI assistants can follow focused, repeatable guidance. + +--- + +## Skills overview + +Skills are reusable convention and workflow guides that assistants use when working with your codebase. Each skill includes rules, examples, anti‑patterns, and often a step‑by‑step process and checklists. + +| Category | Skills | Description | +|----------|--------|-------------| +| **Laravel** | General, HelperFunctions, Models, Controllers, Migrations, Routing, FormRequests | Framework conventions, config/logging, Eloquent, routes, validation | +| **Backend** | Actions, Commands, DTO, Enums, Events, Exceptions, Helpers, Interfaces, Jobs, Middleware, Observers, Policies, Requests, Resources, Services, Traits | PHP architecture, single-purpose classes, API resources, queue jobs | +| **Frontend** | Blade, Design, Livewire, Tailwind, Translations | Templates, design system, components, Tailwind CSS, i18n | +| **Testing** | PHPUnit, PestTesting, PHPStan, Dusk | Unit/feature tests, static analysis, browser tests | +| **Services** | Saloon, DocuWare, Albatros | External API integrations (Saloon, DocuWare, Albatros) | + +**Total: 37 skills.** + +--- + +## Full guidelines + +For a complete, human-readable view of the guidelines: + +- Start with **[RULES.md](RULES.md)** for the overall structure, categories, and skill index. +- Drill into individual skills under `resources/boost/skills/{skill-name}/SKILL.md`: + - Each skill defines when to apply it, core rules, examples, and anti‑patterns. + - Newer skills (for example `phpstan`) follow a workflow-style template with sections like **When to Apply**, **Preconditions**, **Process**, **Checklists**, and **Troubleshooting**. + +Projects can treat `RULES.md` as the canonical index and the `SKILL.md` files as detailed playbooks. + +--- + +## Keeping guidelines up to date + +Update the package and refresh Boost’s view of the skills with: ```bash -php artisan guidelines:sync-refactor-command +composer update codebar-ag/coding-guidelines +php artisan boost:update ``` -You may need to allow the plugin once in Composer config: -`composer config allow-plugins.codebar-ag/coding-guidelines true` - -If `/refactor` does not appear in Cursor immediately, reload the Cursor window once. +--- -### Step 6: Override skills locally (optional) +## Project overrides To customize a skill for your project, create a file at `.ai/skills/{skill-name}/SKILL.md`. Your local version takes precedence over the package default. Example: override the Models skill: -``` +```text your-project/ ├── .ai/ │ └── skills/ @@ -91,42 +196,95 @@ your-project/ │ └── SKILL.md ← Your custom version ``` -### Alternative: Sync full repo - -To sync the complete guidelines repo (`.github/prompts`, `RULES.md`, etc.) into a `guidelines/` directory for reference, add to your `composer.json`: - -```json -"scripts": { - "sync-guidelines": "php vendor/codebar-ag/coding-guidelines/scripts/sync-guidelines.php" -} -``` - -Then run `composer sync-guidelines`. This clones or pulls the repo into `guidelines/` at your project root and copies `refactor.md` to `.cursor/commands/refactor.md` for use with Cursor slash commands. - -This sync script is optional and mainly useful when you mirror the full guidelines repo; normal package install/update already auto-syncs `/refactor`. +Project overrides can also adjust the `compatible_agents` frontmatter for a skill to fit your local workflows. +See `RULES.md` for the agent/phase mapping and the `compatible_agents` convention. --- -## How It Works +## How it works -This package places skills in `resources/boost/skills/{skill-name}/SKILL.md`. Laravel Boost v2.2+ automatically discovers skills from vendor packages when you run `boost:update`. No custom sync commands — Boost handles everything. +This package places skills in `resources/boost/skills/{skill-name}/SKILL.md`. Laravel Boost v2.2+ automatically discovers skills from vendor packages when you run `boost:update`. No custom sync commands or Laravel service providers are required—Boost handles discovery directly from the vendor path. + +When you install this package via Composer, `laravel/boost` is automatically installed as a dependency, so you do not need a separate Composer require for Boost. | Source | Path | |--------|------| -| This package | `vendor/codebar-ag/coding-guidelines/resources/boost/skills/` | +| This package (default skills) | `vendor/codebar-ag/coding-guidelines/resources/boost/skills/` | | Project overrides | `.ai/skills/{skill-name}/SKILL.md` | +In day-to-day application work you typically only touch: + +- `RULES.md` (as a reference) +- Your own `.ai/skills/{skill-name}/SKILL.md` overrides +- The skills in this package for **reading** (not editing in `vendor/`) + +Package internals such as `.github/workflows/skills-validation.yml` and `composer.json` are maintained here and normally do not need changes in consumer applications. + --- -## Updating +## Advanced AI integrations -```bash -composer update codebar-ag/coding-guidelines -php artisan boost:update -``` +### Claude CI (GitHub Actions) + +You can create a GitHub Actions workflow that uses Claude to challenge your changes against these rules and produce a copy‑pastable refactor plan. + +- Typical usage in a project: + - Add a workflow such as `.github/workflows/claude-guidelines-review.yml` in your application repository. + - Configure it to run on pull requests to `main` and via a `workflow_dispatch` manual trigger. +- Expected output: a Markdown comment on the PR with: + - A short assessment of guideline alignment. + - A step‑by‑step refactor plan grouped by file/area. + - Optional code snippets or pseudo‑patches you can copy‑paste. + +To enable it, configure the Anthropic API secret as described in **Anthropic secret configuration** and follow the setup instructions of the chosen Claude GitHub Action. + +#### Anthropic secret configuration + +The Claude workflow expects an Anthropic API key to be available as a GitHub secret: + +- **Secret name (default)**: `ANTHROPIC_API_KEY` +- **Recommended location**: organization-level `Settings → Secrets and variables → Actions` so all repositories can reuse it. +- **Usage**: the workflow passes this secret to the Claude Code Action for authenticated calls to the Claude API. + +If your company uses a different secret name convention, update the workflow input to match (search for `secrets.ANTHROPIC_API_KEY` in your copied `claude-guidelines-review.yml` workflow and adjust accordingly). + +### Claude Desktop & Claude Terminal + +When using Claude Desktop or Claude Terminal (for example inside PhpStorm), you can: + +- Tell Claude that the project uses `codebar-ag/coding-guidelines`. +- Ask it to load and follow: + - `RULES.md` + - All skills under `resources/boost/skills/**/SKILL.md` +- Reference specific skills by name in your prompts, for example: + - “Apply the `phpstan` and `phpunit` skills when fixing these tests.” + - “Follow the `models` and `actions` skills when refactoring this feature.” + +This makes local AI usage consistent with what runs in CI and via Boost. + +### MCP (optional) + +If your editor supports MCP (Model Context Protocol), configure it to use the Boost MCP server for full context. See the [Laravel Boost documentation](https://laravel.com/docs/boost) for your editor's setup. --- -## CI +## Claude-based skills validation + +This package validates its own skills using Pest and the [Laravel AI SDK](https://laravel.com/docs/12.x/ai-sdk): + +- **Run locally**: `vendor/bin/pest --group=skills` +- **Environment**: Set `ANTHROPIC_API_KEY` and optionally `ANTHROPIC_MODEL` (default in `phpunit.xml.dist`: `claude-haiku-4-5`). +- **Retries**: optionally set `SKILL_VALIDATION_MAX_ATTEMPTS` (default: `3`) to control strict fail-after-retry behavior for temporary provider overloads. +- **PHPUnit config**: `phpunit.xml.dist` is committed; copy to `phpunit.xml` (gitignored) for local overrides. + +The `.github/workflows/skills-validation.yml` workflow runs these checks on pushes and pull requests. Configure `ANTHROPIC_API_KEY` and `ANTHROPIC_MODEL` as GitHub secrets. + +Under the hood, skills validation is performed by a small Laravel AI agent and supports both direct test execution and queued batch execution: + +- **Per-skill tests**: `vendor/bin/pest --group=skills` runs one live Anthropic validation test per `SKILL.md` file (currently 37 tests), so failures are isolated by file. +- **Batch command**: `skills:validate` discovers each `resources/boost/skills/**/SKILL.md` file and dispatches (or runs with `--sync`) one validation job per file. +- **Logging**: each validation appends JSON lines to `storage/logs/skills-validation.log`, including the input markdown, structured output, usage/token metadata, provider status, retry attempt metadata, and output-quality audit fields. +- **Strict overload handling**: both per-skill tests and queue jobs retry bounded times and then fail explicitly when Anthropic remains overloaded. +- **Queue safety**: queued batch validation keeps queue-level retries/backoff in `ValidateSkillJob` in addition to bounded in-job retries for transient overloads. -GitHub Actions run on push and pull requests. Run validation locally: `composer validate-skills` +CI now validates skills directly through the per-skill test dataset, while the queue command remains available for manual or maintenance batch runs. diff --git a/RULES.md b/RULES.md index 2d19e8c..89a69b9 100644 --- a/RULES.md +++ b/RULES.md @@ -2,6 +2,8 @@ This file defines the folder structure and conventions for skills in this package. +It serves as the index of coding-guideline skills for Laravel Boost and other AI assistants. Detailed rules live in the individual `SKILL.md` files, while `README.md` explains installation, high-level usage, and the full skill list. + ## Package Layout Skills live in `resources/boost/skills/{skill-name}/SKILL.md` — the path Laravel Boost discovers for vendor packages. @@ -53,3 +55,8 @@ description: Brief description of when to use this skill ## Overriding Skills Projects can override any skill by creating `.ai/skills/{skill-name}/SKILL.md` in their Laravel project. The local file takes precedence over the package default. + +Use this package’s `resources/boost/skills/{skill-name}/SKILL.md` files as **defaults to read**, not files to edit in `vendor/`. For project-specific conventions: + +- Prefer `.ai/skills/{skill-name}/SKILL.md` in your application. +- Adjust the `compatible_agents` frontmatter there to map skills to the agents from `AGENTS.md` (ArchitectAgent, ImplementationAgent, RefactorAgent, TestAgent, ReviewAgent). diff --git a/composer.json b/composer.json index df45ee3..53e9d0b 100644 --- a/composer.json +++ b/composer.json @@ -1,24 +1,20 @@ { "name": "codebar-ag/coding-guidelines", - "type": "composer-plugin", + "type": "library", "description": "Shared Laravel coding guidelines and skills for codebar-ag projects. Composer package for Laravel Boost.", "keywords": [ "laravel", "boost", - "cursor", "coding-guidelines", "skills" ], "license": "MIT", "require": { - "composer-plugin-api": "^2.0", - "illuminate/console": "^12.0", - "illuminate/support": "^12.0", + "illuminate/console": "^12.41.1", + "illuminate/support": "^12.41.1", + "laravel/boost": "^2.2", "php": "^8.4" }, - "suggest": { - "laravel/boost": "Required for skill discovery. Install in your Laravel project." - }, "autoload": { "psr-4": { "CodebarAg\\CodingGuidelines\\": "src/" @@ -29,24 +25,18 @@ "CodebarAg\\CodingGuidelines\\Tests\\": "tests/" } }, - "extra": { - "class": "CodebarAg\\CodingGuidelines\\Composer\\RefactorCommandPlugin", - "laravel": { - "providers": [ - "CodebarAg\\CodingGuidelines\\CodingGuidelinesServiceProvider" - ] - } - }, - "scripts": { - "validate-skills": "php scripts/validate-skills.php", - "sync-guidelines": "php scripts/sync-guidelines.php" - }, "config": { - "sort-packages": true + "sort-packages": true, + "allow-plugins": { + "pestphp/pest-plugin": true + } }, - "minimum-stability": "dev", - "prefer-stable": true, "require-dev": { - "laravel/pint": "^1.27" + "laravel/pint": "^1.27", + "phpunit/phpunit": "^11.0", + "laravel/ai": "^0.2.0", + "orchestra/testbench": "^10.0", + "pestphp/pest": "^3.0", + "pestphp/pest-plugin-laravel": "^3.0" } } diff --git a/docs/concepts/mermaid/phpstan-analysis-flow.mmd b/docs/concepts/mermaid/phpstan-analysis-flow.mmd new file mode 100644 index 0000000..8ae4086 --- /dev/null +++ b/docs/concepts/mermaid/phpstan-analysis-flow.mmd @@ -0,0 +1,13 @@ +flowchart TD + start[Start] --> preconditions["Verify preconditions"] + preconditions --> initialAnalysis["Run initial PHPStan analysis"] + initialAnalysis --> categorizeErrors["Categorize errors"] + categorizeErrors --> fixIteratively["Fix errors iteratively"] + fixIteratively --> rerunPhpstan["Re-run PHPStan on scope"] + rerunPhpstan --> decisionMoreErrors{"More in-scope errors?"} + decisionMoreErrors -->|Yes| categorizeErrors + decisionMoreErrors -->|No| runTests["Run automated tests"] + runTests --> decisionTestsPass{"Tests pass?"} + decisionTestsPass -->|No| fixIteratively + decisionTestsPass -->|Yes| done[Done] + diff --git a/docs/concepts/mermaid/skill-template-flow.mmd b/docs/concepts/mermaid/skill-template-flow.mmd new file mode 100644 index 0000000..a20ef50 --- /dev/null +++ b/docs/concepts/mermaid/skill-template-flow.mmd @@ -0,0 +1,7 @@ +flowchart TD + start[Start] --> gatherRequirements["Gather requirements"] + gatherRequirements --> designSkill["Design skill structure"] + designSkill --> writeSkill["Write SKILL.md and docs"] + writeSkill --> verifySkill["Verify skill quality"] + verifySkill --> useSkill["Use and iterate skill"] + diff --git a/docs/skills/template-skill.md b/docs/skills/template-skill.md new file mode 100644 index 0000000..d98981a --- /dev/null +++ b/docs/skills/template-skill.md @@ -0,0 +1,167 @@ +--- +name: [skill-name] +description: [one-line description of when/why to use this skill] +--- + +# [Skill Title] + +> **Purpose**: One-line summary of what this skill does and when to use it. +> +> **How to use this template** +> +> - Copy this file into `.cursor/skills/[skill-name]/SKILL.md` (or into your project’s preferred skills directory). +> - Replace all bracketed placeholders like `[Skill Title]`, `[tool-binary]`, `[main workflow trigger]`, and `[path/to/module]` with concrete values. +> - Trim optional sections (**Concept diagram**, **Variants**, **Troubleshooting**) if they are not needed for this workflow. +> - Keep each final skill focused on a single primary workflow to stay readable and maintainable. + +## Concept diagram + +High-level flow for authoring and using this kind of skill: + +- (Optional) Add a mermaid diagram reference here, for example: `[path/to/skill-diagram.mmd]`. + +## When to Apply + +- **Primary use cases**: + - After / during **[main workflow trigger]** (for example: completing a feature or bug fix). + - When **[secondary trigger]** (for example: upgrading a dependency, level, or tool configuration). +- **Explicitly avoid**: + - Do **NOT** run during unrelated tasks; only apply when this workflow is part of the current objective or has been explicitly requested. + +## Preconditions + +- **Environment**: + - Project is checked out and dependencies installed. + - Required tools are available (for example: `[tool-binary]`, `[runtime-1]`, `[runtime-2]`, `[package-manager]`). +- **Repository state**: + - Working tree is clean or only contains changes relevant to this workflow. + - On the correct branch (for example: `main`, `develop`, or the feature branch under review). +- **Configuration / tool setup**: + - Any required config files are present (for example: `[tool-config].neon`, `.env`, `phpunit.xml`, `[tool-config]-baseline.neon`). + - If a baseline or ignore configuration exists, it is committed and understood (do not assume it is safe to delete or rewrite). + +## Process + +Copy this section and replace placeholders for each workflow. Prefer **numbered sub-sections** for major phases. + +### 1. Initial Analysis + +Explain how to run the main tool in **read-only / analysis** mode and how to interpret the output. + +```bash +# Example command (replace with real one) +[tool-binary] [subcommand] [path] --flag-1 --flag-2 +``` + +- Capture and skim the full output to understand: + - Error or finding categories. + - Affected files, modules, or namespaces. + - Whether a baseline or ignore configuration is already in place. +- If a baseline file exists, **respect it by default** – do not fix errors that are intentionally baselined unless explicitly requested. +- Focus first on **new** or **out-of-baseline** findings that were introduced by recent work. + +### 2. Categorize Issues + +Group findings or work items by type before fixing. Common categories: + +- **Type or schema issues**: Missing / wrong param & return types, mismatched generics, invalid payload shapes. +- **Undefined references**: Missing methods, properties, variables, constants, routes, or services. +- **Dead code**: Unused variables, unreachable branches, obsolete functions or classes. +- **Logic issues**: Incorrect comparisons, impossible conditions, misuse of nullable or optional values. +- **Documentation mismatches**: Docblocks or comments contradicting actual signatures or behavior. + +Decide which categories (and which paths/modules) are in-scope for this run. Prefer handling one or two categories or a single module per batch to keep diffs focused and reviewable. + +### 3. Fix Iteratively + +Work in **small, reviewable batches**, not all at once: + +1. Pick a category (or a small set of files, modules, or namespaces). +2. Apply minimal, conservative fixes that respect existing project conventions. +3. Re-run the tool for only the affected scope when possible. + +```bash +# Example: re-run only for a subset of paths +[tool-binary] [subcommand] [path/to/module] --flag-1 --flag-2 +``` + +- After each batch, confirm that: + - The total issue count for that scope is decreasing. + - No new categories of issues have been introduced. + - Fixes align with project coding standards and do not mix in unrelated refactors. + - You are not introducing broad new ignores or baselines without clear justification. + +### 4. Validate with Tests / Secondary Checks + +Once the primary tool reports success (or acceptable remaining issues for the chosen scope): + +- Run relevant automated tests or additional checks: + +```bash +# Example commands – replace or trim as needed +[test-runner-or-secondary-tool] +``` + +- If specific tests or checks map directly to the changed code, run those first for faster feedback. +- Only consider the workflow complete when: + - The primary tool is passing for the chosen scope (or remaining findings are explicitly accepted and documented), and + - Tests or secondary checks are green for the affected areas. + +## Checklists + +Use these checklists to track progress during the workflow. + +### Execution Checklist + +- [ ] Preconditions verified (environment, repo state, configuration / tool setup). +- [ ] Initial analysis run and output reviewed (including any baselines or ignores). +- [ ] Issues categorized by type and in-scope paths/modules selected. +- [ ] Fixes applied iteratively in small, reviewable batches. +- [ ] Tool re-run after each batch until results are stable for the chosen scope. +- [ ] Tests / secondary checks executed and passing (or failures documented and accepted). + +### Communication Checklist (Optional) + +- [ ] Summarized what was run (commands, scope, and options). +- [ ] Noted any trade-offs (for example: findings intentionally ignored or baselined). +- [ ] Highlighted any follow-up work that should be scheduled separately. + +## Variants (Optional) + +Describe common variations of the workflow, for example: + +- **Quick check**: Lightweight run over a narrow path for fast feedback. +- **Full project scan**: Comprehensive run across the entire codebase (more expensive; avoid during tight feedback loops). +- **CI mode**: Stricter flags or paths used in CI only. + +Be explicit about when to choose each variant. + +## Troubleshooting (Optional) + +Common failure modes and how to address them: + +- **Tool fails to start**: + - Verify the binary exists and is executable. + - Ensure dependencies are installed (for example: `[dependency-manager-install-command]`). +- **Configuration errors**: + - Point to the relevant config file(s) and typical fixes. +- **Too many findings**: + - Recommend creating / updating a baseline. + - Narrow the scope to a single module or category for the current run. + +## Safety / Things to Avoid + +- Do **not** apply automatic fixes without reviewing the diff. +- Do **not** mix large refactors with unrelated cosmetic changes in the same batch. +- Do **not** silence errors via ignores or baselines unless there is a clear, documented justification. + +## Example Summary Format + +When reporting results back to the user, use a concise structure like: + +- **Tool / mode**: `[tool-binary]` in `[quick check | full scan | CI mode]`. +- **Scope**: `[paths / modules]`. +- **Result**: + - `[N] issues fixed` + - `[M] issues remaining` (with brief explanation). +- **Follow-ups**: Short list of recommended next steps. diff --git a/phpunit.xml.dist b/phpunit.xml.dist new file mode 100644 index 0000000..98c615a --- /dev/null +++ b/phpunit.xml.dist @@ -0,0 +1,20 @@ + + + + + + + + + + + + tests + + + + diff --git a/prompts/skill-validation.md b/prompts/skill-validation.md new file mode 100644 index 0000000..3f3227a --- /dev/null +++ b/prompts/skill-validation.md @@ -0,0 +1,52 @@ +You are an expert technical editor helping maintain a library of Laravel Boost skills. + +Each skill is a markdown file called SKILL.md that follows these conventions: +- YAML frontmatter with at least: + - name: machine-readable skill identifier (kebab-case) + - description: one-line explanation of when/why to use the skill +- A clear H1 title. +- Concise sections that usually include: + - When to Apply + - Preconditions + - Process (often broken into numbered steps) + - Checklists (Execution / Communication) + - Safety / Things to Avoid + - Optional: Examples, References, Troubleshooting, Variants, Example Summary Format + +You must evaluate a single SKILL.md file strictly against these criteria: + +STRUCTURE (blocking if missing or obviously wrong) +- Has YAML frontmatter with non-empty name and description. +- Has a top-level H1 title. +- Does not contain obvious template placeholders such as [Skill Title], [tool-binary], [main workflow trigger], or TODO markers. + +CONTENT (usually warnings if missing) +- Mentions when to apply the skill and when NOT to. +- Describes prerequisites / preconditions before using the skill. +- Explains the process in concrete, ordered steps. +- Provides at least one checklist or clearly structured bullet list for execution or communication. +- Calls out safety considerations / things to avoid. + +TONE & QUALITY (warnings/improvements) +- Language is clear, unambiguous, and specific to this skill. +- Does not contradict itself or general Laravel practices. +- Uses examples that match the skill's purpose where relevant. +- Keep output high signal: maximum 5 warnings and 5 improvements. + +You MUST respond with ONLY JSON that matches this schema, no extra text: +{ + "skill_name": string, // inferred from frontmatter or path + "path": string, // relative path to the SKILL.md file + "valid": boolean, // false only for structural or severe content issues + "errors": string[], // blocking issues that should fail CI + "warnings": string[], // non-blocking consistency or clarity issues + "improvements": string[] // concrete suggestions to strengthen the skill +} + +Consider a skill INVALID (valid = false) when: +- Frontmatter is missing or name/description are empty or obviously placeholders. +- There is no clear H1 title. +- The file is clearly still the raw template (placeholders not filled in). + +Otherwise, set valid = true even if there are warnings. + diff --git a/refactor.md b/refactor.md deleted file mode 100644 index f6cf80e..0000000 --- a/refactor.md +++ /dev/null @@ -1,118 +0,0 @@ -# Codebase Refactor — Full Guidelines Compliance - -You are refactoring a Laravel codebase to achieve 100% alignment with **codebar-ag coding guidelines**. This prompt is used when (a) newly adopting guidelines in an existing project, or (b) cross-checking AI-generated implementations for compliance. - ---- - -## 1. Skill Discovery - -Locate skills from one of these paths (check in order; first existing wins): - -- `resources/boost/skills/` (when running inside this guidelines package repo) -- `vendor/codebar-ag/coding-guidelines/resources/boost/skills/` -- `guidelines/resources/boost/skills/` - -If none exist, search the workspace for `**/resources/boost/skills/*/SKILL.md` and use the nearest matching root as the active skill source path. - -Project overrides in `.ai/skills/{skill-name}/SKILL.md` take precedence over package defaults. - -**Action:** List all `SKILL.md` files. For each skill, extract: - -- `name` (from frontmatter or folder) -- `Tags` — the first path-like value (e.g. `app/Models/**/*.php`) is the glob for file discovery -- `Rules`, `Anti-Patterns`, `Examples` — apply these when analyzing and refactoring - ---- - -## 2. Processing Order (Dependency-Aware) - -Process skills in this order to avoid repeated edits and respect dependencies: - -| Phase | Skills | -|-------|--------| -| Foundation | `general`, `php`, `helperfunctions` | -| Data layer | `migrations`, `enums`, `models`, `traits` | -| Backend core | `actions`, `services`, `dto`, `exceptions`, `interfaces` | -| HTTP layer | `formrequests`, `controllers`, `middleware`, `requests`, `resources`, `routing` | -| Infrastructure | `commands`, `jobs`, `events`, `observers`, `policies` | -| Frontend | `blade`, `design`, `livewire`, `tailwind`, `translations` | -| Integrations | `saloon`, `docuware`, `albatros` (only if matching files exist) | -| Helpers | `helpers` | -| Testing | `phpunit`, `pesttesting`, `phpstan`, `dusk` | - ---- - -## 3. Per-Skill Workflow - -For each skill in order: - -1. **Match files** — Find all files in the workspace that match the skill’s glob patterns from Tags (e.g. `app/Http/Controllers/**/*.php`). -2. **Skip if empty** — If no files match (e.g. no Albatros service), skip the skill. -3. **Read skill** — Load the full `SKILL.md` content for Rules, Examples, and Anti-Patterns. -4. **Analyze** — Check each matching file against the Rules and Anti-Patterns. -5. **Refactor** — Fix violations using the skill’s Examples. Preserve behavior; do not introduce breaking changes. -6. **Batch edits** — Group edits by skill (e.g. all controller fixes in one pass). - ---- - -## 4. Efficiency Directives - -- **Incremental changes** — Prefer small, reviewable edits over large rewrites. -- **Prioritize when large** — If the scope is large, produce a prioritized compliance report and refactor in phases. -- **Cross-check mode** — When validating recent AI work, focus first on recently changed files, then broaden if needed. -- **Avoid redundant passes** — Process skills in the defined order so earlier fixes are not undone by later ones. - ---- - -## 5. Output Format - -### Phase 0: Plan and Confirm (mandatory) - -Before making any code changes: - -- Enter planning mode and produce a concrete implementation plan. -- Include: applicable skills, target files, prioritized violation groups, and intended edit batches. -- Present the plan to the user and request explicit approval. -- Do not edit files, run formatters, or execute write operations until the user confirms the plan. - -### Phase A: Compliance Report (before edits) - -Produce a concise report: - -- Skills that apply (have matching files) -- Skills that are skipped (no matching files) -- Per skill: files with violations, brief description of each violation -- Summary: total violations, suggested commit grouping - -### Phase B: Refactoring (skill-by-skill) - -For each skill with violations: - -1. State the skill name and what is being fixed. -2. Apply the changes. -3. Suggest a commit message for that batch of changes. - ---- - -## 6. Tags-to-Glob Mapping - -Skills use Tags like: - -``` -**Tags:** app/Models/**/*.php, laravel, php, backend, eloquent, model, database -``` - -Use the **first path-like Tag** (e.g. `app/Models/**/*.php`, `database/migrations/**/*.php`, `resources/views/**/*.blade.php`) as the glob. Some skills have multiple paths (e.g. `app/Events/**/*.php`, `app/Listeners/**/*.php`); include all path-like Tags for that skill. - ---- - -## 7. Non-Breaking Refactors Only - -- Do not change observable behavior. -- Do not remove or rename public APIs without explicit approval. -- Prefer additive fixes (add missing types, FormRequests, transactions) over removals. -- If a refactor is ambiguous or risky, report it and do not apply it automatically. - ---- - -**Begin by discovering skills, then producing the compliance report, then executing refactors in the specified order.** diff --git a/resources/boost/skills/actions/SKILL.md b/resources/boost/skills/actions/SKILL.md index ab4ce2a..aead827 100644 --- a/resources/boost/skills/actions/SKILL.md +++ b/resources/boost/skills/actions/SKILL.md @@ -1,25 +1,74 @@ --- name: actions description: Single-purpose business logic classes that encapsulate one well-defined business operation. Actions are the primary location for business logic in Laravel applications, invoked from controllers, commands, or jobs. +compatible_agents: + - architect + - implement + - refactor + - review --- -**Name:** Actions -**Description:** Single-purpose business logic classes that encapsulate one well-defined business operation. Actions are the primary location for business logic in Laravel applications, invoked from controllers, commands, or jobs. -**Compatible Agents:** general-purpose, backend -**Tags:** app/Actions/**/*.php, laravel, php, backend, business-logic, action +# Actions -## Rules +## When to Apply -- Action classes live in `app/Actions/` -- Each action represents **one single business operation** — if you can't describe it in a single sentence, split it up -- Use a clear verb-noun naming pattern: `CreateInvoice`, `SendPasswordResetEmail`, `ArchiveExpiredSubscriptions` -- Never use vague names like `InvoiceAction` or `UserHandler` -- Actions expose a single public `execute()` method -- Keep the constructor for dependency injection only -- Actions are resolved via the service container -- Never include HTTP concerns (request, response, redirects) in an action -- Never put multi-domain orchestration in an action — use a Service instead -- Never put reusable formatting or utility logic in an action — use a Helper +- When implementing or refactoring a **single business operation** that can be described in one sentence. +- When slimming **fat controllers, commands, or jobs** by moving business logic out of them. +- When multiple entry points (controller, command, job, listener) should reuse the **same business logic**. +- When aligning legacy code with the project’s pattern of **`app/Actions/` classes with `execute()`**. + +## When Not to Use + +- Tiny, one-line behavior that naturally belongs on the model and has no reuse. +- Cross-domain orchestration with retries/workflows that should be a Service. +- HTTP boundary concerns (validation/response shaping) that belong in controllers/requests. + +## Preconditions + +- The Laravel project is installed and bootstrapped. +- The `app/Actions/` directory exists (or will be created) and is autoloaded by Composer. +- Related models, notifications, events, and DTOs required by the action already exist or have a clear design. If prerequisites are missing, create them first or narrow the Action scope. +- Authorization and validation rules are defined at the controller, policy, or Form Request level. + +## Process + +### 1. Decide if an Action is Appropriate + +- Confirm the work is a **single business operation**, not multi-step orchestration across domains. +- Prefer an Action when: + - The behavior will be reused from multiple places. + - The behavior is business logic, not HTTP or infrastructure logic. +- If the behavior crosses multiple domains or requires complex orchestration, prefer a **Service** instead. + +### 2. Design the Action + +- Place the class in `app/Actions/`. +- Use a clear verb–noun naming pattern: + - Examples: `CreateInvoice`, `SendPasswordResetEmail`, `ArchiveExpiredSubscriptions`. + - Avoid vague names like `InvoiceAction`, `UserHandler`, `DataProcessor`. +- Plan for a **single public `execute()` method** that represents the operation. +- Keep the constructor for dependency injection only (repositories, services, helpers, etc.). + +### 3. Implement the Action + +- Implement `execute()` with the full business operation: + - Perform any database writes and domain logic required for the operation. + - Call other Actions or Services as needed, but keep the responsibility focused. +- Resolve the Action through the **service container** (type-hint it in controllers, commands, or jobs). +- Do **not**: + - Include HTTP concerns (`Request`, `Response`, redirects) inside the Action. + - Include cross-domain orchestration that belongs in a Service. + - Put reusable formatting or generic utility logic here (use Helpers instead). + +### 4. Integrate from Controllers, Commands, and Jobs + +- In controllers: + - Validate input via Form Requests. + - Authorize via policies or `$this->authorize()`. + - Inject the Action and call `execute()` with validated data or models. +- In console commands or queued jobs: + - Resolve the Action from the container. + - Iterate over models or DTOs and delegate the business operation to `execute()`. ## Examples @@ -78,14 +127,44 @@ class GenerateInvoicesCommand extends Command } ``` -## Anti-Patterns +## Checklists -- Putting HTTP concerns (`Request`, `Response`, redirects) inside an action -- Creating multi-step orchestration across domains in a single action (use a Service) -- Naming an action vaguely: `InvoiceAction`, `UserHandler`, `DataProcessor` -- Adding multiple `execute()` methods or public methods beyond the single operation -- Adding business logic in a constructor — use `execute()` for that -- Performing database queries unrelated to the action's single responsibility +### Execution Checklist + +- [ ] Verified the behavior is a **single business operation** appropriate for an Action. +- [ ] Created or updated a class under `app/Actions/` with a clear verb–noun name. +- [ ] Implemented a single public `execute()` method for the operation. +- [ ] Kept the constructor for dependency injection only. +- [ ] Removed HTTP concerns from the Action (validation, requests, responses, redirects). +- [ ] Ensured authorization is handled in controllers, policies, or Form Requests. +- [ ] Updated controllers, commands, or jobs to **delegate to the Action** instead of duplicating logic. + +## Testing Guidance + +- Add focused tests for each Action behavior branch (success/failure edge cases). +- Mock/fake external dependencies (mail, notifications, queue) and assert interaction boundaries. +- Keep integration coverage in feature tests where the Action is invoked from controllers/commands/jobs. + +## Safety / Things to Avoid + +- Putting HTTP concerns (`Request`, `Response`, redirects) inside an Action. +- Creating multi-step orchestration across domains in a single Action (use a Service instead). +- Naming an Action vaguely, for example `InvoiceAction`, `UserHandler`, `DataProcessor`. +- Adding multiple `execute()` methods or extra public methods beyond the single operation. +- Adding business logic in a constructor — keep it in `execute()`. +- Performing database queries unrelated to the Action’s single responsibility. + +```php +// Anti-pattern: Action doing orchestration + HTTP concerns +class ProcessInvoiceAction +{ + public function execute(Request $request): RedirectResponse + { + // Mixed responsibilities: validation, orchestration, and HTTP response + // Move validation/response to controller, orchestration to Service. + } +} +``` ## References diff --git a/resources/boost/skills/albatros/SKILL.md b/resources/boost/skills/albatros/SKILL.md index 24c856e..0067dc7 100644 --- a/resources/boost/skills/albatros/SKILL.md +++ b/resources/boost/skills/albatros/SKILL.md @@ -1,18 +1,33 @@ --- name: albatros description: Albatros accounting API integration via Saloon. Use when working with app/Services/Albatros/, AlbatrosConnector, or Albatros DTOs. +compatible_agents: + - architect + - implement + - refactor + - review --- -**Name:** Albatros API Integration -**Description:** Albatros accounting API integration via Saloon. Use when working with app/Services/Albatros/, AlbatrosConnector, or Albatros DTOs. -**Compatible Agents:** general-purpose, backend -**Tags:** app/Services/Albatros/**/*.php, albatros, accounting, saloon, api-integration +# Albatros API Integration + +## When to Use + +- You are integrating with the Albatros accounting API specifically. +- You are editing `app/Services/Albatros/`, its connector, requests, or DTO mapping. +- You need typed DTO responses, pagination support, and cached reference data. + +## When Not to Use + +- The integration target is not Albatros (use the generic integration/service skills instead). +- The operation is local business logic with no external API call. +- You need one-off scripts without reusable connector/request architecture. ## Rules - `AlbatrosConnector` extends `Saloon\Http\Connector` - Token-based authentication with Mandant header - Base URL from `config('albatros.base_url')` +- Keep credentials and Mandant values in `.env`, mapped through `config/albatros.php`; never hardcode secrets. - `AlbatrosService` wraps all API calls and returns typed DTOs or `Collection` of DTOs - Use `Cache` for reference data (addresses, accounts, VAT codes, etc.) - Paginated endpoints use `fetchAllPages()` helper with `lastIndex` parameter @@ -24,6 +39,11 @@ description: Albatros accounting API integration via Saloon. Use when working wi - Handle API field name casing variations in `fromArray()` - Cache reference data to minimize API calls - Use `clearCache()` method when data needs refreshing +- Scope cache keys by Mandant to avoid cross-tenant contamination +- Fail fast on non-success responses and use retries only for transient errors (timeouts/429/5xx) +- In `fetchAllPages()`, document and keep retry/backoff explicit (attempts + delay) for predictable operations. +- Treat empty-string `lastIndex` as the stop sentinel unless API docs specify a different terminal token. +- Normalize response shape at service boundary (for example `items` + `lastIndex`) before DTO mapping. - All monetary values as `decimal:2` ## Examples @@ -102,17 +122,67 @@ readonly class AdresseData // Service with caching public function getAdressen(): Collection { - return Cache::remember('albatros.adressen', 3600, fn () => + return Cache::remember($this->cacheKey('adressen'), 3600, fn () => $this->fetchAllPages(fn ($lastIndex) => new ListAdressenRequest(lastIndex: $lastIndex)) ); } public function clearCache(): void { - Cache::forget('albatros.adressen'); + Cache::forget($this->cacheKey('adressen')); } ``` +```php +// Service pagination + error handling pattern +use Illuminate\Support\Collection; +use Saloon\Exceptions\Request\RequestException; + +private function fetchAllPages(callable $requestFactory): Collection +{ + $all = collect(); + $lastIndex = ''; + + do { + $response = retry(3, function () use ($requestFactory, $lastIndex) { + return $this->connector->send($requestFactory($lastIndex)); + }, 200); + + if (! $response->successful()) { + throw new RequestException($response, 'Albatros request failed.'); + } + + $payload = $response->json(); + $items = collect($payload['items'] ?? []); + $all = $all->merge($items->map(fn (array $row) => AdresseData::fromArray($row))); + $lastIndex = (string) ($payload['lastIndex'] ?? ''); + } while ($lastIndex !== ''); + + return $all; +} + +private function cacheKey(string $segment): string +{ + return sprintf('albatros.%s.%s', config('albatros.mandant'), $segment); +} +``` + +```php +// Minimal config/albatros.php pattern +return [ + 'base_url' => env('ALBATROS_BASE_URL'), + 'mandant' => env('ALBATROS_MANDANT'), + 'token' => env('ALBATROS_TOKEN'), +]; +``` + +```php +// Mocked Saloon test note (no real API calls) +Saloon::fake([ + '*' => MockResponse::make(['items' => [], 'lastIndex' => ''], 200), +]); +``` + ## Anti-Patterns - Making uncached API calls for reference data that rarely changes @@ -121,6 +191,7 @@ public function clearCache(): void - Not handling API field name casing variations in `fromArray()` - Storing monetary values as float or string instead of `decimal:2` - Forgetting to call `clearCache()` when reference data is updated +- Reusing non-Mandant-specific cache keys across Mandant contexts ## References diff --git a/resources/boost/skills/blade/SKILL.md b/resources/boost/skills/blade/SKILL.md index 8b8e0f1..a137d5d 100644 --- a/resources/boost/skills/blade/SKILL.md +++ b/resources/boost/skills/blade/SKILL.md @@ -1,25 +1,50 @@ --- name: blade description: Laravel Blade template conventions covering components, output escaping, security, structure, and formatting. +compatible_agents: + - implement + - refactor + - review --- -**Name:** Blade Templates -**Description:** Laravel Blade template conventions covering components, output escaping, security, structure, and formatting. -**Compatible Agents:** general-purpose, frontend -**Tags:** resources/views/**/*.blade.php, laravel, php, frontend, blade, template, html +# Blade Templates + +## When to Use + +- Creating or refactoring server-rendered view templates in `resources/views/`. +- Building reusable UI fragments with Blade components. +- Rendering validated/authorized data from controllers, Livewire, and view models. + +## When Not to Use + +- Complex stateful interactions that should live in Livewire components. +- Heavy client-side application flows that require a dedicated SPA framework. +- Raw PHP templating where Blade directives provide clearer intent. + +## Preconditions + +- Laravel Blade is enabled (default Laravel app setup). +- If `x-*` Alpine directives are used, Alpine is loaded by the frontend build/layout. +- If `wire:*` directives are used, Livewire is installed and version-compatible. +- Data passed to views is already validated and authorized upstream. + +## Process Checklist + +- [ ] Decide whether this should be plain Blade, a Blade component, or Livewire. +- [ ] Keep markup declarative and move reusable blocks into components. +- [ ] Render user-provided values with `{{ }}` by default. +- [ ] Use `{!! !!}` only for trusted, pre-sanitized HTML. +- [ ] Keep scripts/styles out of Blade files unless explicitly required by framework conventions. +- [ ] Ensure text and labeling follow project language/content standards. ## Rules -- Use Blade components (``) for reusable UI pieces -- Prefer anonymous components for simple, presentation-only elements -- Use class-based components when logic is needed -- Use `{{ }}` for escaped output (default) — never output raw user input unescaped -- Use `{!! !!}` only when the content is explicitly safe (e.g., pre-sanitized HTML) -- No inline `