Files
cmhub/progress.md
T

176 lines
17 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 执行进度记录
> 本文件是只追加的历史流水,用来记录任务执行过程、验证命令、阻塞点和关键决策。
> 当前目录、当前命令、下一个可领取任务等可覆盖快照,写入 [`docs/current-state.md`](docs/current-state.md)。
## 职责边界
- `docs/06-tasks.md`:任务看板,维护任务状态、依赖和验收要点。
- `progress.md`:历史流水,只追加记录每轮执行发生了什么。
- `docs/current-state.md`:当前快照,可覆盖更新仓库现实、可运行命令和下一步。
不要在本文重复维护当前目录结构、当前运行命令或下一个任务;这些信息以 `docs/current-state.md` 为准。
## 记录格式
每完成或中断一轮任务,在文件末尾追加一条记录:
```markdown
## 【YYYY-MM-DD】T-【编号】 【任务名】
- 状态:【DONE / BLOCKED / PARTIAL】
- 变更:【修改了哪些文件或模块】
- 验证:【运行的真实命令和结果】
- 阻塞:【如有,写明原因和需要谁决策】
- 决策:【如有,记录本轮确定的关键取舍】
- 下一步:【建议下一个任务 ID 或待确认事项】
```
## 执行记录
## 2026-06-29 文档初始化(非任务)
- 状态:DONE
- 变更:基于 `D:\github\harness_coding_docs` 模板,结合需求讨论生成 `cmhub` 全套 harness 文档(AGENTS/CLAUDE、docs/00–06、api、routes、current-state、README、progress、init 脚本);通用流程文档(adoption/clean-state/method-map/evaluator/quality)从模板复制。
- 验证:仅文档,无代码可跑。
- 决策:技术栈 Django+DRF+django-admin;预付费点数模型(充值按汇率转点存本地,调用扣本地点数,不实时查支付系统);生成接口同步返回;充值由支付系统服务端回调入账(验签+幂等)。
- 下一步:领取 T-001 初始化 Django + DRF 骨架。支付系统接口文档待提供(T-304 前需要)。
## 2026-06-29 设计优化:可插拔供应商(别名 + 适配器)(非任务)
- 状态:DONE
- 变更:把「两个接口 + 后台配模型」的设计从简化版抬到可治理版,更新到多个文档:
- `04-architecture.md`:AI 调用层改为 Provider 适配器架构;新增 ModelAlias 表与 AiModel 的 capabilities/加密 key;PricingRule 改为按别名定价;CallRecord 增 alias + model_used;计费时序加入别名解析与能力校验;难点表补充抽象泄漏/供应商耦合/配置热生效/审计;项目结构加 `apps/ai/providers/`。
- `api.md`:对外 `model` 字段明确为能力别名;新增 `parameters` 透传;响应加 `model_used`;图片默认返回 URL;AI 模块合约改为别名解析 + Provider 适配器接口。
- `03-tech-stack.md` / `02-requirements.md` / `05-coding-rules.md` / `routes.md` / `06-tasks.md`:同步别名机制、密钥加密、配置审计、对象存储等决策与任务。
- 验证:仅文档;自检文档间链接与任务依赖一致(T-302 依赖更新为 T-104)。
- 决策:① 对外绑能力别名而非具体模型 SKU;② `api_type` 升级为显式 Provider 适配器层 + capabilities 声明 + parameters 透传;③ 供应商密钥加密存储 + 配置热生效 + 后台变更审计。按账号授权别名、按比例分流/故障转移列入 Backlog(接口预留,MVP 不实现)。
- 下一步:领取 T-001 初始化 Django + DRF 骨架(Phase 1 任务已重排为 T-101 适配器层 / T-102 别名解析 / T-103 审计 / T-104 跑通)。
## 2026-07-01 设计决策:桌面端全同步接入 + V2 异步预研(非任务)
- 状态:DONE
- 变更:把「桌面端不改、全同步接入 cmhub」的可用性结论与前提写入两个每轮必读文档:
- `03-tech-stack.md` 第二节「同步生成而非任务队列」决策下补:桌面端可不改交互骨架、只换 service 层 URL/密钥即可接入;同步可用的三前提;何时转 V2 异步的触发信号。
- `04-architecture.md` 第五节新增 `5.1 同步方案可用性结论`:超时链路层层放大对齐(点名 `timeout_seconds:0`、Gunicorn 30s、Nginx 60s 三个默认值雷,建议统一 300s)、worker 数按峰值总并发预留、适用边界与 V2 触发条件。
- 验证:仅文档;`ai_models.json` 现存 `timeout_seconds: 0`,迁入服务端时须改有限值(关联约束已写入 04 第五节)。
- 决策:① MVP 桌面端不改、`桌面端 → cmhub → 中转站` 全同步,多一跳不影响可用性,点数一致性更简单(一次请求闭环:预扣→同步调→成功/失败退点);② 同步可用的硬前提是「超时链路 + worker 容量」配对,否则「小量正常、上量假死」;③ 适用边界为单接入方小并发批量,V2 异步(队列)延后,但适配器接口与 `call_record` 三态需为异步预留口子。
- 安全提醒:`ai_models.json` 内三把 `sk-` 为明文真实密钥,视为已泄露,迁入时须加密存储(Fernet/KMS)并轮换;密钥不进桌面端。
- 下一步:不改变任务看板顺序,仍从 T-001 起步;V2 异步化触发条件见 03/04,暂不排期。
## 2026-07-01 设计决策:版本锁定 + 数据库选型(MySQL 8.4 独立实例)(非任务)
- 状态:DONE
- 变更:结合实际部署环境(一台 VPS,实测 15G 内存 / available 7.4G / 无 swap,已装 MySQL 5.7 供其他服务用),定稿版本与数据库选型,更新 `03-tech-stack.md`(技术栈表语言/框架/数据库三行 + 决策记录三条)、`04-architecture.md`(数据库条目 + 第五节并发扣点难点补 CHECK 版本注意)、`README.md` 技术栈行。
- 验证:仅文档。
- 决策:
- ① 框架/语言锁定 **Django 5.2 LTS + Python 3.12**(`requires-python ">=3.12,<3.14"`);禁用已 EOL 的 Django 4.0/4.1;理由是安全/维护窗口,非性能(性能瓶颈在等上游+worker,见 5.1)。
- ② 数据库定 **MySQL 8.4 LTS,cmhub 专用独立实例**。放弃复用 VPS 已有的 MySQL 5.7:5.7 跑不了 Django 5.2(需 ≥8.0.11)、已 EOL、不支持 CHECK 约束;曾评估「坚持 5.7」会连锁把 Django 拖回 4.0(EOL)+Python≤3.10+cmbot 兼容风险,被否。内存宽裕(7.4G),单开独立实例与已有 5.7 隔离、互不影响。
- ③ 硬性约束:InnoDB + utf8mb4;CHECK 需 MySQL ≥8.0.16 才生效,扣点主防线是 `select_for_update` / `UPDATE ... WHERE balance>=N`,不能只靠 CHECK;MySQL 默认隔离级别 REPEATABLE READ,计费按此语义验证;开发亦用 MySQL,不用 SQLite(会忽略 FOR UPDATE,测不出并发扣点)。
- 待办提醒:T-001 骨架落地时须选 MySQL 驱动(`mysqlclient` 或 `PyMySQL`)、`DATABASES` 配 `charset=utf8mb4`、连接指向独立实例端口;机器建议补 2–4G swap;`03` 部署维度仍为「待定」,部署基线待后续定稿。
- 下一步:不改变任务看板顺序,仍从 T-001 起步(Django+DRF 骨架,按上述版本/数据库落地)。
## 2026-07-01 定位扩展:新增自助用户端(B2B → B2B+B2C)(非任务)
- 状态:DONE
- 变更:按用户新增需求(终端用户自助注册/扫码充值/API Key 管理/查记录),把项目从纯 B2B API 网关扩展为「自助用户端 + 计费 API + 运营后台」三合一,系统性更新文档:
- 定位/需求:`01-vision`、`00-ai-start-here`、`02-requirements`、`project-brief`、`project-onepager`(用户角色加注册用户;MVP 加用户端;移除"自助注册"非目标;注册不送点数)。
- 架构:`04-architecture`(系统结构加用户端;数据模型 Account→`User`+`UserWallet`+`ApiKey`;两套认证;4.2 加自助扫码下单时序;难点加 API Key 哈希/注册滥用/Web-API worker 隔离/充错账户;项目结构 apps;架构纪律)。
- 合约/路由/规则:`api.md`(认证主体 User、`recharge/create` 转正扫码、API 只认 Key)、`routes.md`(用户端页面路由、admin 改 User/Wallet/ApiKey)、`03-tech-stack`(用户端形态 Django SSR+Bootstrap+allauth、鉴权、部署 worker 隔离)、`05-coding-rules`(范围、API Key 哈希、API 只认 Key、锁 wallet)。
- 任务:`06-tasks`(T-002 首迁移前定自定义 User;T-201 改 User/Wallet/ApiKey;T-203 锁 wallet;T-305 扫码下单;新增 Phase 4 用户端 T-501~504;里程碑加 M4 用户端)。
- `README`、`current-state` 同步。
- 验证:仅文档。
- 决策:
- ① 前端形态选 **Django 模板 SSR 单体**(+Bootstrap/allauth/crispy),不引前后端分离框架。
- ② 用户模型:`User`(auth 登录态) / `UserWallet`(点数余额,扣点锁 wallet、与 auth 解耦) / `ApiKey`(User 1:N,sha256 哈希存储、明文只显示一次)。
- ③ 认证分两套认同一 User:用户端 session+CSRF,对外 API 只挂 API Key(不挂 Session,防绕过计费)。
- ④ 充值:`recharge/create` 转正,用户端自助扫码下单 + 回调入账,订单绑定 user 防充错账户,金额 Decimal 向下取整。
- ⑤ **注册不送免费点数**(必须充值才有点数,降低薅羊毛);注册须邮箱验证、生成接口须限流。
- ⑥ 单体部署按路径把图片 API 与用户端页面分流到不同 worker 池。
- 待办提醒:**支付系统扫码下单 + 回调接口文档仍未提供**,是 T-304/T-305 充值的硬阻塞;自定义 User 必须在首次 migrate 前定义(Django 硬约束)。
- 下一步:任务仍从 T-001 起步;用户端任务见 Phase 4(T-501~504)。
## 2026-07-01 补全支付协议(参考同系统 PHP 实现,解除充值 blocker)(非任务)
- 状态:DONE
- 变更:从 Obsidian 笔记(虎观虾皮一键采购 `扫码支付购买流程-技术文档` + `扫码支付迁移到Django-实施指南`)提取同一支付系统的扫码支付协议,补进当前 Django 仓库文档:
- `api.md`:充值段重写为微信 V3 native + 支付宝当面付双回调(`/recharge/callback/wechat`、`/alipay`)+ `create`(pay_method、code_url/qr_code)+ `status` 轮询;金额单位、验签、幂等、应答格式明确。
- `04-architecture.md` 4.2:补通道协议、库、金额单位、回调应答、`@csrf_exempt`、主动查单兜底。
- `03-tech-stack.md`:充值对接行加库 `wechatpayv3`/`python-alipay-sdk`。
- `routes.md`:拆微信/支付宝回调端点 + status。
- `06-tasks.md`:T-304 拆双回调+主动查单,T-305 加 weixin/alipay+轮询。
- `05-coding-rules.md`:回调 `@csrf_exempt` + 主动查单兜底。
- `current-state.md`:blocker 降级。
- 验证:仅文档。
- 决策:
- ① 路线确认:**继续当前 Django 仓库**,Obsidian 的 Go(Gin+GoAdmin) cmhub 方案仅作支付逻辑参考(用户拍板)。
- ② 支付通道:微信 V3 native(`wechatpayv3`,金额**分**,回调 SDK 验签解密、`TRANSACTION.SUCCESS`、应答 `{code:SUCCESS}`);支付宝当面付 `trade.precreate`(`python-alipay-sdk`,金额**元**,`verify`、`TRADE_SUCCESS/FINISHED`、应答 `success`)。
- ③ 二维码不含业务数据,靠 `out_trade_no`(=order_no) 在回调关联;回调 `@csrf_exempt`;幂等 `select_for_update`+`status!=pending`;须主动查单兜底。
- ④ 只取支付层,不引入 Obsidian 源里的套餐/会员有效期/邀请返佣业务(那是虎观助手专有);充值入账走本项目 `UserWallet`+`points_ledger`+`ExchangeRate`。
- 待办提醒:**blocker 从「协议缺失」降级为「仅缺商户密钥/证书真实值」**,不阻塞开发,可先 mock。原 PHP 遗留坑(测试后门号、H5 金额写死、支付宝 debug 沙箱、明文密钥)不迁入。
- 下一步:任务仍从 T-001 起步;充值见 T-304/T-305(可 mock 先行)。
## 2026-07-01 吸收 AI 模型调用机制(来自 Go 方案 §16.6)(非任务)
- 状态:DONE
- 变更:从 Obsidian `Golang-Gin-GoAdmin-技术方案` §16.6 提取三个上游模型的真实调用机制(业务规则/上游契约,非技术栈),补进 `04-architecture.md`(3.1 + AI 层职责)、`api.md`(待确认 + image 改图必传)、`03-tech-stack.md`、`06-tasks.md`(T-101 验收)。
- 验证:仅文档。
- 决策:
- ① GPT-5.5(`chat`)标准 chat/completions;Nano Banana 2(`api_type=auto`)走 chat/completions 多模态返图、需自定义解析、可文/图生图;GPT Image 2(`images_edits`)走 images/edits 改图、原图必传。
- ② 两个图片模型**非标准** `images/generations`,每模型独立 url+key;图片返回结构(URL/base64/位置)**首次对接抓真实响应再定解析**。
- ③ 只吸收 AI 模型机制,**不吸收** Go 方案的会员套餐/续期/折扣/邀请返佣/多端 JWT(属虎观采购业务或 Go 栈,非 cmhub 定位);鉴权继续用 API Key(比桌面端 JWT 更安全,不在桌面端存密码)。
- 下一步:T-101/T-102 实现适配器时按此机制,首次对接 `api.vectorengine.ai` 抓真实响应确认图片返回结构。
<!-- 后续从这里向下继续追加记录。 -->
## 2026-07-01 文档优化:定位一致性 + 充值 schema + 调用状态 + 环境配置(非任务)
- 状态:DONE
- 变更:按全栈落地前优先级修正文档:
- `docs/README.md` / `project-brief.md` / `project-onepager.md`:定位同步为「自助用户端 + 计费型 AI 能力网关 + 运营后台」三合一,并加入 `env.md` 导航。
- `docs/04-architecture.md` / `docs/api.md` / `docs/06-tasks.md`:充值订单改为下单时锁定 `exchange_rate` 与 `points_granted`,回调入账使用订单值并校验金额;`call_record.status` 明确为 `pending -> success / failed`,失败退点通过 `points_ledger(refund, ref_call_id)` 关联。
- `docs/env.md`:新增环境变量与配置清单,覆盖 Django、MySQL、AI 密钥加密、微信/支付宝、对象存储与上线检查。
- `docs/03-tech-stack.md` / `docs/current-state.md` / `docs/00-ai-start-here.md` / `docs/02-requirements.md` / 汇报文档:同步环境配置入口、当前快照与支付 blocker 降级口径。
- 验证:文档修改;用 `rg` 定位相关段落,未运行代码测试(仓库当前尚无代码)。
- 阻塞:无。
- 决策:充值汇率采用「下单锁定」而非「回调时读取当前汇率」,便于页面展示预计到账点数,也避免用户扫码后后台改价导致入账变化;调用记录不增加 `refunded` 状态,账务冲正由点数流水表达。
- 下一步:仍从 T-001 初始化 Django + DRF 骨架开始。
## 2026-07-01 文档优化:里程碑口径同步(非任务)
- 状态:DONE
- 变更:同步汇报文档里程碑到 `06-tasks.md` 的 M1-M5 口径:`project-brief.md` 增加 M4 用户端可用、M5 验收上线;`project-onepager.md` 进度行同步 M4/M5。
- 验证:文档修改;用 `rg` 定位里程碑旧口径。
- 阻塞:无。
- 决策:以 `06-tasks.md` 的里程碑为权威,汇报文档只做同口径摘要。
- 下一步:仍从 T-001 初始化 Django + DRF 骨架开始。
## 2026-07-01 文档优化:Phase 顺序口径同步(非任务)
- 状态:DONE
- 变更:更新 `docs/00-ai-start-here.md` 的优先路径,Phase 3/4/5 与 `docs/06-tasks.md` 对齐:Phase 3 为对外 API 与充值,Phase 4 为用户端,Phase 5 为后台与发布。
- 验证:文档修改;用 `rg` 对照 `00-ai-start-here.md` 与 `06-tasks.md` 的 Phase 标题。
- 阻塞:无。
- 决策:任务阶段顺序以 `06-tasks.md` 为权威,入口文档只做一致的导航摘要。
- 下一步:仍从 T-001 初始化 Django + DRF 骨架开始。
## 2026-07-01 T-001 初始化 Django + DRF 项目骨架
- 状态:DONE
- 变更:
- 新增 `manage.py`、`config/` Django 工程骨架。
- 新增 `requirements.txt`,锁定 Django 5.2 系列与 DRF 3.16 系列。
- `config/settings.py` 加入 `rest_framework`,`SECRET_KEY` / `DEBUG` / `ALLOWED_HOSTS` 支持环境变量,默认仅用于本地开发。
- `init.ps1` / `init.sh` 替换为真实命令;按用户要求使用系统 Python 3.12,不使用虚拟环境。Windows 用 `py -3.12`,Unix/WSL 用 `python3.12`。
- 同步 `docs/00-ai-start-here.md`、`docs/03-tech-stack.md`、`docs/current-state.md`、`docs/06-tasks.md`、`README.md`。
- 验证:
- `py -3.12 -m pip install -r requirements.txt`:Django 5.2.15 / DRF 3.16.1 已安装。
- `py -3.12 manage.py check`:通过,0 issues。
- `py -3.12 manage.py test`:通过,当前 0 tests。
- `./init.ps1`:通过,完成依赖检查、`manage.py check`,打印启动命令。
- `C:\Python312\python.exe manage.py runserver 127.0.0.1:8765 --noreload`:端口 smoke 通过(TCP 8765 可连接),随后已停止进程。
- `bash -n init.sh`:当前机器无可用 bash/WSL,无法本机验证 Unix 脚本。
- 阻塞:无。
- 决策:T-001 不接入 MySQL、不创建自定义 User、不创建 apps 目录;这些按任务边界留给 T-002。T-001 阶段暂保留 Django 默认 SQLite 配置用于框架启动检查,T-002 必须在首次迁移前改为自定义 User + MySQL 8.4 配置。
- 下一步:领取 T-002 建立 apps 目录、自定义 User 与配置。