--- name: Slot 硬规则落地 overview: 在用户级 `~/.cursor` 强化分层/PHPDoc 规则为可执行 checklist,并新增 Cursor Hooks:拦截宿主机 php/composer、在 Agent 结束前自动跑仓库校验脚本,未通过则注入 follow-up 要求继续修复。 todos: - id: hooks-scripts content: 新建 ~/.cursor/hooks.json、block-host-php.sh、verify-slot-backend.sh 并 chmod +x status: completed - id: rules-mdc content: 扩展 backend-layering.mdc;php-doc alwaysApply;新增 agent-completion-gate.mdc status: completed - id: plan-dod content: 每日返水 plan 追加 Definition of Done(与脚本检查项一致) status: completed - id: verify-hooks content: 手动验证:宿主机 php 拦截、docker php 放行、verify 脚本 PASS/FAIL status: in_progress isProject: false --- # Slot 后端硬规则落地 ## 目标 把当前「软约束」升级为三层: | 层级 | 手段 | 效果 | |------|------|------| | 上下文 | 规则 `alwaysApply` + 完成前 MUST | 每条对话强制可见 | | 行为 | Agent 必须跑校验脚本并贴输出 | 可审计、可复查 | | 机器 | Cursor Hooks `failClosed` | 违反则阻断或自动续跑修复 | 不依赖各 slot 仓库已有 CI(目前无 `.github/workflows`、无 pre-commit),**先落在用户级 `~/.cursor`**,对你当前多根工作区(`slot_console`、`backend/slot_admin` 等)全部生效。 ## 1. 强化 Cursor Rules(`~/.cursor/rules/`) ### 1.1 扩展 [backend-layering.mdc](file:///Users/ray/.cursor/rules/backend-layering.mdc) 在文末新增 **「Agent 完成前 MUST」**(短、可验证): - **重命名/删除类**:对本次 diff 中删除的 `*.php`,提取类名,在 `~/Documents/project/www/slot` 下 `rg` 引用数为 **0**。 - **新建/大改 `app/api/controller/*`**:必须 `extends \slotLib\basic\BaseController`,构造注入对应 `*Logic` + `*Validator`;参照 [FreeCreditsController.php](file:///Users/ray/Documents/project/www/slot/slot_console/app/api/controller/FreeCreditsController.php)。 - **禁止 Logic 型 Service**:不得新建以单业务用例编排为主、仅转发 Model/Logic 的 `app/service/*Service`(`DailyRebateCalcService` 这类**公共计算**除外)。 - **声称完成前**:必须执行 `~/.cursor/hooks/verify-slot-backend.sh`,在最终回复粘贴脚本输出(`PASS` 或 `FAIL` 明细)。 ### 1.2 调整 [php-doc.mdc](file:///Users/ray/.cursor/rules/php-doc.mdc) - `alwaysApply: false` → **`alwaysApply: true`** - 在「Agent 执行要求」增加:**最终回复必须含一行 `PHPDoc: checked` 或列出例外文件** 与 layering 规则叠加后,PHPDoc 不再因 glob 未命中而漏掉。 ### 1.3 新增 [agent-completion-gate.mdc](file:///Users/ray/.cursor/rules/agent-completion-gate.mdc) `alwaysApply: true`,仅 15~20 行,避免与 layering 重复: - 引用校验脚本路径与 Hooks 行为 - 禁止在未跑脚本前写「已完成 / 可以合并」 - 多仓库任务:脚本会扫描 `slot_*` 与 `backend` 下有 git 的目录 ## 2. Cursor Hooks(用户级,真正「硬」) 新建: - [~/.cursor/hooks.json](file:///Users/ray/.cursor/hooks.json) - [~/.cursor/hooks/block-host-php.sh](file:///Users/ray/.cursor/hooks/block-host-php.sh) - [~/.cursor/hooks/verify-slot-backend.sh](file:///Users/ray/.cursor/hooks/verify-slot-backend.sh) ```mermaid flowchart TD shell[Agent_Shell_command] blockHook[block-host-php.sh] edit[PHP_file_edits] stop[Agent_stop] verify[verify-slot-backend.sh] shell --> blockHook blockHook -->|deny_naked_php_composer| block[permission_deny] blockHook -->|docker_exec| allow[permission_allow] stop --> verify verify -->|FAIL| followup[followup_message_continue_fix] verify -->|PASS| done[session_ends] ``` ### 2.1 `beforeShellExecution` — 落实 [dev-environment.mdc](file:///Users/ray/.cursor/rules/dev-environment.mdc) **`block-host-php.sh`**(`failClosed: true`): - 若命令以 `php` / `composer` 开头且**不包含** `docker exec` → `permission: deny` - 允许:`docker exec ... php`、`docker exec ... composer` - 其它命令 → `allow` 这样宿主机误跑 PHP 会被 Hook **直接拦住**,不依赖模型记忆。 ### 2.2 `stop` — 分层与调用方收尾 **`verify-slot-backend.sh`**(`failClosed: false`,失败时返回 `followup_message` 让 Agent 继续改): 扫描根目录:`/Users/ray/Documents/project/www/slot` 下各子仓库(存在 `.git` 的 `slot_*`、`backend`): | 检查 | 逻辑 | |------|------| | 删除类无残留引用 | `git diff --diff-filter=D --name-only` 的 PHP → 解析 `class X` → `rg '\bX\b'` 全 slot 根,非 0 则 FAIL | | API Controller 结构 | `git diff --name-only` 命中 `app/api/controller/*.php` → 文件须含 `extends \slotLib\basic\BaseController`(无则 FAIL,除非文件头有 `@layering-exempt`) | | 禁止符号回归 | 内置 banlist(首项 `DailyRebateService`),`rg` 命中即 FAIL | | 可选轻量 PHPDoc | 对 diff 中新增的 `public function`,上一行非 `/**` 则 WARN(不阻断,避免历史债) | 输出格式固定: ``` === verify-slot-backend === PASS ``` 或 `FAIL` + 逐条原因;`stop` hook 解析到 `FAIL` 时返回 `followup_message`:「校验未通过,按明细修复后重跑脚本」。 脚本依赖:`bash`、`git`、`rg`(你本机已有);不依赖 `jq`(用 grep/sed 解析 stdin,降低 hook 环境差异)。 ### 2.3 `hooks.json` 草案 ```json { "version": 1, "hooks": { "beforeShellExecution": [ { "command": "./hooks/block-host-php.sh", "matcher": "^\\s*(php|composer)\\b", "failClosed": true } ], "stop": [ { "command": "./hooks/verify-slot-backend.sh", "failClosed": false } ] } } ``` 路径相对 **`~/.cursor/`**(用户 hook 约定)。创建后 `chmod +x` 两个脚本。 **验证步骤**(实施后手动测一次): 1. Agent 尝试 `php -v` → 应被拦截 2. `docker exec ... php -v` → 应放行 3. 故意留 `DailyRebateService` 引用 → `stop` 应触发 follow-up ## 3. 每日返水 Plan 补 DoD(可选,与硬规则对齐) 在 [每日返水活动化改造_dd1575a1.plan.md](file:///Users/ray/.cursor/plans/每日返水活动化改造_dd1575a1.plan.md) 末尾加 **Definition of Done** 小节(与脚本检查项一致),便于人工对照: - `rg DailyRebateService` → 0 - `DailyRebateController` 对齐 `FreeCreditsController` - 删除 orphan `dailyRebateTierConfig/*` - `verify-slot-backend.sh` → PASS (仅更新 plan 文档,不执行业务代码。) ## 4. 不纳入首期的项(避免过度工程) - 各仓库 CI / pre-commit:可后续把 `verify-slot-backend.sh` 拷到 `scripts/` 进 pipeline - `DailyRebateTierValidateService` 迁到 Validate 层:属代码重构,单独 PR - `afterFileEdit` 每次保存都跑校验:太吵,先用 `stop` + 规则要求手动跑脚本 ## 5. 实施顺序 1. 写两个 hook 脚本 + `hooks.json`,本地 chmod + 试跑脚本 2. 改/增三个 `.mdc` 规则文件 3. 更新每日返水 plan 的 DoD(若你同意) 4. 重启 Cursor 或确认 Hooks 面板已加载 ## 风险与说明 - **Hooks 是 Cursor 产品能力**:需 Cursor 版本支持 `hooks.json`;若 `stop` 的 stdin 字段与文档不一致,首版脚本以「扫描 git diff」为主,不依赖复杂 JSON 字段。 - **硬 ≠ 100%**:模型仍可能不写 follow-up 前的脚本输出;`stop` hook 是兜底。二者叠加后明显严于仅 Rules。 - **多根工作区**:脚本按 `~/Documents/project/www/slot/*/git` 遍历,不依赖当前打开哪个 folder。