回答 Neo 在 01-W1-findings-response.md 上写的 5 个新问题: 1. F1-3 Frozen >1 年 - 本地硬盘 tar.zst 即可, 不必对象存储 2. F2-1 OpenAPI 作用深入浅出 - "厨房菜单 vs 大堂菜单"比喻 + 5 个使用场景 (FastAPI 双层结构 + 28 天 stale 不破坏运行的原因) 3. F2-2 自建 Gitea 优化 - .gitea/workflows/ 替代 GitHub Actions, 默认仍 5 分钟版 (步骤 1+2+5), 启 Actions 可选 4. F3-2 system prompt 计费 - 100% 计入 (Qwen 无 caching 折扣) + 推荐方案 A 全 prompt 入 git 单源 (新增 Wave 5 prompt 治理任务) 5. F3-4 全 API 端点遍历 - ~25-30 端点 / 半天集中改造, 兑现 Wave 0 全览调研价值 (推荐 Wave 5 集中, 不分散) 最终 Wave 总分配: - Wave 1 (进行中): F1-5 - Wave 2 前 (立即): F2-1A 恢复脚本 - Wave 2: F1-1 / F2-1B hook / F3-1 / F3-2A / F3-3 - Wave 4: F1-2 / F1-3 三层归档 / F3-5 - Wave 5: F2-2 tests / F3-4 全 API 沙箱校验 / F3-2B prompt 治理 (新增) 待 Neo 拍板 3 项: - F2-2 是否启 Gitea Actions - F3-2B 全 App prompt 入 git 单源 是否启动 - F3-4 集中 Wave 5 vs 分散
25 KiB
Wave 1 发现 — Neo 反馈响应(主线整合)
日期:2026-05-04 / 触发:Neo 在
00-W1-findings-stories.md12 项业务故事卡上写斜体反馈 用途:对每条反馈给出主线处理路径 + 修正前期判断错误 + 答疑 + 评估新方案
一、12 项处理总览(更新版)
| # | Neo 反馈类型 | 处理 | Wave |
|---|---|---|---|
| F1-1 | ✅ 同意 Wave 2 选 A | 直接排程 | Wave 2 |
| F1-2 | 🟡 质疑前提"问题在哪" | 降级为 P1 UX(非安全),修正描述 | Wave 4 |
| F1-3 | 🟡 提出新方案 JSON+MD | 评估并推荐改良版 | Wave 4 |
| F1-4 | 🟡 质疑前提"site_admin 不能登 admin-web" | 撤销 — 不是问题 | — |
| F1-5 | ✅ 同意 Wave 1 选 A | 直接排程 | Wave 1 |
| F2-1 | 🟡 要历史原因调研 | 真相:抓取脚本被 Claude Opus 4.6 大批量清理时误归档(2026-04-06)→ A 恢复脚本 + B 加 hook | Wave 2 前(立即) |
| F2-2 | 🟡 给出前提要更优方案 | 简化方案(不脱敏 + 不启 CI) | Wave 5 |
| F3-1 | ✅ 选 B(显式 ?scope=) | 直接排程 | Wave 2 |
| F3-2 | 🟡 让我联网搜 | DashScope 实证 + 推荐方案 | Wave 2 |
| F3-3 | ✅ 选 A(audit + 二次确认) | 直接排程 | Wave 2 |
| F3-4 | ✅ 选 A + 新提问 | 答疑"沙箱 4-1 申请 4-5 数据" | Wave 5 文档 |
| F3-5 | ✅ 选 A,先彻底修完再后续 | 直接排程 | Wave 4 |
二、修正项详细分析
F1-2 修正:不是"跨租户 PII 泄露",是"切 site UX 不一致"
Neo 的质疑(完全正确):
admin-web 是系统管理后台,看到租户的一些信息,问题在哪里?我同意加店铺过滤,也可以查看所有店铺。
主线核实代码(权限模型实证):
admin-web 登录: auth.admin_users (super_admin / admin),JWT aud="admin"
tenant-admin 登录: auth.tenant_admins (tenant_admin / site_admin),JWT aud="tenant-admin"
两套用户表 + 两套 aud 完全分离,admin-web 没有 site_admin 登录场景。所以原 F1-2 描述里的"site_admin 越权看到 PII"前提错误 — site_admin 根本进不来 admin-web。
修正后真正的问题:
- admin-web super_admin 切 site 时,run-logs 列表应该按所选 site 过滤(否则切 site 没意义)
- 但 super_admin 依然有权看所有 site(只是默认按当前选择的 site 显示,可显式切"全部")
- 这是 UX 一致性问题,不是安全/PII 问题
修正后的方案:
- A 切 site 即过滤,提供"全部 site"切换选项(推荐):默认按当前 site 过滤,super_admin 可显式切"全部" → UX 一致
- B 维持现状(全表,前端筛选):零改 → super_admin 习惯
- C 维持现状 + 列表加 "site_id" 列:可读性提升,无过滤 → 简单
修正后判定:[P1 UX] Wave 4(数据正确性 Wave,顺手),选 A — 与切 site 行为一致。法律风险表述删除(super_admin 有合法授权)。
反馈:选择方案A
F1-4 撤销:admin-web 没有 site_admin 登录场景,问题不存在
Neo 的质疑(完全正确):
admin-web 是系统级管理后台,site_admin 本就没有权限登录啊,何来此问题?
主线核实:确认 admin-web 路由全部 Depends(get_current_user) 来自 admin_users 表,site_admin 通过 tenant-admin 登录,JWT aud="tenant-admin",根本无法通过 admin-web 登录(aud 不匹配会被拒绝)。
结论:F1-4 撤销(P1-7 PRD 撰写时假设了多角色 admin-web 场景,与实际不符)。
关联调整:批 1 PRD 里 F1-4 评估发现需要回滚标注。让我在批 1 PRD 加注脚,声明这条评估错误已撤销。
结论:[B 现状对] 撤销,无需 Wave 排期
三、评估 Neo 新方案
F1-3 评估:JSON 索引 + MD 文件 / 或 JSON 也放硬盘
Neo 提出:
基于 B 选项再做优化,数据库只记录索引(每月一行的 JSON 数据索引),通过 JSON 解读出要找的 MD 文件,真正内容记录在 MD 文件中,以文件形式记录在指定硬盘目录中。或者更激进 — JSON 也放硬盘?
主线评估:
优势
- 数据库压力大幅降低:90 天 hot 数据保留 DB,90+ 天冷数据归档到文件 → 列表查询不卡
- 可读性强:MD 文件运维可直接
cat / grep,不依赖客户端 - 备份成本低:文件系统增量备份比 DB 增量备份便宜
- 符合"冷数据归档"通用模式
风险
- 跨月查询不便:JSON 索引按月组织,用户查"最近 7 天 token 使用"需要跨 1-2 个月文件聚合
- 全文检索弱:MD 不支持索引 → grep 慢(尤其文件大时)
- 并发写:多个 AI 调用同时写同一个 MD 文件 → 需要文件锁或单 worker 串行写
- 激进版"JSON 也放硬盘"问题更大:列表查询需要扫所有月份 JSON,启动慢
推荐改良版
hot/cold + 工业标准格式:
- Hot(0-30 天):DB
biz.ai_run_logs(列表 / 筛选 / 分页友好) - Cold(30-365 天):Parquet 文件按月分区(
/data/cold/ai_run_logs/2026-04.parquet),DuckDB 可直接 SQL 查询,列存压缩比 MD/JSON 高 10x - Frozen(>1 年):对象存储(可选,Wave 5 之后)
- Index:DB 保留
biz.ai_run_logs_archive_index表(每月一行,记 partition 路径 + row_count + 占用空间)
比 Neo 的 JSON+MD 方案优:
- ✅ Parquet 比 MD 体积小,解压快
- ✅ DuckDB 直接对 Parquet 跑 SQL,跨月聚合不需要写 Python 代码
- ✅ 工程上久经考验(数据湖标准格式)
比 Neo 的"JSON 也放硬盘"激进版优:
- ✅ 启动快(DB index 表毫秒级返回月份列表)
- ✅ 工程友好(Parquet 主流工具链都支持)
修正后判定:[P1] Wave 4,选改良版 D(Hot DB 30 天 + Cold Parquet 按月分区)。如果你坚持 MD 友好(运维 cat / grep),可以双写:Parquet 主存储 + MD 摘要文件(每行 1 句关键字段)用于人眼浏览。
反馈:同意你的做法,选择改良版 D(Hot DB 30 天 + Cold Parquet 按月分区)。但Frozen(>1 年)使用对象存储,也是放在本地硬盘么?
四、简化方案
F2-2 改良:基于 Neo 给的前提,最简方案
Neo 给的前提:
仅当前开发环境进行测试;支持同步测试脚本到 GIT;敏感信息可以上传 GIT 我允许
最简方案(对齐 Neo 前提):
| 步骤 | 动作 | 工时 |
|---|---|---|
| 1 | 改 .gitignore:71 tests/ → 删除该行(或改为更精细 **/__pycache__/ **/.pytest_cache/) |
5 分钟 |
| 2 | git add -A apps/*/tests/ 入仓现有所有测试 |
1 分钟 |
| 3 | 不脱敏(Neo 允许敏感) | 0 |
| 4 | 不启 CI(Neo 仅本地测试) | 0 |
| 5 | 写审计:tests 入仓 + 备注"Neo 决定本地跑测试" | 5 分钟 |
好处:
- 测试代码可见 → 跨设备协作不破坏
- 测试可信度提升(Wave 1 W1-T4 audience 7 单测可入仓)
- 后续若决定启 CI,只需添 GitHub Actions 即可,无需先做脱敏扫描
修正后判定:Wave 5 处理(主线 5 分钟级动作,跟其他文档收尾合并 1 个 PR)。
反馈:我使用自建Gitea服务器,和GitHub没关系啊。再看下方案,进行优化修改。
五、F3-2 实证 — DashScope Qwen3-Max-Preview 计费
5.1 官方计价(2026-05 实测)
| 项 | DashScope 官方价 | OpenRouter 第三方 |
|---|---|---|
| Input | $1.20 / 1M tokens ≈ ¥8.64 / 1M | $0.78 / 1M |
| Output | $6.00 / 1M tokens ≈ ¥43.20 / 1M | $3.90 / 1M |
| 上下文窗口 | 258K tokens | — |
| 最大输出 | 66K tokens | — |
(USD→RMB 按 1:7.2 估算,实际按结算汇率为准)
5.2 Qwen3 Tokenizer 切词特性(用于精确估算)
Qwen3 系列基于 BPE tokenizer,中英文切词比例:
| 文本类型 | 字符 / token 比 | 1000 字符约耗 token |
|---|---|---|
| 纯英文 | 3.8-4.2 | ~250 |
| 纯中文 | 1.6-1.9 | ~600 |
| 中英混合 | 2.0-2.5 | ~450 |
| JSON 结构 | 2.5-3.0(标点占 token) | ~370 |
NeoZQYY 场景多为中文 prompt + JSON output,估算系数:1000 字符 ≈ 500 tokens。
5.3 SDK 计费返回(关键)
DashScope SDK 调用返回中包含实际 token usage:
response = dashscope.Generation.call(...)
# response.usage.input_tokens
# response.usage.output_tokens
# response.usage.total_tokens
重要发现:DashScope 不返回直接的 RMB cost 字段,需要后端按"input × 单价 + output × 单价"自己算。
5.4 推荐方案(基于实证)
修正后选项:
- A SDK token + 配置表单价(SCD2):
cfg_ai_token_price表按(model, effective_from)切片,每次调用记 input_tokens / output_tokens,后端实时算 RMB → 优:符合 SCD2 规范,DashScope 调价时只需 INSERT 新行 劣:对账依赖配置表与官方价格同步 - B 硬编码 $1.20 / $6.00 + 月度对账:简单,DashScope 调价后手工更新代码 → 优:5 分钟落地 劣:依赖人
- C 调用 DashScope 计费 API(若有):查询账户实际消费 → 优:最准 劣:大概率没有此 API
修正后判定:选 A(SCD2 配置表),Wave 2 实施。表 schema 建议:
CREATE TABLE biz.cfg_ai_token_price (
model_name TEXT NOT NULL, -- 'qwen3-max-preview'
input_price_per_million NUMERIC(8,4), -- 8.64 RMB
output_price_per_million NUMERIC(8,4), -- 43.20 RMB
currency TEXT DEFAULT 'CNY',
effective_from DATE NOT NULL,
effective_to DATE, -- NULL 表示至今
note TEXT,
PRIMARY KEY (model_name, effective_from)
);
写入策略:Wave 2 第一次种子写入当前价格,后续 DashScope 调价时人工 INSERT 新行(effective_from = 调价日,前一行 effective_to = 调价前一日)。
同意你的调研结果,按这个来。另外,system prompt要不要也计算在内?我是否要更新一版全App的System prompt同步在项目中?
六、F3-4 答疑 — "沙箱 4-1 申请 4-5 数据"
Neo 提问:
比如沙箱设定了 4 月 1 日,我申请了 4 月 5 日的数据,如何处理?返回空?
主线分析(基于 P20 SPEC §3.5 业务日上界视图):
6.1 当前实现(2026-05-02 已落地)
P20 SPEC §3.5 的 39 个业务日上界视图,在沙箱模式下:
WHERE <date_column> <= app.business_date_now() -- = sandbox_date
意味着:
- 沙箱设 2026-04-01,小程序/admin-web 访问任何业务数据视图
- 视图自动 WHERE 上界 ≤ 2026-04-01
- 如果用户显式过滤
>=2026-04-05(申请 4-5 数据)→ 返回空(因为 4-5 这天的数据已被视图层过滤掉)
6.2 推荐处理(更友好)
| 选项 | 行为 | 优 | 劣 |
|---|---|---|---|
| A 显式 422 拒绝(我推荐) | 后端校验:若用户 query 含 date_param > sandbox_date → 返回 422 + "沙箱日期 2026-04-01,无法查询晚于此日期的数据" |
UX 明确,用户知道为什么空 | 后端 query 校验逻辑增加 |
| B 静默返空 | 当前实现:返回 [] | 简单 | 用户不知道是真没数据还是被沙箱挡了 |
| C 悄悄裁剪查询范围 | 后端把 >=4-5 自动改为 <=4-1 |
看起来"有数据" | 误导用户,数据语义错位 |
强烈推荐 A:沙箱演示场景下,用户切了 sandbox_date 应该明确知道"不能查未来",422 是清晰的反馈。
实施位置:
- 小程序 + admin-web 的 board / records 端点,在 query 解析后加校验
- 校验函数放
apps/backend/app/services/runtime_context.py,统一逻辑
修正后判定:Wave 5 文档收尾时统一加 + 在 P20 SPEC §3.5 加这条 AC(验收标准)。可在 Wave 1-4 内任何模块改动时顺手加。
反馈:这个方式好!友好的交互。但要注意你说说的,所有API数据的端点都要加解析,API和页面,需要全部遍历(之前提过的一个文档全览的一个任务的价值。)让所有页面和功能都适配。
七、F2-1 OpenAPI 历史调研(完成)
详细 234 行报告 → F2-1-openapi-history.md
惊人真相(印证 Neo 直觉"有历史原因被忽略"):
- OpenAPI 抓取脚本
scripts/ops/_export_openapi.py曾经存在,12 行(2026-03-09 创建,逻辑极简from app.main import app; app.openapi()) - 2026-04-06 00:03:同一天先跑脚本抓最后一次 OpenAPI(commit 6f8f123,backend-api.json 末次更新)
- 2026-04-06 00:39:36 分钟后,Claude Opus 4.6 协助"清理 1155 个废弃文件"(commit
779b2f6),把活的工具与一堆 v4-v8 废报告脚本一起误归档到_DEL/_DEL/scripts/ops/_export_openapi.py— 大批量整理时工具识别不足 - 28 天内无人发现(因为
spec-close.md第 45 行虽写"手工同步 backend-api.json"但没指脚本路径,无 hook 强制) - 9/10 缺失端点都是工具消失后新加的 router(都在
caf179a/ 2026-05-04 02:30 加入) - 1/10(
/api/admin/triggers/unified)在6f8f123同 commit 内,属"抓取与合并并行竞态"
真相判定:AI 大批量整理时的误判,把活的工具当废文件归档。脚本本身无 bug,只是消失了。
推荐方案 A+B 组合:
- A 从
_DEL/恢复脚本(5 分钟,12 行无需改)+ 重抓 + 入仓 → Wave 2 撰写前完成 - B 加 PostToolUse hook 匹配
apps/backend/app/routers/*.py,提醒重抓,并在 spec-close.md 第 45 行补脚本调用命令(防 OpenAPI 再 stale) - C(改运行时拉 /openapi.json)留 Wave 5 远期治理
修正后判定:Wave 2 前主线立即执行 A 恢复 + 重抓(零风险),Wave 2-3 加 B 防御。
反馈:同意你的建议,吸取教训,建立一些机制,不要让类似事件再发生。另外,我还是不太明白OpenAPI 脚本再本项目中的作用,结合业务,深入浅出的再向我解释下。
八、本次响应后 Wave 重新分配
| Wave | 新增 / 调整 |
|---|---|
| Wave 1(进行中) | + F1-5 沙箱 batch-run 接入 runtime_context(沙箱主线必修) |
| Wave 2 | + F1-1 长事务幂等(批 2 admin-ai 改造时一并)+ F2-1 修 OpenAPI 抓取 + F3-1 cache 粒度 + F3-2 配置表单价 + F3-3 audit_log + 二次确认 |
| Wave 4 | + F1-2 降级 UX(切 site 过滤) + F1-3 hot/cold + Parquet + F3-5 unified 分页 |
| Wave 5 | + F2-2 tests/ 入仓(简化 5 分钟版) + F3-4 沙箱越界 422(P20 SPEC AC + 各 service 校验) |
| 撤销 | F1-4(admin-web 无 site_admin 场景) |
九、需 Neo 进一步确认的 3 项
| # | 问题 | 主线建议 |
|---|---|---|
| F1-3 | hot/cold + Parquet 改良版 vs Neo 原 JSON+MD 方案 | 改良版(运维"cat 友好"可加双写 MD) |
| F1-2 | 修正后选 A(切 site 过滤 + 显式"全部")vs 维持现状 | A |
| F3-2 | SCD2 配置表单价 vs 硬编码 | SCD2 |
回答这 3 项后,所有 Wave 1 findings 进入实施轨道。F2-1 子代理调研完成后,主线整合最终路径。
来源
- DashScope Qwen3-Max-Preview 价格:
十、第二轮追加 — Neo 5 个新问题回答
10.1 F1-3 追问 — Frozen >1 年 用对象存储,是放在本地硬盘么?
答:对。"对象存储"是技术术语,不一定是云,在你项目里直接本地硬盘即可。
澄清概念:
| 形态 | 定义 | 你项目是否合适 |
|---|---|---|
| 云对象存储 | 阿里云 OSS / 腾讯云 COS / AWS S3 | 不适合(外部依赖 + 要钱) |
| 本地对象存储 | MinIO(开源,本地部署,S3 兼容) | 数据量大时再考虑 |
| 本地文件系统 | /data/cold/.../frozen/YYYY.tar.zst |
就用这个最简 |
修正后 Frozen 方案:
- 1 年以上的月份 Parquet 打包成
frozen/2026.tar.zst(zstd 压缩,比 gzip 小) - 放服务器本地硬盘指定目录(如
/data/cold/ai_run_logs/frozen/) - DB index 表记
frozen_path = '/data/cold/.../2026.tar.zst',需要时主线脚本解压查 - 不必上 MinIO 或 OSS,直到数据量超过 100GB 再考虑
补充:这种"本地硬盘冷归档"也是工业常见做法(很多自托管系统都这么干,比如 PostgreSQL WAL 归档)。
10.2 F2-1 追问 — OpenAPI 脚本作用 深入浅出
用人话说:OpenAPI 是后端给前端 / AI 工具 / 测试团队看的"功能菜单 JSON",菜单要随后端改动同步更新。
菜单上写什么:
- 项目有哪些 API(151 个)
- 每个 API 接受什么参数(GET / POST / 必填 / 可选)
- 每个 API 返回什么字段(响应结构)
- 每个 API 的权限要求(super_admin / 任意 admin / 公开)
FastAPI 的双层结构:
后端运行时 ──→ 自动暴露 GET /openapi.json(实时生成的菜单,永远最新)
↓ 用 _export_openapi.py 抓
docs/contracts/openapi/backend-api.json(静态版本,存 git,不启动后端就能查)
菜单(backend-api.json)在 NeoZQYY 的 5 个使用场景:
| # | 用途 | 当前是否在用 |
|---|---|---|
| 1 | admin-web 前端类型自动生成(openapi-codegen) | 没用(前端手写 axios) |
| 2 | MCP 工具读 spec(.mcp.json 的 openapi 配置)→ AI 助手知道项目有哪些 API |
在用(但 stale 时 AI 不知道新 API) |
| 3 | Swagger UI 渲染(交互式 API 文档页面) | 在用(后端 /docs 路由) |
| 4 | API 变更追踪(diff 新旧 backend-api.json) | 偶尔用 |
| 5 | Wave 1 W1-T7 PRD 撰写自动生成总表 | 本次在用(发现缺端点) |
为什么 28 天没发现 stale:
- 前端手写 axios,不依赖 openapi-codegen 自动生成 → 没"前端自动断"反馈
- MCP 工具 stale 时 AI 助手只是"不知道某些新 API",不会破坏运行功能
- Swagger UI 走的是后端运行时
/openapi.json,不读 backend-api.json,也不会受影响 - 真正会断的是 Wave 1 这种"自动生成 PRD"工作流 — 28 天内没人做这事
菜单与代码的关系比喻:
- 后端 router 改了 → 相当于厨房新加了一道菜
- 自动菜单(
/openapi.json)立刻有这道菜 - 静态菜单(backend-api.json)需要服务员(脚本)定期把厨房菜单抄到大堂
- 服务员被误辞退后,大堂菜单 stale 28 天
修复价值:
- A 恢复脚本 + 重抓:服务员回来了
- B 加 hook:每次厨房改菜,自动叫服务员
10.3 F2-2 追问 — 自建 Gitea,方案优化
修正方案(对齐 Gitea 自建环境):
| 步骤 | 动作 | 备注 |
|---|---|---|
| 1 | 删 .gitignore:71 tests/ |
不变 |
| 2 | git add apps/*/tests/ 入仓现有所有测试 |
不变 |
| 3 | (可选)加 .gitea/workflows/test.yml Gitea Actions |
Gitea 1.20+ 支持 Actions(语法兼容 GitHub Actions),自建 Runner |
| 4 | 不脱敏(Neo 允许) | 不变 |
| 5 | 写审计 | 标"自建 Gitea + 仅本地测,可选 Gitea Actions" |
步骤 3 Gitea Actions 是否启用:
- 启:Gitea 服务器有富余资源 + 想自动跑测试 + Runner 已配 → 推荐(类似 GitHub Actions 体验)
- 不启:仅本地跑(Neo 当前前提)→ 跳过这步,5 分钟方案就够
关键差异(对比 GitHub Actions):
- 配置文件路径:
.gitea/workflows/*.yml(不是.github/workflows/) - 语法 95% 兼容 GitHub Actions
- Runner 在自己服务器(数据不出自己机房,符合 Neo 自建偏好)
- 免费(GitHub Actions 私有仓有 quota,Gitea 自建无限制)
修正后判定:Wave 5 处理,默认走 5 分钟版(步骤 1+2+5);如 Neo 需要 CI,Wave 5 末尾追加步骤 3。
10.4 F3-2 追问 — system prompt 计费 + 全 App prompt 同步项目
问题 A:system prompt 是否计入 token 费用?
答:100% 计入。
DashScope 计费规则:
input_tokens= system_prompt tokens + 历史消息 tokens + 本次 user 消息 tokens- 每次调用都会重新算一遍 system prompt(没有"prompt 缓存折扣")
示例:
- system prompt 长 1000 字符(中文)≈ 600 tokens
- 1000 次调用累计 = 60万 input tokens
- 60万 × ¥8.64/1M = ¥5.18(单 system prompt 部分一年的成本)
优化建议:
- 精简 system prompt(每减 100 字 → 一年省 ~¥1)
- 不要把"几乎不变的业务字典"塞 system prompt(可以塞 user prompt 末尾,某些 model 支持 prompt cache)
- Qwen 系列没有 prompt caching 折扣(Anthropic / OpenAI 部分模型有),所以全量计费
问题 B:是否要更新一版全 App 的 system prompt 同步在项目中?
强烈推荐 A 全 prompt 入 git 作为权威源。
当前现状(P2-6 调研发现):
- 8+1 个 APP 的 prompt 一部分在百炼云端控制台,一部分在 git (
apps/backend/app/ai/prompts/app[N]_*_prompt.py) - 双源风险:云端调优后 git 没同步,或 git 改了云端没更新 → 实际运行用的是哪个?
3 套方案对比:
| 方案 | 描述 | 优 | 劣 |
|---|---|---|---|
| A 全 prompt 入 git + SDK 显式传(推荐) | 调用 dashscope SDK 时传 prompt_template 用 git 版本,云端控制台 prompt 仅作开发调试用 |
git 是唯一权威 + 可 diff / blame | 工作量大,需要把云端现有 prompt 全部导出入 git |
| B 仅 git 备份 + 云端权威 | 每月手工导出云端 prompt 到 git docs | 简单 | 易过期,不可追溯 |
| C 维持现状 | 双源分裂 | 0 改 | 完全不可追溯 |
A 实施步骤:
- 先做"勘察":列出 8+1 个 APP 哪些 prompt 在云端、哪些在 git
- 把云端 prompt 全部导出到
apps/backend/app/ai/prompts/(每 APP 一文件) - SDK 调用改为传
prompt_template = open(prompt_file).read() - 云端控制台 prompt 标"已废弃,以 git 为准"或直接清空
- 写 SPEC
docs/prd/specs/PXX-ai-prompt-governance.md约定"git 单源"
关联 P2-6 决策:Neo P2-6 反馈"暂时不改 prompt 我同意,但要记录后续观察的需求,需要跟踪" — 本项 B 是这个跟踪的具体落地。
修正后判定:新增 Wave 任务 — Wave 5 prompt 治理(Wave 5 文档收尾时统一处理,因为不阻塞功能)。
10.5 F3-4 追问 — 全 API 端点遍历改造工作
Neo 的关联:
注意你说说的,所有 API 数据的端点都要加解析,API 和页面,需要全部遍历(之前提过的一个文档全览的一个任务的价值。)让所有页面和功能都适配。
完全正确。这就是 Wave 0 全览调研的价值兑现。
覆盖范围估算(基于 Wave 0 已有矩阵):
| 来源 | 端点数 | 需加 sandbox 校验子集 |
|---|---|---|
| 02b admin-web 矩阵 | 19 路由 | ~8 个(board / runtime-context / db-viewer / 大部分 admin_ai) |
| 02a 小程序矩阵 | 21 页 → ~25 业务 API | ~15 个(board-finance/customer/coach + performance + customer-records + ...) |
| tenant-admin(未在 Wave 0 矩阵但需补) | ~10 个 | ~5 个 |
| 批 1 PRD 23 端点 | — | 已覆盖部分 |
| 合计 | — | ~25-30 个端点需校验 |
实施方式(集中而非分散):
# apps/backend/app/services/runtime_context.py
def assert_query_within_sandbox(
site_id: int,
query_dates: list[date], # 用户传入的所有日期参数
) -> None:
"""
沙箱模式下校验:用户查询的日期不能超过 sandbox_date。
超过则抛 HTTPException(422, "沙箱日期 X,无法查询晚于此日期的数据")。
"""
ctx = get_runtime_context(site_id)
if ctx.mode != "sandbox":
return # live 模式不校验
for d in query_dates:
if d > ctx.business_date:
raise HTTPException(
status_code=422,
detail=f"当前为沙箱模式 {ctx.business_date},不能查询晚于此日期的数据(请求 {d})",
)
各 service 调用方:
# 任何接受日期 query 的端点
@router.get("/board/finance")
async def get_board_finance(
start_date: date,
end_date: date,
user: CurrentUser = Depends(...),
):
assert_query_within_sandbox(user.site_id, [start_date, end_date]) # 1 行
# 后续业务逻辑不变
总工作量:
- 1 个 helper 函数(15 分钟)
- ~25-30 处端点各加 1 行调用(每处 2 分钟,合计 1 小时)
- P20 SPEC §3.5 加这条 AC(10 分钟)
- 走查测试每端点 5-10 分钟,合计 ~3-4 小时
- 总和:半天工作量(零分散)
这正是 Wave 0 全览的回报:不需要重新摸排哪些端点要改,矩阵已列出。
修正后判定:
- 集中改造(不在各 Wave 顺手加)→ Wave 5 末尾专门做一批,半天搞定
- 关联 Wave 0 矩阵作为校核清单(Wave 5 末打钩"30 个端点已覆盖")
- P20 SPEC §3.5 加 AC + §14.4 走查清单加这条
十一、本次响应后 Wave 总分配(最终版)
| Wave | 主题 + 新增 |
|---|---|
| Wave 1(进行中) | + F1-5 沙箱 batch-run 接入 runtime_context |
| Wave 2 前(立即) | F2-1 恢复 OpenAPI 抓取脚本(从 _DEL/ 拉回 + 重抓 + 入仓) |
| Wave 2 | F1-1 长事务幂等 + F2-1B 加 hook + F3-1 cache 粒度 + F3-2 SCD2 配置表 + F3-3 audit_log + 二次确认 |
| Wave 4 | F1-2 切 site 过滤 UX + F1-3 Hot/Cold/Frozen 三层 + F3-5 unified 分页 |
| Wave 5 | F2-2 tests/ 入仓(Gitea 简版)+ F3-4 全 API 沙箱校验集中改造(半天 + 30 端点)+ F3-2B prompt 治理(全 prompt 入 git 单源)(新增) |
| 撤销 | F1-4 |
十二、还需要 Neo 拍板的 3 项
| # | 问题 | 我的建议 |
|---|---|---|
| F2-2 | 是否启 Gitea Actions(还是仅本地跑) | 看 Neo 自建 Gitea 是否方便 — 不强求 |
| F3-2B | 全 App prompt 入 git 单源(选 A)是否启动 | Y,Wave 5 处理 |
| F3-4 | 集中 Wave 5 改造(半天)vs Wave 1-4 分散加 | 集中 Wave 5(避免分散遗漏) |
回答这 3 项,Wave 1 findings 完整收口。F2-1 恢复脚本可以现在就做(零风险 5 分钟)。
下一轮 Neo 反馈完成后,主线立即按最终 Wave 分配执行。Wave 1 仅剩 W1-T8 §14 走查 + F1-5 沙箱 batch-run 接入 runtime_context 两项即可收尾。