Verify a Laravel change before calling it done, and orient in an unfamiliar Laravel codebase. Use after editing PHP, Blade, routes, config or migrations; when asked to "check", "verify" or "make sure it works"; before committing; or before changing code you have not read (what calls it, which tests cover it).
Installs into .claude/skills of the current project.
Are you the author of Ai Verify?
Add the live security badge to your README. It updates with every re-scan.
[](https://www.skillsdirectory.com/skills/semitexa-ai-verify)
---
name: ai-verify
description: Verify a Laravel change before calling it done, and orient in an unfamiliar Laravel codebase. Use after editing PHP, Blade, routes, config or migrations; when asked to "check", "verify" or "make sure it works"; before committing; or before changing code you have not read (what calls it, which tests cover it).
---
# Verify Laravel changes with ai:verify
## The loop
1. Make a coherent change. That can be one fix or one feature slice; it doesn't have to be every file you will eventually touch.
2. Run `php artisan ai:verify`. With no options it verifies uncommitted work: staged, unstaged and untracked files.
3. Read the final line, `{"kind":"verdict","verdict":...}`.
4. On `fail`, fix the `violation` events in order and go back to step 2. Each violation has `path`, `line`, `rule`, `message` and sometimes a `tip`, such as `vendor/bin/pint app/Foo.php` or `vendor/bin/phpcbf app/Foo.php`. A `command.<name>` violation comes from a check the project added; its tip is the exact command to reproduce it.
5. On `incomplete`, don't claim success. Check `unchecked_files` (nothing read those files) and any `result` with `status: incomplete` (timeout, crash, or a required tool missing). Fix the cause, or tell the user exactly what could not be verified.
6. On `pass`, check `gaps`: those checks did not run, so say which ones when you report the result. Adding a dependency such as Larastan is the project owner's decision, so mention it rather than installing it unasked. Then follow any `restart` hints (`queue:restart`, `octane:reload`, `config:clear`) before testing in a browser.
## As MCP tools (Laravel Boost)
If Laravel Boost's MCP server is connected, the commands are also tools, with the same JSON the commands print with `--json`:
| Tool | Same as | Arguments |
|---|---|---|
| `ai-verify` | `php artisan ai:verify --json` | `files`, `git_ref`, `scope`, `timeout` (seconds, for long suites) |
| `ai-graph` | `php artisan ai:graph --json` | `node`, `impact` |
| `ai-verify-receipt` | `php artisan ai:verify:receipt --json` | `id`, `unread` |
A `fail` verdict is a normal answer, not a tool error: read `violations`, fix them and call `ai-verify` again.
## Receipts and commits
- Every run writes a receipt (`{"kind":"receipt","id":"rcpt-…"}`). `php artisan ai:verify:receipt` shows whether it still **holds**: it is intact, the verdict was `pass`, and nothing changed since. Check it before claiming the work is verified.
- Commit exactly what you verified: `git add -A` after a passing run. With the git hook installed (`ai:verify:install --git-hook`), the commit gets an `AI-Verify: pass rcpt-… tree=…` trailer, and CI compares that tree with the commit's own.
- If the hook prints `no AI-Verify trailer — this commit is not the state … verified`, it lists the files that differ. Stage them, or re-run `ai:verify` on what you commit.
- If the hook prints `the commit message may not describe this change`, the subject names something (a field, a method) whose line you did not change, while you changed a line just like it. Either you edited the wrong line, or the message is wrong. Fix the one that is wrong and amend.
- To stamp a commit you already made: `php artisan ai:verify --git-ref=HEAD~1`, then `git commit --amend --no-edit`.
## Choosing the input
| Situation | Command |
|---|---|
| Normal work | `php artisan ai:verify` |
| Whole branch before a PR | `php artisan ai:verify --git-ref=main` |
| Specific files | `php artisan ai:verify --files=app/Models/Post.php,routes/web.php` |
| Fast inner loop | `php artisan ai:verify --scope=minimal` |
| Risky or cross-cutting change | `php artisan ai:verify --scope=broad --impact` |
Scope widens to `broad` automatically for providers, contracts, `bootstrap/app.php`, `composer.json` and large change sets. Read the `expansion` events to see why.
## Rules
- Never delete, skip (`->skip()`, `markTestSkipped`), `->only()`, or hollow out tests to get a pass. The `test_integrity` check compares changed test files with git HEAD and fails on any of these.
- If removing a test is genuinely right, for example because it moved elsewhere, add `// verify:accept-test-change <reason>` to the test file and say so to the user.
- `pre-existing` / `severity: warning` violations were already there before your change. You may mention them, but don't fix unrelated code unless asked.
## Orientation with ai:graph
- `php artisan ai:graph`: routes and their actions, the most-depended-on classes, and code that no test reaches.
- `php artisan ai:graph posts.show` or `/posts/{post}`: controller@method, FormRequest, middleware, views, models (with table and policy), and the tests that hit the route.
- `php artisan ai:graph "App\Models\Post"`: what the class uses, what uses it, and which tests cover it.
- `php artisan ai:graph --impact=app/Models/Post.php`: blast radius (low/medium/high) and the tests to run.
Add `--json` for machine-readable output. It is the default when stdout is not a terminal.