chore(memory): 协作约定 AGENTS.md

把用户明确表达过的偏好固化下来,避免每次重新摸索:
- **不要改一点就提交推送**,攒够一批或到里程碑再提交
- 新功能是「增加」不是「替换」,旧路径完整保留
- 不要重复展示同一份数据(库里有的字段让已有界面显示,查询去刷新它)
- 单项外部调用失败不整体失败,但要如实暴露
- 如实报告(含自己的错误与局限);结论要有验证,关键用例做反向验证

以及这个仓库踩过的坑:
- 别拿不同时刻的快照对比(曾把时间差异当成账号差异,得出错误规则)
- Pydantic 静默丢字段的三种变体(含手写 @model_serializer)→ 断言要看 model_dump()
- 用例可能假绿(缺 session.commit,MySQL REPEATABLE READ)
- 区间删除容易连带删行;docker compose run 会吞 stdin

另附仓库事实:分支/生产/镜像库/测试库/迁移编号/前端 tsc 严格项。
This commit is contained in:
yml2213
2026-10-04 20:03:25 +08:00
parent aea05952af
commit 93d972d3fb
+60
View File
@@ -0,0 +1,60 @@
# 协作约定(给 AI 助手 / 协作者)
> 这些是用户明确表达过的偏好。**每次在这个仓库里干活前先读一遍。**
## 提交与推送
- **不要改一点就提交、推送。**
小改动先攒着,**攒够一批**再提交;只有用户明确说「提交 / 推送」,
或者到了一个自然的里程碑(一个完整功能做完、一轮反馈全部改完)才 commit / push。
- 一次提交要**整合**相关改动,不要拆成一堆碎提交。
- 推送时 `main` 与 `dev` 一起同步(`dev` 是工作分支):
`git push gitea main` → `git checkout dev && git merge --ff-only main && git push gitea dev`。
## 功能改动
- **新功能是「增加」,不是「替换」。** 旧路径要完整保留(例:账号检测保留了
手动粘贴,新增「按账号选择」;旧的手动输入逻辑一行未动)。
- 改动要**务实、克制**:不做没人要的重构,不加用不上的抽象。
- **不要重复展示同一份数据。** 数据库里已有的字段(如 `accounts.points` /
`gold_balance` / `elite_opened`)就让已有界面显示,查询去**刷新**它们,
不要另开一份副本 —— 同一屏出现两份会让人分不清哪份是准的。
- **单项外部调用失败不要让整个流程失败**,但要**如实暴露**(错误写进 `errors`
并在 UI 展示),别让「没查到」被读成「没有」。
## 报表 / 汇报
- **如实报告,包括自己的错误、误判和局限。** 不确定就说不确定,别猜。
- **结论要有验证**:能实测就实测(本仓库有生产镜像库可用),
能反向验证(把 bug 注入回去看用例是否变红)就反向验证。
- 用中文回答。
## 一次踩过的坑(值得记住)
- **别拿不同时刻的快照做对比。** 曾经把相隔两个月的两条记录对比,
把「时间差异」当成了「账号差异」,得出错误规则并写进设计文档。
对比必须在**同一时刻**。
- **Pydantic 会静默丢字段 —— 本仓库已经踩过三次**,每次表现都不同:
1. 构造函数传了、模型上没声明 → `extra='ignore'` 丢掉;
2. 模型上声明了、但**手写的 `@model_serializer` 里没列** → 属性有值、JSON 里没有;
3. 字段名与 schema 声明的不一致(如 `elite_bind_status` vs `role_bind_status`)。
**应对**:断言要看 **`model_dump()`(序列化结果)**,只看属性会假绿;
改完接口先在 Python 里打一遍 `model_dump()` 确认字段真在里面。
- **别信"测试通过" —— 用例可能是假绿的(缺 `session.commit()` 时,
MySQL REPEATABLE READ 会让它看不到别的会话刚提交的行)。
关键用例要做反向验证。
- **删代码块时用"从 A 到 B"的区间删除很危险**,容易连带删掉中间的行
(曾把 `**bind_payload(acc),` 一起删掉)。改完要**读回来确认**。
- **`docker compose run` 默认读 stdin**:脚本用 `ssh 'bash -s' < 脚本` 喂进去时,
它会把脚本剩下的行吃掉。要用 `docker compose run -T --rm ... </dev/null`。
## 仓库事实
| | |
| --- | --- |
| 工作分支 | `dev`(本地开发);`main` = 已发布;远端是 `gitea` |
| 生产 | SSH 别名 `order+douyu_huya`(47.114.114.225),部署目录 `/root/live-hub-py` |
| 本地生产镜像 | `douyu_login_prod`(`scripts/refresh_local_prod_mirror.sh` 同步) |
| 测试库 | `douyu_login_test`(独立库,**不要**拿镜像库跑测试套件) |
| 迁移 | 编号按落地顺序取,**不预留**;已应用的迁移不能改名 |
| 前端 | `tsc -b` 开了 `noUnusedLocals`,死代码/未用导入会直接报 TS6133 |