diff --git a/docs/2026-05-30-PROJECT_LEARNINGS_AND_LOCAL_SKILLS.md b/docs/2026-05-30-PROJECT_LEARNINGS_AND_LOCAL_SKILLS.md new file mode 100644 index 00000000..550b1fed --- /dev/null +++ b/docs/2026-05-30-PROJECT_LEARNINGS_AND_LOCAL_SKILLS.md @@ -0,0 +1,147 @@ +# 2026-05-30 项目经验总结与本地 Skills 沉淀 + +## 目标 + +把这次 `sub2api-cn-relay-manager` 项目里反复验证过、且明显提升任务完成质量的经验沉淀为可复用 skills,减少后续任务中的以下问题: + +- 只做本地验证就误判“已完成” +- 控制面、运行态、数据面三层割裂 +- `provider_status / last_probe_status` 和真实用户数据面不一致 +- 长链路任务推进数小时后,状态板、远端环境和实际代码版本发生漂移 + +本次新增的项目内 skills 放在: + +- [.agent/skills/remote-truth-closure/SKILL.md](/home/long/project/sub2api-cn-relay-manager/.agent/skills/remote-truth-closure/SKILL.md) +- [.agent/skills/routing-data-plane-e2e/SKILL.md](/home/long/project/sub2api-cn-relay-manager/.agent/skills/routing-data-plane-e2e/SKILL.md) +- [.agent/skills/false-negative-status-triage/SKILL.md](/home/long/project/sub2api-cn-relay-manager/.agent/skills/false-negative-status-triage/SKILL.md) + +## 项目级经验 + +### 1. “本地通过”不能代表“任务完成” + +这次项目里最重要的经验不是某个接口,而是交付链必须闭环: + +1. 本地测试与门禁通过 +2. 提交并推到目标远端 +3. 真实远端部署到指定实例 +4. 真实入口或真实用户链路验证 +5. `EXECUTION_BOARD.md` 如实落盘 + +任何一步缺失,都不应声明“已完成”。 + +### 2. 控制面、运行态、数据面必须分开看 + +本项目后期已经清晰分成三层: + +- 控制面:`logical_group / route / shadow_group / public_model` +- 运行态:`sticky / cooldown / failover / route health` +- 数据面:真实 `/v1/chat/completions` 与 host `usage_logs` + +如果只验证控制面创建成功,不能证明路由真正可用;如果只看前端目录展示,也不能证明普通用户真的能用。 + +### 3. stock host 的 shadow provider 尽量使用 canonical model + +真实验证证明,把 `alias/public model` 直接下沉到 stock host 的 shadow group,容易触发 `channel pricing restriction` 一类兼容问题。 + +更稳的策略是: + +- public alias 留在插件层 +- stock host 的 shadow provider 尽量只承载 canonical upstream model + +### 4. 最终证据优先级要固定 + +这次项目里,很多误判都来自错误地把低优先级信号当成最终真相。 + +更可靠的证据顺序是: + +1. 真实用户数据面结果 +2. host `usage_logs` +3. route decision / sticky / failover 日志 +4. provider / inventory 投影状态 +5. probe-only 结果 + +尤其是 host 侧,后续要优先看 `usage_logs`,不要再拿 `api_keys.usage_*` 当最终证据。 + +### 5. false-negative 不应通过“隐藏错误”解决,而应通过“修正语义”解决 + +这次最后一轮修复很典型: + +- `batch_status=partially_succeeded` 仍然保留 +- 但只要真实 `access_status` 已 ready,`provider_status` 就不该继续显示为 `degraded` +- 对单帐号、真实 access 已 ready、`smoke_model_seen=true` 的场景,`provider_account` 也不应继续显示 `broken/failed` + +关键不是把失败抹掉,而是让不同层级状态各自表达正确语义。 + +### 6. 长链路任务必须把“代码提交”和“验收记录提交”分开 + +这次项目反复证明,分开提交非常重要: + +- 功能提交:表达行为变化 +- docs/验收提交:表达真实验证结果 + +### 7. 远端环境必须主动清理,避免测试噪音 + +`remote43` 的历史目录、旧进程、旧 bundle、旧 checkout 残留,会直接污染验证结果,甚至制造绑定歧义、路由归属冲突这类假问题。 + +后续长项目应尽早建立: + +- 仅保留一个 active app 目录 +- 仅保留一个 latest fixed checkout +- 主动清理旧 bundle、旧辅助进程、临时逻辑分组 + +## 新增 skills 的作用 + +### 1. `remote-truth-closure` + +**作用**:把“本地开发 -> 提交推送 -> 远端部署 -> 真验 -> 状态板更新”收成一个强约束工作流。 + +**解决的问题**: + +- 任务推进到一半就误判完成 +- 远端跑的版本和本地以为的版本不一致 +- `EXECUTION_BOARD.md` 和真实状态脱节 + +### 2. `routing-data-plane-e2e` + +**作用**:专门约束逻辑分组、route、shadow host/group/model、managed key 与真实 chat 数据面的闭环验收。 + +**解决的问题**: + +- 只验证了 `resolve`,没验证真实 `/chat/completions` +- 没有 host 侧 usage 证据,无法证明命中目标帐号 +- public alias 与 canonical shadow model 混用导致 host 兼容问题 + +### 3. `false-negative-status-triage` + +**作用**:当 `provider_status / account_status / probe_status` 和真实用户请求不一致时,强制按四层信号做对比,并把修复限定在最小语义边界内。 + +**解决的问题**: + +- 真实用户链路通了,但后台仍显示 `degraded` 或 `broken` +- 误把 raw probe 失败直接投影成最终可用性 +- 用过度宽松的规则掩盖真实坏样本 + +## 对后续任务的直接收益 + +### 完成质量 + +- 更少虚假的“已完成” +- 更少只验证局部能力的片面结论 +- 更强的远端真相约束 +- 更少由测试残留导致的错误判断 + +### 完成能力 + +- 更快从卡住状态恢复真实进度 +- 更快定位是控制面问题、运行态问题,还是数据面问题 +- 更快把“现象冲突”收口为“语义修复”而不是无休止试错 + +## 后续建议 + +如果后面继续在这条产品线上推进,建议默认套用: + +1. 任何带部署与真验的任务:`remote-truth-closure` +2. 任何 logical group、route、shadow provider 任务:`routing-data-plane-e2e` +3. 任何“真实可用但后台显示失败”的任务:`false-negative-status-triage` + +这三者合起来,基本就是本项目后半程最有效的经验压缩。 diff --git a/docs/EXECUTION_BOARD.md b/docs/EXECUTION_BOARD.md index afee8828..eef8e0b8 100644 --- a/docs/EXECUTION_BOARD.md +++ b/docs/EXECUTION_BOARD.md @@ -1809,3 +1809,27 @@ - import batch 仍保留真实 `partially_succeeded` - provider 级状态与真实 access closure 一致,显示 `active` - account inventory 不再错误显示 `broken/failed` + +## 2026-05-30 已沉淀项目技能模板 + +**目标**:把本项目后半程最有效的做法沉淀成可复用 skills,减少后续任务中的虚假完成、控制面/数据面割裂和状态误报问题 + +**新增项目内 skills**: + +- `.agent/skills/remote-truth-closure` + - 约束 `本地门禁 -> 提交推送 -> 远端部署 -> 真实验证 -> 执行板落盘` 全链路闭环 +- `.agent/skills/routing-data-plane-e2e` + - 约束 `logical_group / route / shadow_group / managed key / host usage_logs` 的控制面 + 数据面验收 +- `.agent/skills/false-negative-status-triage` + - 约束 `provider_status / account_status / real data plane` 信号冲突时的分层诊断与语义修复 + +**配套总结文档**: + +- `docs/2026-05-30-PROJECT_LEARNINGS_AND_LOCAL_SKILLS.md` + +**本次沉淀固定的关键经验**: + +- 本地测试通过不能代表任务完成,必须以远端真实验证收口 +- public alias 尽量留在插件层,stock host 的 shadow provider 优先承载 canonical model +- 最终证据优先级固定为:真实数据面 > host usage logs > route logs > provider/inventory 投影 > probe-only 信号 +- false-negative 应通过修正状态语义解决,而不是简单隐藏失败