This commit is contained in:
ray zhou
2026-06-29 14:51:55 +08:00
parent 225fb2bd28
commit 2dd9f17da9
319 changed files with 29461 additions and 9412 deletions

View File

@@ -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`

View File

@@ -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 调用 ServiceService 再原样调用 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 文件中。

View File

@@ -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 是否包含可推导的重复标量?

View 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