# AGENTS.md — Project Backend

Instructions for every coding agent in this repository. Claude Code loads this
through `CLAUDE.md`, which also imports every steering file. Codex / Antigravity /
OpenCode cannot import files: open the files the [task routing table](#task-routing)
lists, or load the matching `project-*` skill.

**This project** (name: `APP_NAME` in `.env`) is a Laravel 13 API backend built on the shared project base. The apps it serves (surfaces) and their
technology are in `config/docs.php` → `surfaces` — `client` (trainee, Flutter),
`trainer` (Flutter), `admin`, `center` and `provider` (Vue dashboards). Business scope
comes from the BRD: working file `docs/brd/BRD-Morvia-Project-Guide-en.md`, one feature
per file in `docs/brd/features/`. Per-surface docs are in `docs/{surface}/`.

## Read first — cheapest path (TD-05)

1. `php artisan docs:brief {surface} {feature}` (or MCP `project-docs` → `get-integration-brief`):
   registry row, the feature doc's Quick reference, the BRD section and the decision rows in one page.
2. `.kiro/steering/` — the rules for your task only (routing table below).
3. Only if the brief is not enough: one section of the feature doc, `docs/brd/features/{ID}.md`,
   a `docs/DECISIONS_LOG.md` entry, the feature's lines in `docs/app_screens/INDEX.md`.

Never read `PROJECT_BRAIN.md`, `DECISIONS.md`, `CHANGELOG.md` or a BRD file end to end —
`grep -n` the ID and read that slice. Limits: `config/docs.php` → `budgets` (`DocsBudgetTest`).

## Task routing

| Task | Load skill | Rule files to read (`.kiro/steering/`) |
|------|-----------|----------------------------------------|
| Set up the project, add/change a surface (guard) or its tech (Flutter/React), ingest the BRD or screens | `project-init` | `api-surfaces.md`, `business-logic.md`, `feature-documentation.md` |
| Build, change, or fix a feature / endpoint | `project-feature` | `business-logic.md`, `api-surfaces.md`, `architecture.md`, `code-standards.md`, `postman-collection.md` |
| Admin CRUD screen | `project-feature` | + `crud-conventions.md`, `base-project-style.md` |
| Migrations, models, enums, seeders | `project-migrations` | `business-logic.md` |
| Write or bump a feature doc, changelog, registry | `project-feature-docs` | `feature-documentation.md` |
| Ambiguous requirement, BRD/screen/schema conflict, record a decision | `project-decisions` | `business-logic.md` |
| Tests | `testing-best-practices` (Boost) | `feature-documentation.md` (AC-ID naming) |
| Postman collection, request field labels | `project-postman` | `postman-collection.md` |

`project-*` skills live in `.agents/skills/` and are mirrored to `.claude/skills/`;
re-sync after editing one. Steering file summaries, the mirror command, Codex
command rules, MCP servers and the docs gate: `docs/AGENT_SETUP.md`.

## Non-negotiables

- Every feature traces to BRD IDs or a recorded decision. No invented scope; open
  decisions are never silently resolved — use `DECISIONS.md` or ask.
- Business rules live in `app/Domain/{Module}/Rules`, not in controllers or requests.
- Responses always use `json()` → `{status, message, data}`.
- A feature is not done until its doc in `docs/{surface}/{slug}.md` is written or
  bumped, and the `PROJECT_BRAIN.md` registry and `docs/CHANGELOG.md` are updated.
  Response examples in docs are real (from tests or the `/tester` console), never imagined.
- Never hand-edit `docs/postman-collection.json`; run `php artisan postman:generate`.
- `docs/brd/*` and `docs/app_screens/*` are input: never edit them. Record
  interpretations in `docs/DECISIONS.md`.
- The docs viewer (`/docs`), API console (`/tester`) and `project-docs` MCP server
  run on every environment **except production** (TD-01). Never weaken that gate.

## Commands

```bash
php artisan test --compact [--filter=DocsViewerTest]
vendor/bin/pint --dirty                # Pint
php artisan postman:generate           # regenerate the collection
php artisan docs:brief client auth     # start every feature here
php artisan mcp:start project-docs      # docs MCP server over stdio
```

More commands: `docs/AGENT_SETUP.md`.

## Rule precedence

The `<laravel-boost-guidelines>` block below is generated by Laravel Boost and
is rewritten on `boost:update` — do not edit inside it. When it conflicts with
the project rules above or in `.kiro/steering/`, **the project rules win**:

- **Documentation files:** feature docs are always requested (`feature-documentation.md`).
- **New folders:** `app/Domain/{Module}`, `app/Mcp/`, `routes/api/v1/{surface}.php`, and
  the per-surface folders of `api-surfaces.md` are pre-approved.
- **Comments:** PHPDoc on every class and public/protected method; short `#` why-comments allowed (`code-standards.md`).
- **Generators:** prefer `make:crud`, `make:action`, `make:query`, `make:command-service`, `make:value-object` over `make:class`.
- **Deployment:** the project is not on Laravel Cloud; ignore Cloud suggestions.

===

<laravel-boost-guidelines>
=== foundation rules ===

# Laravel Boost Guidelines

## Foundational Context

This application is a Laravel application running on PHP 8.4. Always use the APIs that match the installed major version of each package — do not assume a version.

Before relying on a package's API, confirm its installed version:
- PHP packages: run `composer show --direct` to list direct dependencies with versions, or `composer show <vendor/package>` for a single package.
- JS packages: check `package.json` for the installed versions.

## Skills Activation

This project has domain-specific skills available in `**/skills/**`. You MUST activate the relevant skill whenever you work in that domain—don't wait until you're stuck.

## Conventions

- You must follow all existing code conventions used in this application. When creating or editing a file, check sibling files for the correct structure, approach, and naming.
- Use descriptive names for variables and methods. For example, `isRegisteredForDiscounts`, not `discount()`.
- Check for existing components to reuse before writing a new one.

## Verification Scripts

- Do not create verification scripts or tinker when tests cover that functionality and prove they work. Unit and feature tests are more important.

## Application Structure & Architecture

- Stick to existing directory structure; don't create new base folders without approval.
- Do not change the application's dependencies without approval.

## Frontend Bundling

- If a frontend change doesn't show in the UI or you get a "Unable to locate file in Vite manifest" error, run `npm run build` or ask the user to run `npm run dev` or `composer run dev`.

## Documentation Files

- You must only create documentation files if explicitly requested by the user.

=== boost rules ===

# Laravel Boost

## Tools

- Laravel Boost is an MCP server with tools designed specifically for this application. Prefer Boost tools over manual alternatives like shell commands or file reads.
- Use `database-query` to run read-only queries against the database instead of writing raw SQL in tinker.
- Use `database-schema` to inspect table structure before writing migrations or models.
- Use `get-absolute-url` to resolve the correct scheme, domain, and port for project URLs. Always use this before sharing a URL with the user.
- Use `browser-logs` to read browser logs, errors, and exceptions. Only recent logs are useful, ignore old entries.

## Searching Documentation (IMPORTANT)

- Use `search-docs` before changes that depend on Laravel ecosystem APIs, behavior, configuration, or version-specific syntax. Skip it for copy-only edits and other changes where package documentation is irrelevant. Reuse sufficient results already in context instead of searching again.
- Pass a `packages` array to scope results when you know which packages are relevant.
- Use multiple broad, topic-based queries: `['rate limiting', 'routing rate limiting', 'routing']`. Expect the most relevant results first.
- Do not add package names to queries because package info is already shared. Use `test resource table`, not `filament 4 test resource table`.

### Search Syntax

1. Use words for auto-stemmed AND logic: `rate limit` matches both "rate" AND "limit".
2. Use `"quoted phrases"` for exact position matching: `"infinite scroll"` requires adjacent words in order.
3. Combine words and phrases for mixed queries: `middleware "rate limit"`.
4. Use multiple queries for OR logic: `queries=["authentication", "middleware"]`.

## Project Rules

- This project contains committed, area-grouped rules in `.ai/rules` when that directory exists, including path-scoped framework guidelines under `.ai/rules/boost`. Before you enter plan mode or create/edit any file, you MUST first: open @.ai/rules/index.md (it maps file globs to rule files), read every rule file whose globs cover the path(s) in scope, and run `grep -rin 'keyword' .ai/rules` to catch what a path match alone misses. Do not write code until you have read and are following every matching rule. If `.ai/rules` does not exist, continue without it.

## Artisan

- Run Artisan commands directly via the command line (e.g., `php artisan route:list`). Use `php artisan list` to discover available commands and `php artisan [command] --help` to check parameters.
- Inspect routes with `php artisan route:list`. Filter with: `--method=GET`, `--name=users`, `--path=api`, `--except-vendor`, `--only-vendor`.
- Read configuration values using dot notation: `php artisan config:show app.name`, `php artisan config:show database.default`. Or read config files directly from the `config/` directory.

## Tinker

- Execute PHP in app context for debugging and testing code. Do not create models without user approval, prefer tests with factories instead. Prefer existing Artisan commands over custom tinker code.
- Always use single quotes to prevent shell expansion: `php artisan tinker --execute 'Your::code();'`
  - Double quotes for PHP strings inside: `php artisan tinker --execute 'User::where("active", true)->count();'`

=== php rules ===

# PHP

- Always use curly braces for control structures, even for single-line bodies.
- Use PHP 8 constructor property promotion: `public function __construct(public GitHub $github) { }`. Do not leave empty zero-parameter `__construct()` methods unless the constructor is private.
- Use explicit return type declarations and type hints for all method parameters: `function isAccessible(User $user, ?string $path = null): bool`
- Follow existing application Enum naming conventions.
- Prefer PHPDoc blocks over inline comments. Only add inline comments for exceptionally complex logic.
- Use array shape type definitions in PHPDoc blocks.

=== deployments rules ===

# Deployment

- Laravel can be deployed using [Laravel Cloud](https://cloud.laravel.com/), which is the fastest way to deploy and scale production Laravel applications.

=== tests rules ===

# Test Enforcement

- Add or update tests for behavior and logic changes when a test provides meaningful regression coverage.
- Pure copy, styling, and layout-only changes do not require new or updated tests.
- When test coverage applies, run the affected tests and ensure they pass.
- Test the changed behavior and its important failure modes, but do not add tests beyond them.
- Read the `testing-best-practices` skill before writing tests.

=== laravel/core rules ===

# Do Things the Laravel Way

- Use `php artisan make:` commands to create new files (i.e. migrations, controllers, models, etc.). You can list available Artisan commands using `php artisan list` and check their parameters with `php artisan [command] --help`.
- If you're creating a generic PHP class, use `php artisan make:class`.
- Pass `--no-interaction` to all Artisan commands to ensure they work without user input. You should also pass the correct `--options` to ensure correct behavior.

### Model Creation

- When creating new models, create useful factories and seeders for them too. Ask the user if they need any other things, using `php artisan make:model --help` to check the available options.

## APIs & Eloquent Resources

- For APIs, default to using Eloquent API Resources and API versioning unless existing API routes do not, then you should follow existing application convention.

## URL Generation

- When generating links to other pages, prefer named routes and the `route()` function.

## Testing

- When creating models for tests, use the factories for the models. Check if the factory has custom states that can be used before manually setting up the model.
- Faker: Use methods such as `$this->faker->word()` or `fake()->randomDigit()`. Follow existing conventions whether to use `$this->faker` or `fake()`.
- When creating tests, make use of `php artisan make:test [options] {name}` to create a feature test, and pass `--unit` to create a unit test. Most tests should be feature tests.

=== pint/core rules ===

# Laravel Pint Code Formatter

- If you have modified any PHP files, you must run `vendor/bin/pint --dirty --format agent` before finalizing changes to ensure your code matches the project's expected style.
- Do not run `vendor/bin/pint --test --format agent`, simply run `vendor/bin/pint --format agent` to fix any formatting issues.

=== phpunit/core rules ===

# PHPUnit

- This project uses PHPUnit. Create tests with `php artisan make:test --phpunit {name}`.
- Do not include the test suite directory in `{name}`. Use `SomeFeatureTest`, not `Feature/SomeFeatureTest`.
- Read the `testing-best-practices` skill for guidance on coverage, naming, structure, dependency isolation, and review.

## Running Tests

- Run the narrowest set of tests that covers the change. Pass a file path or `--filter=testName` to `php artisan test --compact`.
- Rerun a test after each change to it.
- Run `vendor/bin/phpunit` to call the test runner directly. It accepts the same file path and `--filter=testName` arguments.

</laravel-boost-guidelines>
