games-development-ai/docs/superpowers/specs/2026-06-09-王蓝莓小卖部黄金闭环-design.md
zizi 7f24a344d0 docs(agent-specs): B2 归档——64 个闭线工作记录移入 _archive/,热目录顶层 90→26
承接目录治理:上轮只压缩内容未减文件数,闭线工作记录仍平铺致目录看着仍一堆(创始人指出)。本次执行 B2 归档。

64 个 ≤06-15 闭线档(25 压缩桩 + 闭线 review/report/纪要/edit-plan)git mv 入 docs/agent-specs/_archive/(文件名不变、仍 git 跟踪可查)。热目录 ≤06-15 仅留 13 活档(决策/纲领/SoT/活spike)+13 个 06-16 在飞。

活资产 20 处旧路径引用(.agents/docs/memory/_index)同步改 _archive/,引用断裂复测=0;_index 活地图 + 治理档状态收口。约束:0 个 06-16 被移、orchestrator 等未跟踪在飞档零误纳。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-16 13:26:19 +00:00

161 lines
15 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.

<!-- /autoplan restore point: /root/.gstack/projects/zizi-al-games-development-ai/dev-2.0.0-autoplan-design-restore-20260609-084100.md -->
<!-- v2 收缩重构版:经 /autoplan CEO 双声音(Claude 子代理+Codex)评审 + 用户前提门 D1 确认。原 v1(经营全垂直)见 git history -->
# 设计 v2最小数据闭环clicker-plus 通用 runtime+ 小卖部皮肤
> 文档号HJ-DESIGN-006 日期2026-06-09 分支dev/2.0.0
> 上游:`docs/agent-specs/_archive/2026-06-09-下一阶段路线-plan.md`autoplan 三轨定稿)的 **B 轨黄金闭环**。
> 评审:/autoplan CEO 双声音收敛"收缩重构",用户前提门 D1 确认。进度底账 `docs/mvp/MVP进度总账.md`。
> 下一步:转 writing-plans。
---
## 1. 背景与动机
B 轨 = 把 1 条完整垂直闭环做真,核心是**最小数据回路遥测→quality_score→feed 排序)**。
**v1→v2 反转autoplan CEO 双声音一致)**v1 为「经营」模板专门扩 Runtime被两个独立模型判为"把可演示游戏误当平台闭环"。v2 改为:**通用 clicker-plus 数据驱动 runtime + 确定性 PackageFactory**,经营/小卖部只是**配置皮肤 + 内容样例**,不主导架构。这样同样产出"小卖部"体验,又沉淀可复用的平台生产能力,避免每品类加 Runtime 分支。
**可行性勘察实证(只读代码)**:前端 Runtime 已动态读 `gameConfig.target`/`assets`,但玩法逻辑硬编码、`manifest.entry` 从不执行;后端 aigc/runtime/telemetry 全桩feed-api 无 `FeedApi`、publish 不写 feed、`game_runtime_package` 无列存整包 JSON。
---
## 2. 目标 / 非目标
**目标:证明平台「生产→分发→采数→排序」的复用能力**(非"做一个游戏"
- 通用 clicker-plus 数据驱动 runtime + PackageFactory同一套数据化配置点击/目标/时长/可选库存商品)产出不同皮肤的游戏。
- 最小数据回路真实跑通play 事件真落库、quality_score 真算、feed 排序真读它A/B 可证),**clicker-plus 即可验,不依赖经营皮肤**。
- 小卖部皮肤 + ≥10 个参数化种子内容,让 feed 不是"两个游戏赛马"。
**非目标YAGNI** 不为单品类扩 runtime经营=配置皮肤);不做完整经营状态机;不接真实 LLM/Dify、MQ、OSS、runtime 真实编译;不做真实鉴权/多租户。
**口径收敛对外措辞CEO 双声音)**:本闭环达成 = "**数据飞轮埋点骨架 + 推荐反馈链路已跑通**"**不是**"护城河已建"(护城河要等真实创作者/玩家/反作弊/留存)。
---
## 3. 架构总览
```
[创作] studio.createDraft → project.createProject ✅已有
↓ 选 clicker-plus 模板 + 参数(点击/目标/时长/可选商品·皮肤)
[生成] aigc.generate → PackageFactory 确定性填充 → 合法 GamePackage(无LLM) 🔨桩→真
[落包] runtime.persistPackage → game_runtime_package(READY) via PackageStore 🔨新建(V10加列)
↓ manifestUrl=后端端点(PackageStore.read)
[发布] project.submitPublish 门禁 → 状态机 ✅门禁已真
[可见] 进入"可见态"(批次1定义:终态可见 + package READY 双条件) ──钩子──→ 写 feed rank 🔨FeedApi.upsertRank
[feed可见] feed.stream 读 rank + **回填本体(标题/封面/作者/packageUrl)** 🔨读端在,本体回填待补
[试玩] 前端 getRuntimePackage→manifestUrl→通用 clicker-plus runtime 🔨数据驱动小扩
[遥测] game_play_start/end(duration_ms,completed)/like/share + eventId 🔨桩→真(同步落库,经聚合服务接口)
→ /events/batch 同步写 event → upsert game_telemetry_game_stat(按天)
→ quality_score → **当日 stat 覆盖** game_feed_rank.quality_score/sort_score
[排序] feed.stream 重查 → 排序反映新 quality_score ✅读端在
```
**3 个关键决策(已修正):**
1. **feed 写入挂"可见态"**v1 误写 `APPROVE→PUBLISHED`,实际审核通过到 `APPROVED`、PUBLISHED 是另一状态Codex critical。→ 批次1 先读 `ProjectStatusEnum` + 状态机**定义 feed-eligible 态**(终态可见 AND runtime package=READY 双条件feed 写入钩子挂这里,不把不可玩游戏推进 feed。
2. **manifest=后端端点 + `PackageStore` 抽象**DB 是 MVP 实现,**V10 迁移加 `game_runtime_package.package_json LONGTEXT`(确定项,非开放项)**。退场契约manifest-from-DB 是脚手架M3 接 OSS/真实编译时整体下线,**不在其上叠功能**。
3. **quality_score**`clamp(60×完玩率 + 20×like率 + 20×share率, 0, 100)`(完玩率=completed/play_startlike/share 率截断 1.0**回灌口径=取该 game 当日 stat 覆盖 `feed_rank.quality_score`(跨天加权留 M5**(修 stat 按天 / rank 按游戏 的语义裂Codex critical`sort_score=quality_score+boost`
---
## 3.5 三段批次(数据回路 AC 与经营皮肤解耦CEO 双声音)
| 批次 | 内容 | 验收 |
|---|---|---|
| **① 契约/状态机校正** | 定义 feed-eligible 发布态 / V10 manifest 存储 / `FeedApi` 契约(含本体回填字段)/ telemetry 幂等键(eventId) / defaultZone / IP 原创名 | 契约入库、V10 迁移就绪 |
| **② 最小数据闭环clicker-plus** | PackageFactory 产 clicker-plus 包→落包→发布后入 feed→试玩→事件落库→quality_score 回灌→**A/B 排序**。**不依赖经营皮肤/runtime 扩展** | **数据回路 A/B AC 在此锁定** |
| **③ 经营皮肤 + 种子** | clicker-plus 配置出"小卖部"皮(点击售卖+极简库存)+ ≥10 参数化种子内容 | feed 有内容池;**经营皮肤可降级**(撞 <15KB 先退纯 clicker数据回路 AC 不动 |
---
## 4. 组件设计(职责 / 接口 / 依赖)
| # | 单元 | 职责 | 接口 | 依赖 |
|---|---|---|---|---|
| 1 | **clicker-plus GameConfig schema**契约 | 约束通用 clicker-plus 配置点击/目标/时长/可选商品列表/皮肤元信息 | `contracts/templates/clicker-plus.schema.json`经营= schema 的一组参数+皮肤 | game-package.schema.json |
| 2 | **PackageFactory**aigc | templateId+参数 确定性产合法 GamePackage LLM多参数批量产种子 | `getTemplateList()` 返真模板`generate` DONE 产物=骨架代入参数→校验 clicker-plus+package schema | #1project |
| 3 | **PackageStore + runtime 落包**新建 | 抽象包存储DB=MVP impl跳过真编译落 `game_runtime_package(READY)` | `PackageStore.persist/read`**V10 `package_json LONGTEXT`**`GET /app-api/runtime/manifest/{versionId}` | game_runtime_package(+V10) |
| 4 | **FeedApi.upsertRank + 本体回填**新建·填结构缺口 | feed-api `FeedApi`upsert rankfeed.stream **回填标题/封面/作者/packageUrl**否则空卡Codex high | `upsertRank(gameId,versionId,zoneId,qualityScore,boost)`stream join project 本体 | game_feed_rankproject |
| 5 | **project 可见态钩子** | 进入 feed-eligible 批次1定义后调 `FeedApi.upsertRank` 写基线分**不动门禁/状态机(D2锚点)** | 钩子挂"可见态 + package READY"双条件后 | #4 |
| 6 | **telemetry 同步落库+算分** | `/events/batch` 同步 eventupsert stat quality_score #4。**经聚合服务接口**(未来换 MQ 不改业务语义) | 替换 `dispatchToMq`**幂等键含 `eventId/clientEventId`**( ts 变化重复刷分) | event/stat #4 |
| 7 | **通用 clicker-plus runtime**前端中度扩展 | 数据驱动读 gameConfig点击/目标/时长/可选库存商品皮肤化渲染。**先量当前 build 字节余量**(防撞 <15KB) | `startRuntime`上报 `game_play_start`/`game_play_end`(duration_ms,completed)/`like`/`share`+有效 traceId+eventId | gameConfig(#1)、SDK |
| 8 | **6 开工前置项 + beacon/tenant**前端 | VITE_API_BASE / mock 门控 / token=test1+tenant-id / **sendBeacon 走 baseURL**(否则绕过) / 种子 tenant_id=1 / vite dev | | |
**upsertRank 列级语义消歧Codex high**project 钩子写 `quality_score=COALESCE(existing, baseline)`不下调telemetry `quality_score=新值, sort_score=新值+boost`**必须能覆盖**)。"可见先于试玩"正常无竞争此为安全网
---
## 5. 数据流 + A/B 验收
**主链路**创作PackageFactory clicker-plus PackageStore 落包(READY)→submitPublish 门禁进可见态钩子写 feed rankfeed.stream(回填本体)可见前端 clicker-plus runtime 试玩上报事件(eventId+traceId)→同步写 eventupsert 当日 stat quality_score当日覆盖 feed_rank重查 feed 排序变化
**A/B 验收(数据回路 AC批次②clicker-plus 即可Codex critical 协议)**备同 zone boost A/B 两个已"可见"clicker-plus 游戏 记初始 feed 顺序 只向 B 上报有效 `game_play_start+game_play_end(completed=true)+like+share` eventId)→ 断言 `game_telemetry_event` 有原始行当日 `stat.quality_score` 变大`feed_rank.sort_score` 变大 重查 feed **B 排到 A 前** **同 eventId 重发不重复计数** mock 仍通过 **feed 卡片本体非空**(标题/封面真回填)。
---
## 6. 错误处理
| 失败点 | 处理 |
|---|---|
| PackageFactory 产物 schema 不合法 | task FAILED不落包studio 链态 FAILED前端提示 |
| 包不存在(NOT_READY) | 前端走 demo 兜底——但黄金闭环要真包落包失败=闭环断,**登记缺口**(不靠兜底掩盖) |
| **未到可见态/package 未 READY** | **不写 feed**(双条件)防不可玩游戏进流 |
| feed 卡片本体回填失败 | 缺本体的 rank 行不展示或降级占位**不允许空卡冒充可见** |
| feed rank 并发(可见钩子 vs telemetry) | 列级语义分离4)钩子不下调telemetry 权威覆盖 |
| telemetry eventId 缺失/重复 | eventId eventId 幂等去重( ts 变化重复刷分) |
| traceId | 后端拒(已有)前端必生成 |
| mock token 401/加密/跨域 | autoplan 已覆盖 |
---
## 7. 测试与验收
- **批次 A/B 验收**(§5)=数据回路 ACclicker-plus 即可与经营皮肤解耦
- **单元测试**:① PackageFactory(合法/非法参数验产物 schema + 批量产种子)② PackageStore(/读整包 JSON)③ FeedApi.upsertRank(给分验 sort_score+幂等+本体回填)④ telemetry( play_start/end stat 累加+quality_score 公式+eventId 幂等+ feed)⑤ project 可见态钩子(到可见态 FeedApi未到不调)⑥ clicker-plus runtime( config 验点击/目标/时长/库存)。
- ** agent 独立复跑**(铁律)。
- **完成判据**批次 A/B 全绿 + 单元绿 + feed 本体非空 + 浏览器肉眼演示
---
## 8. 边界 / 回滚 / 风险
- **改动边界**不动 project 门禁/状态机(D2锚点)、不动 feed 读端排序逻辑不接 MQ/OSS/真编译/ LLM**telemetry 走聚合服务接口包走 PackageStore**( MQ/OSS 不改业务语义)。
- **回滚单元 3 批次各自 commit**:①契约+V10 PackageFactory/PackageStore/FeedApi/可见钩子/telemetry 同步 clicker-plus runtime+经营皮肤+种子后端非零改动回滚=按单元 revert + cleanup SQL
- **数据污染清理**固定 traceId/eventId 前缀 + 固定 gameId 清单 + cleanup SQL + 表快照
- **风险**:① clicker-plus runtime <15KB缓解先量字节余量经营皮肤可降级退纯 clicker数据回路 AC 不动)② manifest-from-DB 沉淀成债缓解PackageStore 抽象+退场契约)③ quality_score 低样本易刷缓解MVP 接受置信度/去重/反作弊留 M5对外口径不夸大)。
---
## 9. 开放项 / 依赖(批次①解决)
- **发布态定义** `ProjectStatusEnum` + 状态机确定 feed-eligible APPROVED 即可见还是 APPROVED 后再 publish PUBLISHED+ package READY 双条件
- **V10 迁移**确定项`game_runtime_package.package_json LONGTEXT`注明大小上限与超限处理)。
- **defaultZone**feed 默认专区 zoneId project game_zone 或约定常量)。
- **IP**种子内容用**原创换皮**"蓝莓妹的小卖部"/自造不用真实"王蓝莓"IP撞自家 ip/compliance 风门对外材料有侵权尾险"王蓝莓"仅内部代号
- **种子供给**:≥10 参数化种子PackageFactory 批量产feed 内容池与上游 plan §2.D 对齐
---
<!-- AUTONOMOUS DECISION LOG -->
## Decision Audit Trailautoplan · design review
| # | 阶段 | 决策 | 分类 | 原则 | 理由 | 否决项 |
|---|---|---|---|---|---|---|
| 1 | CEO | 运行 Claude 独立 CEO 子代理 + Codex CEO 声音 | Mechanical | P6 | 双声音对抗评审(codex 已就绪) | 仅 subagent |
| 2 | CEO | **设计形态:收缩重构** | **USER-GATED(前提门 D1)** | P1+P5 | 两模型一致;用户确认通用 clicker-plus+皮肤 | 保留经营-specific runtime |
| 3 | CEO | 通用 clicker-plus 数据驱动 runtime + PackageFactory(经营=皮肤) | Taste→采纳 | P5 | 避免每品类扩 runtime 分支爆炸,沉淀复用能力 | 为 business 单独扩 runtime |
| 4 | CEO | feed 写入挂"可见态+package READY"双条件 | Mechanical | P5 | 修 APPROVE≠PUBLISHED 状态机错(Codex critical) | 挂 REVIEWING/错态 |
| 5 | CEO | V10 加 package_json LONGTEXT(确定项) | Mechanical | P5 | 现表无列存整包 JSON包存 DB 必需(Claude/Codex critical) | 标"实现时确认" |
| 6 | CEO | quality_score 回灌=当日 stat 覆盖 rank | Mechanical | P5 | 修 stat 按天/rank 按游戏语义裂(Claude/Codex) | 一次性 upsert 不定口径 |
| 7 | CEO | telemetry 幂等键含 eventId/clientEventId | Mechanical | P1 | 防 ts 变化重复刷分(Codex high) | 仅 traceId |
| 8 | CEO | feed.stream 回填本体(标题/封面/作者/packageUrl) | Mechanical | P1 | 防空卡 demo 露馅(Codex high) | 只读 rank |
| 9 | CEO | 抽 PackageStore + telemetry 聚合服务接口 + 退场契约 | Taste→采纳 | P5 | 换 MQ/OSS 不改业务语义;防 DB-JSON 永久债 | DB/同步写死长期架构 |
| 10 | CEO | IP 原创换皮(非真王蓝莓) | Mechanical | P4 | 撞自家 ip 风门+对外侵权尾险 | 真实王蓝莓做招牌 |
| 11 | CEO | 拆 3 段批次(数据回路 AC 与经营皮肤解耦) | Taste→采纳 | P3 | clicker-plus 即可验 A/B经营皮肤可降级 | 单批次绑死 |
| 12 | CEO | 对外口径=埋点骨架/反馈链路(非护城河) | Mechanical | P5 | 2 游戏少量遥测不证护城河 | 夸大为护城河已建 |
| 13 | — | Design/DX 阶段跳过 | Mechanical | P3/P6 | UI 项 0 命中;内部模块 API 非开发者产品 | 跑 Design/DX |