ok
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
---
|
||||
description: Agent 完成前门禁:校验脚本 + Hooks 兜底
|
||||
description: Agent 完成前门禁:校验脚本 + Skill 检测报告 + Hooks 兜底
|
||||
alwaysApply: true
|
||||
---
|
||||
|
||||
@@ -8,15 +8,20 @@ alwaysApply: true
|
||||
## 禁止
|
||||
|
||||
- 未跑校验脚本前,不得写「已完成」「可以合并」「验收通过」等收尾表述。
|
||||
- 改动 PHP 后,未按 `slot-backend-completion-report` Skill 输出「检测结果」章节就收尾。
|
||||
|
||||
## 必须
|
||||
|
||||
1. 任务收尾前执行:`~/.cursor/hooks/verify-slot-backend.sh`
|
||||
2. 在最终回复粘贴完整输出(以 `=== verify-slot-backend ===` 开头)。
|
||||
3. 修改 PHP 后,最终回复含 `PHPDoc: checked`(见 `php-code` 规则 PHPDoc 章节)。
|
||||
4. 改动 `app/**/*.php` 须遵守 `php-code` 用例写法章节(BusinessException、按层写法)。
|
||||
5. 修改 `app/**/logic/**/*.php` 时,完成前对照 `php-clean-code` **§3 参数与日志**、**§3 编排上下文与聚合 DTO** 与 **§8 自查**(不仅依赖 verify 脚本)。
|
||||
6. 工作区在 `www/ray` 时,执行校验须:`SLOT_ROOT=/Users/ray/Documents/project/www/ray ~/.cursor/hooks/verify-slot-backend.sh`(避免 `PASS (no changed files)` 误判)。
|
||||
1. **收尾前读取并执行** Skill:`~/.cursor/skills/slot-backend-completion-report/SKILL.md`(或项目内 `.cursor/skills/slot-backend-completion-report/`)。
|
||||
2. **跑检测**(推荐一条命令):
|
||||
```bash
|
||||
SLOT_ROOT="${SLOT_ROOT:-<当前 Cursor 工作区根>}" \
|
||||
~/.cursor/skills/slot-backend-completion-report/scripts/report.sh
|
||||
```
|
||||
- `SLOT_ROOT` 为当前工作区根,**禁止写死** `www/ray` 或 `slot-xxx`;脚本内 `php -l` 的 docker `-w` 由 git 仓库路径动态映射(见 Skill)。
|
||||
3. 最终回复**必须包含** Skill 规定的「检测结果」章节(门禁输出、php -l、规范对照表、结论),并含 `PHPDoc: checked`。
|
||||
4. 改动 `app/**/*.php` 须遵守 `php-clean-code` 用例写法(BusinessException、按层写法)。
|
||||
5. 修改 `app/**/logic/**/*.php` 时,对照 `php-clean-code` **§3 常量规则**、**§3 参数与日志**、**§3 编排上下文与聚合 DTO** 与 **§8 自查**(不仅依赖 verify 脚本)。
|
||||
|
||||
## Hooks(用户级 `~/.cursor/hooks.json`)
|
||||
|
||||
|
||||
@@ -10,8 +10,8 @@ alwaysApply: true
|
||||
| **Controller** | 接收请求;补充 header / 路由参数;调用 Validate;构建 DTO;调用 Logic / Service;返回统一响应 |
|
||||
| **Validate** | 参数必填、类型、长度、格式、枚举、数组结构 |
|
||||
| **DTO** | 承载已校验参数;做轻量格式整理;**不**做参数合法性判断;**不**查数据库;**不**写业务规则 |
|
||||
| **Logic** | 负责业务用例、流程编排、事务控制;可以调用本 Logic 内部方法组织步骤;简单逻辑可直接调用 Model;复杂或跨场景复用能力才调用 Service |
|
||||
| **Service** | 只承载公共能力,例如 center / sdk / 公共配置 / 公共计算 / 跨业务复用逻辑;**不是**每张表都建一个 Service;**不是**把 Logic 方法简单搬过去 |
|
||||
| **Logic** | 负责业务用例、流程编排、事务控制;可以调用本 Logic 内部方法组织步骤;简单逻辑可直接调用 Model;复杂或跨场景复用能力才调用 Service;**禁止返回 `array`**,固定形状结果返回 **Entity** |
|
||||
| **Service** | 只承载公共能力,例如 center / sdk / 公共配置 / 公共计算 / 跨业务复用逻辑;**不是**每张表都建一个 Service;**不是**把 Logic 方法简单搬过去;**禁止返回 `array`**,结构化结果返回 **Entity** |
|
||||
| **Model** | 数据查询;数据写入;scope / 搜索器 / 关联;把查询条件沉淀成模型方法 |
|
||||
|
||||
## Logic 与 Service 边界
|
||||
@@ -21,6 +21,14 @@ alwaysApply: true
|
||||
- 不应创建只做中转的 Service 方法,例如 Logic 调用 Service,Service 再原样调用 Model 或另一个 Logic,且没有封装公共能力。
|
||||
- 如果确实需要中转层,必须在代码或 PR 说明中解释原因,例如兼容历史接口、统一事务边界、隔离第三方 SDK、收敛跨模块依赖等。
|
||||
|
||||
## Logic / Service 返回值
|
||||
|
||||
- **禁止** Logic / Service 方法返回 `array`(含 `@return array{...}`、`@return XxxEntity[]`)。
|
||||
- 固定形状业务数据用 `app/entity/{业务域}/XxxEntity`(优先 `extends BaseEntity`);多条记录用列表/汇总 Entity 包装,不在 Logic/Service 签名上返回数组。
|
||||
- 允许 `void`、标量、`?XxxEntity`、单个 Entity;禁止直接返回 Model。
|
||||
- Controller 将 Entity 转为统一 HTTP 响应(如 `activeData()`);Validate / 入参 DTO 规则不变。
|
||||
- `verify-slot-backend.sh` 对 diff 新增行自动检测上述规则;临时豁免见 `php-clean-code` §4 `@logic-service-array-exempt`。
|
||||
|
||||
## Agent 完成前 MUST
|
||||
|
||||
1. **重命名/删除类**:对本次 diff 中删除的 `*.php`,类名不得出现在**其它已改动**的 PHP 文件中。
|
||||
|
||||
@@ -69,10 +69,11 @@ alwaysApply: true
|
||||
- 方法参数一般不超过 3 个。
|
||||
- 参数超过 3 个时,优先使用 DTO、Value Object 或专门数据结构。
|
||||
- 核心业务入参不要直接使用含糊的 `array`。
|
||||
- 返回 `array` 时必须结构明确,并用 PHPDoc 描述结构。
|
||||
- **Logic / Service 禁止返回 `array`**(含 `@return array{...}`、`@return XxxEntity[]`);固定形状业务结果必须返回 **Entity**(见 §4「返回值规则」)。
|
||||
- Model 若返回 `array`,必须结构明确,并用 PHPDoc 描述结构。
|
||||
- 私有方法也必须有清晰业务语义,并写中文 PHPDoc(见 §5;纯 getter/setter 除外)。
|
||||
- 复杂条件必须封装成有语义的方法。
|
||||
- 魔法数字必须变成常量或枚举。
|
||||
- 魔法数字必须变成常量或枚举;**所有类常量必须写中文注释**(见下文「常量规则」)。
|
||||
- 业务规则判断优先使用 `ensureXxx()` 方法。
|
||||
- 不要把查询、判断、写入、返回组装全部堆在一个大方法里。
|
||||
|
||||
@@ -90,6 +91,35 @@ alwaysApply: true
|
||||
- 聚合上下文 DTO 应 **只组合** 子对象;派生值用 `uid()` / `providerCode()` 等 accessor 从子对象读取,或在用例方法内直接使用子 DTO 字段(二选一,不并存)。
|
||||
- 子步骤 private 方法若需多字段,优先传 **一个** 聚合 DTO,而不是再拆 3 个标量参数。
|
||||
|
||||
### 常量规则
|
||||
|
||||
- 魔法数字、魔法字符串必须提为 `const` 或枚举,禁止硬编码在业务逻辑中。
|
||||
- **所有类常量**(`public` / `protected` / `private` const)必须有一行 `/** 中文说明 */`,**无豁免**。
|
||||
- 注释须说明业务含义、取值语义或用途;禁止纯英文复述常量名(无信息增量 → 不合格)。
|
||||
- Model 中状态类常量(`STATUS_*` 等)还须与 `@property status` 描述一致,列出各枚举值含义。
|
||||
|
||||
反例(禁止):
|
||||
|
||||
```php
|
||||
class GameServerLogic extends BaseLogic
|
||||
{
|
||||
private const SOURCE_CODE_LENGTH = 6;
|
||||
}
|
||||
```
|
||||
|
||||
正例:
|
||||
|
||||
```php
|
||||
class GameServerLogic extends BaseLogic
|
||||
{
|
||||
/** 渠道编号长度(位) */
|
||||
private const SOURCE_CODE_LENGTH = 6;
|
||||
|
||||
/** Session 有效 */
|
||||
public const STATUS_ACTIVE = 1;
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 4. Logic / Service / Model 写法
|
||||
@@ -103,6 +133,7 @@ alwaysApply: true
|
||||
- 复杂查询条件应沉淀到 Model。
|
||||
- 涉及多表写入、钱包变动、订单状态变更、活动领取、返水领取、游戏下注 / 派奖时,事务边界必须放在 Logic。
|
||||
- 事务内禁止请求第三方接口、发送 MQ、发送短信、发送邮件、大量循环处理、复杂远程调用。
|
||||
- **Logic 禁止返回 `array`**;业务结果组装为 Entity 后返回,由 Controller 再转为 HTTP 响应(如 `activeData()`)。
|
||||
|
||||
### Service
|
||||
|
||||
@@ -111,6 +142,18 @@ alwaysApply: true
|
||||
- Service 禁止只做 Model 转发或 Logic 转发。
|
||||
- Service 禁止为每张表创建一个 Service。
|
||||
- 如果一个 Service 方法没有封装公共能力,不应创建。
|
||||
- **Service 禁止返回 `array`**;对外暴露的结构化结果同样使用 Entity。
|
||||
|
||||
### 返回值规则(Logic / Service)
|
||||
|
||||
- **禁止** Logic / Service 方法声明返回 `array`(含关联数组、索引数组、`array{...}` 形状数组)。
|
||||
- **必须** 使用 `app/entity/{业务域}/XxxEntity`(优先 `extends app\entity\BaseEntity`)承载固定形状业务数据;命名表达业务语义,如 `GrantSettleResultEntity`、`WalletStatisticsEntity`。
|
||||
- Entity 使用 **public 属性** + 中文属性注释;字段名与接口/库表约定一致(通常 camelCase);`new XxxEntity([...])` 由 `BaseEntity` 填充。
|
||||
- **多条记录**:禁止 `@return XxxEntity[]` 或裸 `array`;使用列表/汇总 Entity(如 `PlayerTaskListEntity`),在 Entity 内用 `/** @var XxxEntity[] */ public array $items` 等**有命名语义**的属性承载;Logic/Service 方法本身仍返回该 Entity 对象。
|
||||
- **允许** 返回:`void`、标量(`bool` / `int` / `string` / `float`)、`?XxxEntity`(可空实体)、单个 Entity。
|
||||
- **禁止** 直接返回 Model 对象;Model 查询结果须在 Logic 内映射为 Entity 后再返回。
|
||||
- Controller 负责把 Entity 转为统一 HTTP 响应;**禁止** 在 Controller 里拼装本应由 Logic 产出的业务结构数组。
|
||||
- `verify-slot-backend.sh` 对 git diff **新增行** 自动拦截 Logic/Service 的 `: array`、`@return array{...}`、`@return Xxx[]`;历史存量方法改 body 不触发。确需临时豁免的文件可在类 PHPDoc 首段标注 `@logic-service-array-exempt`(仅迁移期,须注明原因)。
|
||||
|
||||
### Model
|
||||
|
||||
@@ -120,16 +163,18 @@ alwaysApply: true
|
||||
- Model 方法命名必须表达查询或写入意图,例如 `findEnabledById()`、`existsClaimedRecord()`、`sumValidBetAmount()`、`createClaimRecord()`。
|
||||
- 避免 `getData()`、`getList()`、`handle()`、`process()`。
|
||||
|
||||
#### Model 类 PHPDoc(新建 / 大改必须)
|
||||
#### Model 类 PHPDoc(必须)
|
||||
|
||||
凡 **新建** 或 **大改** `app/model/**/*Model.php`(含 `app/**/model/` 下 Model),类上必须有完整 PHPDoc,**禁止** 只写类型、不写字段说明。
|
||||
凡 `app/model/**/*Model.php`(含 `app/**/model/` 下 Model),类上**必须**有完整 PHPDoc;**禁止**只有一行类说明、无 `@property`,或 `@property` 只有类型无中文说明。
|
||||
|
||||
1. **类注释**:`表名` + 一行业务说明(对齐 DDL `COMMENT` 或需求文档)。
|
||||
2. **`@property`**:每个持久化字段一行,格式 `@property type $field 中文说明`(对齐表字段 `COMMENT`)。
|
||||
2. **`@property`(必须)**:**每个持久化字段**一行,格式 `@property type $field 中文说明`(对齐表字段 `COMMENT`);缺字段、缺中文说明均不合格。
|
||||
3. **易混字段必须区分**:例如 `id`(自增主键)vs `session_id`(对外标识)vs `launch_request_id`(链路追踪)。
|
||||
4. **状态字段**:写清「见 `STATUS_*` 常量」或列出枚举含义(与常量注释一致)。
|
||||
5. **时间字段** `created_at` / `updated_at` 可简写为「创建时间」「更新时间」。
|
||||
6. **状态类常量**(`STATUS_*` 等):每个常量一行 `/** 中文说明 */`,与 `@property status` 描述一致。
|
||||
5. **时间字段** `created_at` / `updated_at` / `create_time` / `update_time` 可简写为「创建时间」「更新时间」。
|
||||
6. **类常量**:遵守上文「常量规则」,每个 `const` 一行 `/** 中文说明 */`。
|
||||
|
||||
**触达 Model 文件时**(新建、小改、补方法):若类 PHPDoc 缺 `@property` 或不完整,须在本次改动中补全,不得留空。
|
||||
|
||||
反例(禁止):
|
||||
|
||||
@@ -166,6 +211,8 @@ class GameLaunchSessionModel extends Model
|
||||
|
||||
**Logic / Service / Model 的 `public` / `protected` / `private` 方法必须写 PHPDoc**,首行用**中文**说明业务动作或结果(很多人看不懂英文方法名,英文命名不能替代 PHPDoc)。
|
||||
|
||||
**所有类常量**(`public` / `protected` / `private` const)必须有一行 `/** 中文说明 */`,见 §3「常量规则」,**无豁免**。
|
||||
|
||||
- `public`:一律必须(纯 getter/setter 除外,见下文)。
|
||||
- `protected` / `private`:Logic 与 Service 中凡承载业务步骤的方法必须写;Model 的 `private` 若仅为薄封装且无语义增量可省略,但 `find*` / `mark*` / 访问 DB/Redis 的 `private` 仍必须写。
|
||||
|
||||
@@ -212,16 +259,29 @@ public static function findActiveBySessionId(string $sessionId): ?self
|
||||
|
||||
除满足上文「默认规则」外,以下场景还须**额外**写明对应标签或结构(不在列表里也不能省略通用 PHPDoc):
|
||||
|
||||
- 返回 `array`:必须用 `@return array{...}` 写清结构。
|
||||
- Logic / Service 返回 Entity:`@return` 写具体 Entity 类名(如 `@return GrantSettleResultEntity`),**禁止** `@return array{...}`。
|
||||
- Model 返回 `array`:必须用 `@return array{...}` 写清结构(Logic / Service 不适用)。
|
||||
- 参数为复杂 `array`:必须用 `@param array{...} $name` 写清结构。
|
||||
- 可能抛出业务异常:必须写 `@throws`(中文说明触发条件)。
|
||||
- 涉及状态流转、钱包、订单、活动、游戏交易:首行中文说明中须点明状态/资金影响。
|
||||
|
||||
返回 array 结构示例:
|
||||
Logic 返回 Entity 示例:
|
||||
|
||||
```php
|
||||
/**
|
||||
* 查询用户钱包汇总。
|
||||
* 执行直接发奖入账并返回账单结果。
|
||||
*
|
||||
* @return GrantSettleResultEntity
|
||||
* @throws BusinessException 钱包不可用或入账失败时
|
||||
*/
|
||||
public function grantSettle(GrantSettleDTO $grantSettleDto): GrantSettleResultEntity
|
||||
```
|
||||
|
||||
Model 返回 array 结构示例(仅 Model 层):
|
||||
|
||||
```php
|
||||
/**
|
||||
* 查询用户钱包汇总原始行。
|
||||
*
|
||||
* @return array{
|
||||
* user_id: int,
|
||||
@@ -263,9 +323,10 @@ public static function findActiveBySessionId(string $sessionId): ?self
|
||||
- 关键业务必须打日志,例如钱包变动、游戏下注、游戏派奖、支付回调、活动领取、返水领取、第三方接口异常、风控命中、重要状态变更。
|
||||
- 日志必须包含关键上下文,例如 `user_id`、`order_no`、`provider_code`、`provider_tx_id`、`round_id`、`amount`、`status`、`error`。
|
||||
- 日志禁止记录密码、token、secret、私钥、支付密钥、银行卡完整号码、用户隐私数据、第三方签名密钥。
|
||||
- 返回结构必须明确。
|
||||
- 返回结构必须明确;Logic / Service 以 Entity 表达,不以裸 `array` 表达。
|
||||
- 不直接返回 Model 对象。
|
||||
- 不返回临时调试字段、SQL、异常堆栈、内部配置、secret、token、sign。
|
||||
- Controller 将 Entity 转为 HTTP 响应;Logic / Service 不返回 HTTP Response。
|
||||
|
||||
---
|
||||
|
||||
@@ -284,22 +345,26 @@ public static function findActiveBySessionId(string $sessionId): ?self
|
||||
- 命名是否清晰?
|
||||
- 方法是否过长?
|
||||
- 嵌套是否过深?
|
||||
- 是否有魔法数字或魔法字符串?
|
||||
- 是否有魔法数字或魔法字符串?是否已提为常量?
|
||||
- **所有类常量是否均有中文注释**(`/** 中文说明 */`)?
|
||||
- Logic 是否表达清晰业务流程?
|
||||
- Service 是否确实是公共能力?
|
||||
- Model 是否只做数据访问?
|
||||
- 新建/大改 Model 是否有类注释 + 带中文说明的 `@property`(易混字段、status 是否写清)?
|
||||
- `STATUS_*` 等状态常量是否有中文注释?
|
||||
- **Model 类 PHPDoc 是否含完整 `@property`(每个持久化字段 + 中文说明)?触达 Model 时缺则须补全。**
|
||||
- 所有 `const`(含 Logic / Service / Model 的 `private const`)是否均有中文注释?
|
||||
- 多表写入是否有事务?
|
||||
- 是否需要幂等?
|
||||
- 是否吞异常?
|
||||
- 日志是否有关键上下文?
|
||||
- 是否泄露敏感信息?
|
||||
- 返回数据是否明确?
|
||||
- Logic / Service 是否**未返回 `array`**,且固定形状结果已用 Entity?
|
||||
- 列表/汇总场景是否用列表 Entity 包装,而非 `@return XxxEntity[]` 或裸数组?
|
||||
- 是否直接返回 Model?
|
||||
- Logic / Service / Model 的 `public` / `protected` / `private` 方法是否均有**中文** PHPDoc 首行(纯 getter/setter 除外)?
|
||||
- 是否存在只有 `@param`/`@return` 类型、无中文业务说明的 PHPDoc?
|
||||
- 返回 array / 复杂数组参数 / 抛异常的方法,是否在通用 PHPDoc 之上补全了 `array{...}` 结构与 `@throws`?
|
||||
- Model 返回 array / 复杂数组参数 / 抛异常的方法,是否在通用 PHPDoc 之上补全了 `array{...}` 结构与 `@throws`?
|
||||
- Logic / Service 返回 Entity 的方法,`@return` 是否为具体 Entity 类名?
|
||||
- 是否存在「仅用于日志」的多余参数?
|
||||
- 是否存在「局部变量 + 聚合 DTO」双份承载同一业务字段?
|
||||
- 聚合 DTO 是否包含可推导的重复标量?
|
||||
|
||||
27
rules/slot-sdk-webman-restart.mdc
Normal file
27
rules/slot-sdk-webman-restart.mdc
Normal file
@@ -0,0 +1,27 @@
|
||||
---
|
||||
description: 修改 slot-sdk 后自动重启依赖它的 Webman 服务(worker 不会热加载 SDK)
|
||||
globs: "**/slot-sdk/**"
|
||||
alwaysApply: false
|
||||
---
|
||||
|
||||
# slot-sdk 变更后重启 Webman
|
||||
|
||||
`slot/sdk` 通过 composer path 仓库 symlink 到 `ray/slot-sdk`,目录在业务项目**之外**。Webman 文件监控只监听业务仓库,**不会**因 SDK 变更重载 worker;不重启会出现 `Call to undefined method ...NotificationService::...` 等旧类缓存问题。
|
||||
|
||||
## Agent 必须做
|
||||
|
||||
本次对话若改动了 `ray/slot-sdk`(含 `src/`、`composer.json` 等),在相关任务收尾前**主动执行**对应服务的 `php webman restart`(Docker 内,勿用宿主机 `php`)。
|
||||
|
||||
## 当前已知依赖(path 仓库)
|
||||
|
||||
| 消费方 | 容器内工作目录 | 重启命令 |
|
||||
| --- | --- | --- |
|
||||
| saas6.x 管理中台 | `/app/www/tenant/saas6.x/server` | `docker exec -w /app/www/tenant/saas6.x/server php82 php webman restart` |
|
||||
|
||||
新增其它项目引用 `../../../ray/slot-sdk` 时,在本表补上 `-w` 路径与重启命令。
|
||||
|
||||
## 执行注意
|
||||
|
||||
- 在**同一轮**改完 SDK 并完成验证后再重启,避免半成品代码被加载。
|
||||
- `webman restart` 可能常驻前台;用足够长的 `block_until_ms`,或确认进程已 `Start success` 后再继续。
|
||||
- 收尾回复中简短说明已重启(或说明跳过原因:本次未改 SDK)。
|
||||
Reference in New Issue
Block a user