框架无关 · 零配置 · 安装即用 · 节省高达 99.8% 的 AI Token 消耗
随着 Claude Code、Cursor、Devin、Gemini CLI 等 AI 编程助手的普及,越来越多的开发团队开始让 AI Agent 代替人工执行测试、静态分析和代码重构。
但这些工具的输出,从未为 AI 设计过。
以一个拥有 1000 个测试用例的项目为例,运行 Pest 之后 Agent 收到的是:
PHPUnit 12.5.14 by Sebastian Bergmann and contributors. ............................................................. 61 / 1002 ( 6%)............................................................. 122 / 1002 ( 12%)............................................................. 183 / 1002 ( 18%)... (省略数百行进度点)............................................. 1002 / 1002 (100%) Time: 00:00.321, Memory: 46.50 MB OK (1002 tests, 1002 assertions) |
|---|
这段输出对人类友好,但对 AI Agent 是纯粹的噪音:
● Agent 消耗大量 Token 处理进度条,却只关心最后一行结论
● 测试失败时,错误信息淹没在海量内容里,Agent 难以精准定位
● 输出大小与测试数量正比增长,项目越大 Token 浪费越严重
PAO(PHP Agent Output) 是一个与框架完全无关的 PHP 工具输出优化包,由 Laravel 官方团队维护,托管在 laravel/ 命名空间下,但不依赖 Laravel,不依赖任何框架。
它的核心逻辑只有一条:
检测到 AI Agent 环境 → 结构化 JSON 输出。未检测到 AI Agent → 输出完全不变,人类体验零影响
支持的 PHP 工具:
工具 | 版本 |
|---|---|
Pest | 4–5 |
PHPUnit | 12–13 |
Paratest | 任意 |
PHPStan | 任意 |
Rector | 任意 |
支持的 PHP 项目类型:Laravel、Symfony、Webman、Laminas、Slim、vanilla PHP……任意使用 Composer 的 PHP 项目。
支持检测的 AI Agent 环境:Claude Code、Cursor、Devin、Gemini CLI 等主流 AI 编程助手。
composer require laravel/pao --dev |
|---|
就这一行。 无需:
● 修改 phpunit.xml 或 pest.config.php
● 添加任何配置文件
● 在代码中引用任何类
● 注册任何服务提供者(非 Laravel 项目无此概念)
PAO 通过 Composer 的 files autoload 机制自动注入,每次 PHP 进程启动时自动执行检测逻辑。
Agent 环境下,安装 PAO 前:
PASS Tests\Unit\UserServiceTest ✓ it creates a user with valid data 0.05s ✓ it rejects duplicate email 0.03s FAIL Tests\Feature\AuthControllerTest ⨯ it returns 401 when token expires 0.02s ────────────────────────────────────────────────────────────────────── FAILED Tests\Feature\AuthControllerTest > it returns 401 when token expires Expected response status 401 but received 500. at tests/Feature/AuthControllerTest.php:64 Tests: 1 failed, 106 passed (859 assertions) Duration: 14.08s |
|---|
Agent 环境下,安装 PAO 后:
{ "tool": "pest", "result": "failed", "tests": 107, "passed": 106, "failed": 1, "duration_ms": 14080, "failures": [ { "test": "Tests\\Feature\\AuthControllerTest > it returns 401 when token expires", "file": "/var/www/app/tests/Feature/AuthControllerTest.php", "line": 64, "message": "Expected response status 401 but received 500.", "trace": [ "/var/www/app/tests/Feature/AuthControllerTest.php:64" ] } ]} |
|---|
Token 消耗从几百降到几十行,Agent 直接读取 file 和 line 精准定位问题。
{ "tool": "phpstan", "result": "failed", "errors": 2, "error_details": { "/app/Service/UserService.php": [ { "line": 23, "message": "Method UserService::find() should return User but returns null.", "identifier": "return.type" } ] }} |
|---|
当使用 --coverage 等插件时,额外输出会清理 ANSI 色码后放入 raw 数组:
{ "tool": "pest", "result": "passed", "tests": 1002, "passed": 1002, "duration_ms": 1520, "raw": [ "Http/Controllers/Controller 100.0%", "Models/User 0.0%", "Total: 33.3 %" ]} |
|---|
字段 | 类型 | 说明 |
|---|---|---|
tool | string | 工具名:pest / phpunit / phpstan / rector / paratest |
result | string | "passed" 或 "failed" |
tests | int | 总测试数 |
passed | int | 通过数 |
failed | int | 失败数(有失败时) |
duration_ms | int | 执行耗时(毫秒) |
failures | array | 失败详情(含 test、file、line、message、trace) |
errors | int | 错误数(PHPStan 专用) |
error_details | object | 错误详情(PHPStan 专用,按文件分组) |
raw | array | 额外插件输出(Coverage、Profile 等) |
变量 | 用途 |
|---|---|
PAO_FORCE=true | 强制开启 JSON 模式,无论是否检测到 Agent |
PAO_DISABLE=true | 强制关闭,恢复人类可读输出(仅供调试) |
PAO_DISABLE=true不得写入 CI 配置、Makefile 或任何脚本,仅用于开发者本地临时调试。
PAO_FORCE=true vendor/bin/pest tests/Feature/TaskControllerTest.php -- 输出{ "tool": "pest", "result": "passed", "tests": 2, "passed": 2, "assertions": 39, "duration_ms": 2523} |
|---|
人工在终端直接运行时不需要也不应该添加 PAO_FORCE:
# 人工运行:正常彩色输出,PAO 自动静默./vendor/bin/pest |
|---|
方案 | 配置成本 | 输出大小 | 失败定位精度 | Agent 友好度 |
|---|---|---|---|---|
原始 Pest/PHPUnit | 无 | ∝ 测试数量 | 中 | ⭐ |
--format=junit XML | 需配置 | 大 | 高 | ⭐⭐ |
自定义 Reporter | 高 | 可控 | 高 | ⭐⭐⭐ |
laravel/pao | 零 | 常数 | 精确到行 | ⭐⭐⭐⭐⭐ |
PAO 最关键的特性:输出大小是常数,100 个测试和 10000 个测试产生的 JSON 体积几乎相同,只有失败详情会增加内容。
1. PHP 版本要求:PHP 8.3+,因为 PAO 使用了 readonly 属性等现代语法。
2. 进程中断:PAO 在 shutdown_function 输出 JSON,若进程被强制 kill(非正常退出),输出可能不完整。
3. Paratest 并行:PAO 对 Paratest 有专门处理,worker 进程的输出会被正确归并。
4. 框架命名空间:包名 laravel/pao 中的 laravel 仅代表维护者,不要求安装 Laravel 框架。
5. CI 环境:CI 中通常不会检测到 AI Agent,如需 JSON 输出可设置 PAO_FORCE=true,但需确认下游流程能正确消费 JSON。
laravel/pao 是 PHP 生态在 AI 编程时代的一个务实解法。它不改变任何工具的行为,不侵入项目代码,只在 AI Agent 介入时悄悄切换输出格式——对人透明,对 AI 友好。
一行安装,永久生效,框架无关,零侵入。
composer require laravel/pao --dev |
|---|