ok
This commit is contained in:
101
skills/slot-backend-completion-report/SKILL.md
Normal file
101
skills/slot-backend-completion-report/SKILL.md
Normal file
@@ -0,0 +1,101 @@
|
||||
---
|
||||
name: slot-backend-completion-report
|
||||
description: >-
|
||||
Slot PHP 后端任务收尾自检:跑 verify 门禁、docker php -l、对照 php-clean-code
|
||||
与 backend-layering 输出结构化检测报告。修改 app/**/*.php 后收尾前必读;用户说
|
||||
「按规范检测」「检测代码」时也触发。
|
||||
---
|
||||
|
||||
# Slot 后端完成前检测报告
|
||||
|
||||
用户级 Skill:**禁止写死** `slot-xxx`、`/app/www/ray/...` 等服务路径;一律从**当前工作区 + git 仓库根 + Docker 挂载**推导。
|
||||
|
||||
## 何时执行
|
||||
|
||||
- 本次对话改动了任意 `app/**/*.php`
|
||||
- 用户要求「按规范检测 / 检测代码 / 出检测报告」
|
||||
- 准备写「已完成 / 可以合并 / 验收通过」之前
|
||||
|
||||
## 步骤(按顺序)
|
||||
|
||||
### 1. 跑统一脚本(推荐)
|
||||
|
||||
```bash
|
||||
SLOT_ROOT="${SLOT_ROOT:-<当前 Cursor 工作区根目录>}" \
|
||||
~/.cursor/skills/slot-backend-completion-report/scripts/report.sh
|
||||
```
|
||||
|
||||
- `SLOT_ROOT` 默认为当前工作区根(可能在 `www/ray`、`www/slot` 等不同 monorepo 下)
|
||||
- 脚本会:
|
||||
1. 调用 `~/.cursor/hooks/verify-slot-backend.sh`
|
||||
2. 对 git diff 中每个改动 `.php` 执行 `docker php -l`
|
||||
|
||||
### 2. 路径映射规则(脚本已实现,Agent 手工跑命令时同样遵守)
|
||||
|
||||
对每个改动 PHP 文件 `$f`:
|
||||
|
||||
1. `repo=$(git -C "$(dirname "$f")" rev-parse --show-toplevel)`
|
||||
2. 宿主机挂载根 → 容器根(见 `dev-environment`):
|
||||
- `SLOT_DOCKER_HOST_ROOT` 默认 `/Users/ray/Documents/project`
|
||||
- `SLOT_DOCKER_CONTAINER_ROOT` 默认 `/app`
|
||||
3. `container_wd="${SLOT_DOCKER_CONTAINER_ROOT}${repo#$SLOT_DOCKER_HOST_ROOT}"`
|
||||
4. `docker exec -w "$container_wd" php82 php -l "${f#$repo/}"`
|
||||
|
||||
示例(由路径**推导**,非手写):
|
||||
|
||||
| git 仓库根(宿主机) | 容器 `-w` |
|
||||
|----------------------|-----------|
|
||||
| `.../project/www/ray/slot-admin` | `/app/www/ray/slot-admin` |
|
||||
| `.../project/www/slot/slot_wallet` | `/app/www/slot/slot_wallet` |
|
||||
|
||||
仓库不在 `SLOT_DOCKER_HOST_ROOT` 下 → 跳过 docker 语法检查并在报告中说明。
|
||||
|
||||
### 3. 规范对照(Agent 读 diff 后填表,脚本无法替代)
|
||||
|
||||
| 检查项 | 依据 | 做法 |
|
||||
|--------|------|------|
|
||||
| PHPDoc 中文首行 | `php-clean-code` §5 | 改动的方法均有中文说明 |
|
||||
| 类常量注释 | `php-clean-code` §3 常量规则 | 所有 `const` 均有 `/** 中文说明 */` |
|
||||
| Logic 参数与日志 | §3 参数与日志 | 无仅用于日志的多余参数 |
|
||||
| 聚合 DTO | §3 编排上下文 | 无重复标量 / 双份拷贝 |
|
||||
| Logic/Service 返回值 | `php-clean-code` §4 + `verify-slot-backend.sh` | 未返回 `array`;固定形状用 Entity |
|
||||
| 分层 | `backend-layering` | Controller 薄、Logic 编排、无 Logic 型 Service |
|
||||
| 业务异常 | `agent-completion-gate` | 不用 RuntimeException 表业务失败 |
|
||||
|
||||
改 `app/**/logic/**/*.php` 时,§3 参数与日志、聚合 DTO、§8 自查**必须**逐项过一遍。
|
||||
|
||||
## 最终回复必须包含的章节
|
||||
|
||||
```markdown
|
||||
## 检测结果
|
||||
|
||||
### 门禁脚本
|
||||
(粘贴 report.sh 或 verify-slot-backend.sh 完整输出,以 `=== verify-slot-backend ===` 或 `=== slot-backend-completion-report ===` 开头)
|
||||
|
||||
### PHP 语法(docker php -l)
|
||||
(粘贴 php -l 输出;无改动 PHP 写「无改动 PHP」)
|
||||
|
||||
### 规范对照
|
||||
| 项 | 结果 | 说明 |
|
||||
|----|------|------|
|
||||
| PHPDoc / 常量注释 | 通过/不通过 | … |
|
||||
| Logic/Service 返回 Entity | 通过/不通过/不适用 | … |
|
||||
| 分层 | 通过/不通过/不适用 | … |
|
||||
| Logic §3 / §8(若改 Logic) | 通过/不适用 | … |
|
||||
|
||||
### 结论
|
||||
通过 / 不通过(不通过须先修复再收尾)
|
||||
|
||||
PHPDoc: checked
|
||||
```
|
||||
|
||||
## 禁止
|
||||
|
||||
- 未跑脚本、未对照规范就写「已完成」
|
||||
- 只贴 `PASS` 一行、无规范对照表
|
||||
- 在宿主机直接跑 `php` / `composer`(须 docker,见 `dev-environment`)
|
||||
- 写死 `/app/www/ray/slot-xxx` 或假设固定 monorepo 目录
|
||||
|
||||
## 与 Hook 的关系
|
||||
|
||||
`~/.cursor/hooks.json` 的 `stop` 会自动跑 `verify-slot-backend.sh`;本 Skill 在此基础上补 **php -l** 与 **结构化 Markdown 报告**,二者互补。
|
||||
86
skills/slot-backend-completion-report/scripts/report.sh
Executable file
86
skills/slot-backend-completion-report/scripts/report.sh
Executable file
@@ -0,0 +1,86 @@
|
||||
#!/bin/bash
|
||||
# 跑 verify 门禁 + 对 git diff 中改动的 PHP 做 docker php -l。
|
||||
# 路径由「当前工作区 + git 仓库根 + Docker 挂载」动态推导,不写死 slot-xxx。
|
||||
set -euo pipefail
|
||||
|
||||
SLOT_ROOT="${SLOT_ROOT:-${WORKSPACE_ROOT:-$(pwd)}}"
|
||||
SLOT_DOCKER_HOST_ROOT="${SLOT_DOCKER_HOST_ROOT:-/Users/ray/Documents/project}"
|
||||
SLOT_DOCKER_CONTAINER_ROOT="${SLOT_DOCKER_CONTAINER_ROOT:-/app}"
|
||||
PHP_CONTAINER="${PHP_CONTAINER:-php82}"
|
||||
VERIFY_SCRIPT="${VERIFY_SCRIPT:-$HOME/.cursor/hooks/verify-slot-backend.sh}"
|
||||
|
||||
host_repo_to_container_wd() {
|
||||
local repo="$1"
|
||||
if [[ "$repo" != "$SLOT_DOCKER_HOST_ROOT"* ]]; then
|
||||
echo ""
|
||||
return 1
|
||||
fi
|
||||
echo "${SLOT_DOCKER_CONTAINER_ROOT}${repo#$SLOT_DOCKER_HOST_ROOT}"
|
||||
}
|
||||
|
||||
collect_changed_php() {
|
||||
local root="$1"
|
||||
local d rel abs
|
||||
for d in "$root"/* "$root"/backend "$root"/backend/*; do
|
||||
[ -d "${d}/.git" ] || continue
|
||||
git -C "$d" diff --quiet 2>/dev/null && git -C "$d" diff --cached --quiet 2>/dev/null && continue
|
||||
while IFS= read -r rel; do
|
||||
[ -z "$rel" ] && continue
|
||||
[[ "$rel" != *.php ]] && continue
|
||||
[[ "$rel" == vendor/* ]] && continue
|
||||
abs="$d/$rel"
|
||||
[ -f "$abs" ] || continue
|
||||
printf '%s\n' "$abs"
|
||||
done < <(
|
||||
{ git -C "$d" diff --name-only 2>/dev/null
|
||||
git -C "$d" diff --cached --name-only 2>/dev/null
|
||||
} | sort -u
|
||||
)
|
||||
done | sort -u
|
||||
}
|
||||
|
||||
echo "=== slot-backend-completion-report ==="
|
||||
echo "SLOT_ROOT=$SLOT_ROOT"
|
||||
echo "SLOT_DOCKER_HOST_ROOT=$SLOT_DOCKER_HOST_ROOT"
|
||||
echo ""
|
||||
|
||||
echo "--- verify-slot-backend ---"
|
||||
SLOT_ROOT="$SLOT_ROOT" bash "$VERIFY_SCRIPT" || verify_exit=$?
|
||||
verify_exit=${verify_exit:-0}
|
||||
echo ""
|
||||
|
||||
echo "--- php -l (docker) ---"
|
||||
syntax_fail=0
|
||||
changed_php=()
|
||||
while IFS= read -r abs; do
|
||||
[ -z "$abs" ] && continue
|
||||
changed_php+=("$abs")
|
||||
done < <(collect_changed_php "$SLOT_ROOT" || true)
|
||||
|
||||
if [ ${#changed_php[@]} -eq 0 ]; then
|
||||
echo "(no changed php files)"
|
||||
else
|
||||
for abs in "${changed_php[@]}"; do
|
||||
repo=$(git -C "$(dirname "$abs")" rev-parse --show-toplevel 2>/dev/null) || {
|
||||
echo "SKIP (no git repo): $abs"
|
||||
continue
|
||||
}
|
||||
rel="${abs#"$repo"/}"
|
||||
container_wd=$(host_repo_to_container_wd "$repo") || {
|
||||
echo "SKIP (outside docker mount): $abs"
|
||||
continue
|
||||
}
|
||||
if ! docker exec -w "$container_wd" "$PHP_CONTAINER" php -l "$rel"; then
|
||||
syntax_fail=1
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "=== summary ==="
|
||||
if [ "$verify_exit" -ne 0 ] || [ "$syntax_fail" -ne 0 ]; then
|
||||
echo "FAIL (verify=$verify_exit syntax=$syntax_fail)"
|
||||
exit 1
|
||||
fi
|
||||
echo "PASS (verify + php -l)"
|
||||
exit 0
|
||||
Reference in New Issue
Block a user