diff --git a/docs/architecture/产品/需求模块映射.md b/docs/architecture/产品/需求模块映射.md index dee00c37..a0681a55 100644 --- a/docs/architecture/产品/需求模块映射.md +++ b/docs/architecture/产品/需求模块映射.md @@ -286,6 +286,7 @@ flowchart LR > 这是一次**逐条读码核实**的完成度快照(2026-06-17,基准 `origin/dev/2.0.0`,两路 Opus forensic 核 155 功能)。口径:✅ 真端到端可验收 · 🟡 有壳/半真/部分接线 · 🔴 未建/纯桩。 > **注意**:这是某一时点的快照,会过期;**实时模块进度以 [`docs/mvp/MVP进度总账`](../../mvp/MVP进度总账.md) §2 矩阵为唯一 SoT**;13 个技术模块的逐模块状态见[架构域](../架构/13模块.md)。本节只保留产品功能侧(155 项)的快照,因为它是 MVP 进度总账之外独有的数据。 +> **⚠️ 06-18 plan002 后增量(快照之后落地,以下计数已就近回填)**:`P-OPN-08`(创作者公开聚合 API `GET /app-api/project/public/creator/{id}`,@PermitAll·仅 status==4·无 PII,后端单测绿+对抗评审 SHIP,`8238bf2d`)与 `P-ACC-03`(适龄徽标 `AgeRatingBadge.vue`,详情/我的项目/创作者主页/play 已渲,`1ebedf29`;feed 卡 `ageRating` 字段=待 additive 补)均已落地,口径=**代码真+mock+评审,真 e2e 验=open**,故已从 🔴 上移至 🟡(未达 ✅)。实时以 MVP进度总账 §2 为准。 ### 按域汇总(155 项产品功能) @@ -308,15 +309,15 @@ flowchart LR | 15 消息通知 NTF | 7 | 4 | 0 | 3 | 通知底座真(四类挂点全通);社交/赛事类型缺 | | 16 IP孵化版权 IPX | 13 | 0 | 0 | 13 | 整域几乎全空 | | 17 B端定制 BIZ | 14 | 3 | 4 | 7 | 核心四步真(表单→报价→进度→验收);增值服务全缺 | -| 18 运营管理 OPN | 9 | 2 | 4 | 3 | 审核主链真;限曝光/导出/经营看板缺 | -| 19 账号合规 ACC | 5 | 0 | 4 | 1 | 普遍半真(壳在内容缺) | -| **合计** | **155** | **18** | **~42** | **~95** | 真端到端 ✅ 仅 18,且**全部落在 P0** | +| 18 运营管理 OPN | 9 | 2 | 5 | 2 | 审核主链真;P-OPN-08 公开聚合 API 06-18 落地(🟡);限曝光/导出/经营看板缺 | +| 19 账号合规 ACC | 5 | 0 | 5 | 0 | 普遍半真(壳在内容缺);P-ACC-03 适龄徽标 06-18 落地(🟡) | +| **合计** | **155** | **18** | **~44** | **~93** | 真端到端 ✅ 仅 18,且**全部落在 P0**(🟡/🔴 含 06-18 plan002 后 P-OPN-08·P-ACC-03 上移) | -### 55 项 P0 精确口径(18 ✅ / 18 🟡 / 19 🔴) +### 55 项 P0 精确口径(18 ✅ / 20 🟡 / 17 🔴 | 06-18 plan002 后:P-OPN-08·P-ACC-03 由 🔴→🟡) - **✅ 18 真端到端**:P-CRT-08(实时预览)、P-CRT-12(进度展示)、P-PLZ-03(点封面即玩)、P-FED-02(滑动切换)、P-FED-03(赞)、P-FED-04(藏)、P-FED-08(分享落地页)、P-FED-11(首屏封面)、P-INC-01(新人现金)、P-NTF-01(站内消息中心)、P-NTF-02(生成完成通知)、P-NTF-03(审核结果通知)、P-NTF-05(收益变动通知)、P-BIZ-01(需求表单)、P-BIZ-03(定制进度看板)、P-BIZ-04(交付验收)、P-OPN-02(拒绝反馈重提交)、P-OPN-03(精选池管理)。 -- **🟡 18 部分**:P-TPL-03、P-CRT-01(一句话生成,代码真但出包依赖部署)、P-CRT-04、P-CRT-09、P-CRT-13、P-LIC-06、P-PUB-03、P-PLZ-01、P-FED-01(竖屏即玩,默认 mock 喂数)、P-FED-05/06/07/10、P-FED-13(推荐池游标桩)、P-FED-14、P-OPN-01/04/05。 -- **🔴 19 缺失**:P-TPL-01、P-CRT-02、P-CRT-10、P-CRT-11(仅 mock)、P-LIC-05、P-PUB-01、P-WAL 渠道字段、P-BIZ-08/11/12、P-OPN-08、P-ACC-02/03、P-PAY-01 等。 +- **🟡 20 部分**:P-TPL-03、P-CRT-01(一句话生成,代码真但出包依赖部署)、P-CRT-04、P-CRT-09、P-CRT-13、P-LIC-06、P-PUB-03、P-PLZ-01、P-FED-01(竖屏即玩,默认 mock 喂数)、P-FED-05/06/07/10、P-FED-13(推荐池游标桩)、P-FED-14、P-OPN-01/04/05、**P-OPN-08(06-18 落地:公开聚合 API 代码真+mock+评审,真 e2e=open)、P-ACC-03(06-18 落地:适龄徽标已渲,feed 卡字段待补)**。 +- **🔴 17 缺失**:P-TPL-01、P-CRT-02、P-CRT-10、P-CRT-11(仅 mock)、P-LIC-05、P-PUB-01、P-WAL 渠道字段、P-BIZ-08/11/12、P-ACC-02、P-PAY-01 等。 > 一句话:**"能生成一个能玩、能发、能刷到、能互动、能记一笔账"的最小闭环已成立**(18 个真 ✅ 全在 P0);最大缺口=生成侧"已证未上产线"+ 玩法模板未建 + 合规检测全桩 + 变现受日历闸门 + 素材/IP/社交三大域近空白。完整优先级分层见[架构域路线](../架构/README.md)与 `docs/mvp/MVP进度总账`。 diff --git a/docs/architecture/前端/README.md b/docs/architecture/前端/README.md index 630909be..986e5388 100644 --- a/docs/architecture/前端/README.md +++ b/docs/architecture/前端/README.md @@ -94,7 +94,7 @@ flowchart TD "token 两层"指的是**原始层(primitive)→ 语义层(semantic)** 的分离,组件层(component)是按需追加的第三层。 -- **原始层**只描述"物理事实":`--c-cyan` 是某个青色、`--sp-3` 是 12px。它不带含义,只是调色板和尺子。 +- **原始层**只描述"物理事实":`--cyan` 是某个青色、`--sp-3` 是 12px。它不带含义,只是调色板和尺子。 - **语义层**描述"用途":`--bg` 是页面背景、`--accent` 是强调色、`--danger` 是危险色、`--surface-1..3` 是从底到顶的层叠表面。组件**只准引用语义令牌**,绝不直接碰原始层。 这样分层带来一个关键好处:**换肤时零改组件**。主题切换只需在语义层重新指向不同的原始色(比如暗色主题下 `--bg` 指向深色、浅色主题下指向浅色),组件因为只认 `--bg` 这个语义名,会自动跟着变,一行组件代码都不用动。 @@ -128,7 +128,7 @@ token 还承担一个长期使命:**做跨端的单一事实源**(single source 1. **响应式优先消费级 Web**。否决 demo 的桌面侧栏控制台范式;移动端沉浸、桌面端居中放大,一套组件适配两端。 -2. **暗色先行 + 设置内多档舒适主题可切**(暗 / 浅 / 柔和三档)。实现方式是在语义层用 `[data-theme]` 属性做覆盖,用 `localStorage` 持久化用户选择,首次进入跟随系统的 `prefers-color-scheme`(浏览器暴露的"用户偏好深色还是浅色"信号)。 +2. **暗色先行 + 设置内多档舒适主题可切**(暗 / 浅 / 柔和三档)。实现方式是在语义层用 `[data-theme]` 属性做覆盖,用 `localStorage` 持久化用户选择;**首次进入默认暗色**(`:root`,不写 `data-theme`),之后由用户在设置内显式切换。(跟随系统 `prefers-color-scheme` 信号是远期增强,当前尚未接入——代码只读 `localStorage`,无持久化值时一律回落暗色。) 3. **SVG 图标取代 Unicode/emoji**,取向 lucide(一套开源的线性 SVG 图标库)。 @@ -146,7 +146,7 @@ token 还承担一个长期使命:**做跨端的单一事实源**(single source 旧令牌(`--cyan`/`--green`/`--radius`/`--shadow` 等)全部保留,其中 `--cyan` 等被设为新语义令牌 `--accent` 的别名,对现有引用零破坏。新增三组: -- **primitive 原始层**:`--c-cyan/green/pink/amber/violet/red`、灰阶 `--c-ink-0..3`、以及一对"在彩色背景上的前景色"`--c-on-accent:#061014`、`--c-on-danger:#2a0608`。 +- **primitive 原始层**:原色板 `--cyan/--green/--pink/--amber/--danger/--violet`,以及一对"在彩色背景上的前景色"`--on-accent:#061014`、`--on-danger:#2a0608`。 - **semantic 语义层**:`--bg`、`--surface-1..3`、`--accent`、`--success`、`--warning`、`--danger`、`--border-1..2`、品牌渐变 `--grad-primary`、热区渐变 `--grad-hot`、焦点环 `--focus-ring`。 - **尺度令牌**:间距 `--sp-1..6 = 4/8/12/16/22/32`、圆角 `--radius-xs..xl = 4/6/8/12/20`(默认 `md`)、阴影 `--elev-1..3`、字号 `--fs-h1/h2/h3/body/caption`、字重 `--fw-*`。 @@ -154,7 +154,7 @@ token 还承担一个长期使命:**做跨端的单一事实源**(single source ### 6.2 组件契约 -`AppButton` 的 props 保持不变(`type/size/block/loading/disabled`),向后兼容;但 primary(主)按钮恢复了品牌的签名渐变(`--grad-primary` + `--fw-cta` 字重 + `--on-accent` 前景),并补齐全部交互态:`focus-visible` 焦点环、`disabled` 时 0.42 透明度、`active` 时 scale 0.97 的按压反馈。`Icon` 组件**禁用 emoji**。 +`AppButton` 的 props 保持不变(`type/size/block/loading/disabled`),向后兼容;但 primary(主)按钮恢复了品牌的签名渐变(`--grad-primary` + `--fw-cta` 字重 + `--on-accent` 前景),并补齐全部交互态:`focus-visible` 焦点环、`disabled` 时 0.5 透明度、`active` 时 scale 0.98 的按压反馈。`Icon` 组件**禁用 emoji**。 ### 6.3 i18n 契约 diff --git a/docs/architecture/后端/README.md b/docs/architecture/后端/README.md index c2dfecb1..1d915c76 100644 --- a/docs/architecture/后端/README.md +++ b/docs/architecture/后端/README.md @@ -75,7 +75,7 @@ flowchart TB - **包名统一**:所有业务代码都在 `com.wanxiang.huijing.game.module.{模块}.{层}` 之下(例如 `...game.module.project.service`)。这条命名规则也是端前缀自动生效的前提——控制器按包路径 `**.controller.app/admin.**` 通配,Huijing 框架据此自动给上 `/app-api`、`/admin-api` 两个端前缀,控制器代码本身零改。 - **两段式模块结构**:每个 game 模块拆成 `-api` 与 `-server` 两个 Maven 子模块。`-api` 只放对外契约面——枚举、错误码常量、跨模块 DTO 与 Feign 接口;`-server` 放真正的实现——controller(app/admin 双端)、service、dal(DO/Mapper)、convert。跨模块只能依赖对方的 `-api`,不能直接碰 `-server`,这是低耦合的硬边界。 -- **错误码分段**:每个模块独占一段错误码区间(例如 project 占 1–100,Wave1 闭环脊柱模块占 100–104),不重叠。完整分配表在 `.agents/rules/engineering-conventions.md §1.3`。 +- **错误码分段**:错误码格式为 `1-{模块段}-***-***`,每个模块独占一段、互不重叠(例如 project 占段 100,Wave1 闭环脊柱 4 模块 aigc/runtime/feed/telemetry 顺延占段 101–104)。完整分配表在 `.agents/rules/engineering-conventions.md §1.3`。 - **契约不放后端**:API/DB/SDK/event 等 8 类跨端契约的单一事实源是仓根的 `contracts/`,后端只引用它、不在模块里另立一份。数据库 schema 的源在 `contracts/db-schemas/`,Flyway 执行副本放在 `huijing-server/.../db/migration/`(两边 diff 必须一致,因为 Flyway 对校验和敏感)。 - **物理形态 = 单体**:13 个模块是**逻辑划分**,物理上全部以 jar 聚合进 `huijing-server` 单体进程运行(monorepo 先行、后续再拆独立仓)。Nacos、RocketMQ 等是框架自带的远期形态,MVP 阶段并未部署。 - **技术栈基线**:Java 17 + Spring Cloud Alibaba + MySQL 8.0 + Redis 7 + Flyway;生成主线是便宜 LLM(如 DeepSeek / MiniMax)经 new-api 网关(一个 OpenAI 兼容的多模型 LLM 网关)直出,配合 SAA(Spring AI Alibaba)裸图编排——这部分的现行架构归架构域的[生成引擎](../架构/生成引擎/)子文档,不在后端域展开。 diff --git a/docs/architecture/架构/13模块.md b/docs/architecture/架构/13模块.md index d53476ff..96485a06 100644 --- a/docs/architecture/架构/13模块.md +++ b/docs/architecture/架构/13模块.md @@ -317,7 +317,7 @@ community 承载**社交关系、互动计数、排行 / 成就计算与全渠 > 动态扇出(fan-out)= 创作者发动态时把它推送到所有粉丝的时间线;APNs / FCM = 苹果 / 谷歌的推送服务。 > -> **现在建到哪了**:✅ 完成(MVP 裁剪后的范围)。通知底座 + 等级引擎是真的,三个上游(生成 / 审核 / 收益)的通知挂点全通,22 个单元测试。需要说明的是**排行榜 / 成就引擎根本没建**(MVP 有意裁剪),多级 / 多通道也未建。 +> **现在建到哪了**:✅ 完成(MVP 裁剪后的范围)。通知底座 + 等级引擎是真的,三个上游(生成 / 审核 / 收益)的通知挂点全通,22 个单元测试。后续 plan002(U3,commit `3f35acb4`,Flyway V23)又补齐了**评论 CRUD + 关注 + 排行 Redis ZSET(排行真算:`afterCommit` 写 ZSET + `rebuildFromDb` 对账保 ZSET↔DB 一致)+ 弹幕 WS**,再叠 35 测(共 57 绿)。真缺口收窄为:**成就引擎(achievement)仍未建**(MVP 有意裁剪)、弹幕多实例(`sender-type=redis`)与多通道未建、举报转 compliance 受理的 -api 待交付。口径与 `docs/mvp/MVP进度总账.md` 对齐。 ### 3.10 ip — 素材安全 / 授权 / IP 风格原子 扩 @@ -337,7 +337,7 @@ ip 为素材和 IP(知识产权)资产提供**安全可信、授权可溯、风 > 授权链 = 一份素材"谁授权给谁、能用在什么范围"的可追溯链条;**T-IP-04 是锁风门两大原料之一**(另一个是 aigc 的 T-AGC-19)。 > -> **现在建到哪了**:◻ seam(接缝寄宿)。ip **有意不独立建模块,而是寄宿在 compliance 里**。当前风格原子是桩,素材安全 / 授权链 / 盗用监测全未建(属远期)。 +> **现在建到哪了**:◻ seam(接缝寄宿)。ip **有意不独立建模块,而是寄宿在 compliance 里**。当前风格原子是桩,ip 模块自身的**素材安全扫描 / 授权链 / 盗用监测原子全未建**(属远期)。注:面向用户的**素材浏览 / 选用 / 上传最小后端不在 ip、而由 studio 域承载**(plan002 U6,`game_material` 表 V24),别误读成"素材相关后端零代码"。 ### 3.11 compliance — 内容安全 / 审核 / 锁风门 扩 @@ -421,7 +421,7 @@ ad 把**联盟接入、广告位 AI 植入、曝光计费、eCPM 优化与归因 | 5 | **telemetry** 遥测 | ✅ 完成 | 唯一真端到端数据底座:事件落库 + quality 真算分 + 日聚合 upsert + 创作者 stats | MQ 异步聚合 = 桩(有意);广告营收字段占位 | | 6 | **ad** 广告 | ✅ 完成 | 计费全链真(合规 → 幂等 → 归因 → 台账)+ 验签 fail-fast,24 单测 | 真联盟 SDK(穿山甲 / 优量汇)= 桩,受广告审核闸门 mock-gated | | 7 | **trade** 资金 | ✅ 完成 | 资金状态机真(逐笔入账 + 冻结 CAS + 对账补偿),41 单测;打款 fail-fast 防假钱 | 真 pay 对接 = 桩,受支付进件闸门 mock-gated | -| 8 | **community** 社区 | ✅ 完成 | 通知底座 + 等级引擎真,3 上游 notify 挂点全通,22 单测 | 排行榜 / 成就引擎根本没建(MVP 裁剪);多级 / 多通道未建 | +| 8 | **community** 社区 | ✅ 完成 | 通知底座 + 等级引擎真,3 上游 notify 挂点全通;plan002 又补评论 / 关注 / 排行 Redis ZSET / 弹幕 WS(57 单测) | 成就引擎仍未建(MVP 裁剪);弹幕多实例(redis)/多通道未建;举报转 compliance 受理 -api 待交付 | | 9 | **studio** 工作室 | 🟡 部分 | 创作编排委托层真(草稿装配 + aigc 接缝 + 血缘) | "7 步生成链"不在 studio(在 aigc SAA 图);六资产 / 角色 rig / 对白树 / 可视化全桩 | | 10 | **compliance** 合规 | 🟡 部分 | 锁风门框架 + 真注入发布链 + RBAC 真 | 核心检测原子全桩恒 pass(风格 / IP / 内容安全)→ 发布链零自动拦截,纯人工兜底 | | 11 | **biz** B 端 | 🟡 部分 | lead 状态机 + 报价落库真,13 单测 | 模板硬编码 4 个(非 32 套);报价引擎 / 签章 / CRM 纯未建 | @@ -432,7 +432,7 @@ ad 把**联盟接入、广告位 AI 植入、曝光计费、eCPM 优化与归因 几条值得单独记住的判断: -- **地基稳**:单体真启、Flyway(数据库迁移)V1–V17 全绿、12 份契约 yaml 锁定、project 真原子跨表发布、telemetry 真闭环——脊柱可承重,不存在 split-brain(指"代码两套各跑各的、互不一致"的脑裂状态)。 +- **地基稳**:单体真启、Flyway(数据库迁移)V1–V25 全绿(06-17~06-18 又叠了 V18 源项目表 / V19 aigc modify / V20 uk / V21 trade 订阅 / V22 compliance 政策+申诉 / V23 community 社交 / V24 素材 / V25 feed 限曝光)、12 份契约 yaml 锁定、project 真原子跨表发布、telemetry 真闭环——脊柱可承重,不存在 split-brain(指"代码两套各跑各的、互不一致"的脑裂状态)。 - **生成主线单独评 🟡(护城河关键路径)**:W-G1 worker 已实证 HJ-GEN-001 成立(便宜模型在 LittleJS 插件库里写出可真玩的轻游戏,经 7 道 CDP 真机真玩验证,单款成本 ¥0.01–0.06,远低于 ¥0.15 的成本闸)。但 worker 尚未接为默认产线,玩法模板未建,插件库还有 4 项短板(文本 HUD / grid / CCD / drag)。 - **三处合规与变现的"逻辑已真、卡在闸门"**:ad / trade 的业务逻辑都已是真的、有几十个单元测试,但真广告联盟 / 真支付渠道被 mock 挡着——卡的不是代码,而是 ICP 备案、支付进件、广告审核这类**不可压缩的日历闸门**(必须等外部审批的时间)。策略是先把逻辑建好,闸门到位即接。 diff --git a/docs/architecture/架构/README.md b/docs/architecture/架构/README.md index 0cb3eef9..304682a3 100644 --- a/docs/architecture/架构/README.md +++ b/docs/architecture/架构/README.md @@ -91,7 +91,7 @@ flowchart TB ```mermaid flowchart LR subgraph 现行["✅ 现行主线(已实测)"] - A1["创作者 Prompt"] --> A2["SAA 裸 StateGraph 编排
11 节点 / 4 条件边"] + A1["创作者 Prompt"] --> A2["SAA 裸 StateGraph 编排
16 节点 / 7 条件边"] A2 --> A3["new-api 网关
OpenAI 兼容 · 多模型"] A3 --> A4["便宜 LLM
DeepSeek-v4 / MiniMax-M2.7·M3"] A4 --> A5["harness 九门兜底
校验 / 构建 / 真玩"] @@ -107,9 +107,9 @@ flowchart LR - **new-api 网关**:一个自部署的 LLM 网关,对外提供 OpenAI 兼容接口,对内可挂多个模型通道。它让"换模型/多通道兜底"变成网关层的配置事,业务代码无感;且单 key 自动入 `newapi_cost` 计费平面,成本可对账。接入时有个工程坑:baseUrl 要剥掉末尾的 `/v1`。 - **harness 九门**:生成产物要真正"能玩"才算数,所以在生成链路后端串了九道确定性门(校验 → 构建 → 真玩),**done 由这些确定性门判定,不让 LLM 给自己打分**。门不过就不出包。 -- **SAA 图的形状**:11 个节点 + 4 处条件边,主链是 `START → render → design → generate → validate → scaffold → build → play → player → emit → END`,validate 不通过则走 `repair → generate` 回环修复,修不好则 `giveup`。唯一布线源是 `SaaStudioGraph.assemble()`,生产派发与回归测试共用同一份,避免布线漂移。 +- **SAA 图的形状**:16 个节点 + 7 处条件边,主链是 `START → render → classify → design → generate → validate → scaffold → asset → build → play → player/nreview → emit → END`,validate / build / play / player 任一不通过则走 `repair → generate` 回环修复;连续失败到升档窗则 `escalate` 升 stage2 强档,救场轮耗尽才 `giveup`(这条 `repair → escalate → giveup` 就是救场阶梯)。唯一布线源是 `SaaStudioGraph.assemble()`,且同一份 assemble 同时服务 iife(factory)与 gameDefinition 两种 sourceMode、生产派发与回归测试共用,避免布线漂移。 -> 演进的更深细节(16/11 节点拓扑、加节点方法、checkpoint 框架坑、观测、dispatcher 契约)在子文档[生成引擎](生成引擎/)与 `.agents/skills/saa-graph-orchestration.md`。 +> 演进的更深细节(16 节点拓扑、加节点方法、checkpoint 框架坑、观测、dispatcher 契约)在子文档[生成引擎](生成引擎/)与 `.agents/skills/saa-graph-orchestration.md`。 ### 2.3 游戏运行时引擎 = LittleJS 增强发行版(Tier1)+ Cocos(Tier2/3) @@ -255,14 +255,14 @@ sequenceDiagram participant PRJ as project 模块 C->>S: 输入 Prompt + 选风格 - S->>GW: POST /app/aigc/generate + S->>GW: POST /app-api/aigc/generate GW->>AIGC: 转发(鉴权通过) AIGC->>AIGC: 创建生成任务(GenerationDispatcher 派发) AIGC-->>S: 202 Accepted {taskId} S->>S: 轮询/SSE 监听任务状态 AIGC->>SAA: dispatch(job) 进入裸图编排 - SAA->>SAA: 节点:render→design→generate(11 节点/4 条件边) + SAA->>SAA: 节点:render→classify→design→generate(16 节点/7 条件边) SAA->>NEWAPI: 各节点经 OpenAI 兼容接口调模型 NEWAPI->>LLM: 转发(单 key → 自动入 newapi_cost 计费) LLM-->>NEWAPI: 返回 GameConfig / 游戏代码 @@ -400,7 +400,7 @@ erDiagram | 文档 | 回答什么 | |---|---| -| [生成引擎](生成引擎/) | 生成主线的深层架构:SAA 16/11 节点拓扑、加节点方法、new-api 接入、checkpoint 框架坑、dispatcher 契约、九门 harness | +| [生成引擎](生成引擎/) | 生成主线的深层架构:SAA 16 节点拓扑、加节点方法、new-api 接入、checkpoint 框架坑、dispatcher 契约、九门 harness | | [前端域](../前端/) | game-studio / game-admin 的前端设计体系、组件分层、SDK 源码组织、运行时容器 | | [后端域](../后端/) | 后端模块的实现级设计、API 路径规范、错误码分配、Flyway 迁移、契约对齐 | | [运维域](../运维/) | 环境/部署/staging 运维、构建门、smoke 门、运行时打包与多渠道导出手册 | diff --git a/docs/architecture/架构/生成引擎/OpenGame对照.md b/docs/architecture/架构/生成引擎/OpenGame对照.md index b4074bb8..fd5468f4 100644 --- a/docs/architecture/架构/生成引擎/OpenGame对照.md +++ b/docs/architecture/架构/生成引擎/OpenGame对照.md @@ -324,7 +324,7 @@ OpenGame 的 shell 执行是**重型**的:PTY 优先(node-pty 加 @xterm/headles ### 3.1 第一类:设计可直接抄进 SAA 节点(价值最高) -物理优先分类的系统提示(含易错例)加五 archetype 体系,本质就是一个 classify 节点加 JSON 容错解析,可以直接照搬。GDD 的"六节每节映射下游"契约加三铁律加按 archetype 动态拼三层规则,**是 OpenGame 最值钱的产物**——它把开放问题结构化成填空题,这正是我们用便宜模型卡 80% 成功率门最需要的杠杆,做成一个 design 节点,内置规则可以整段移植。确定性 bitmask 贴图是纯算法,与模型无关,直接搬。smart_edit 的三级匹配加 LLM 自纠错对便宜模型尤其必要,务必移植(虽然我们走 gameDefinition 结构化源会弱化纯文本编辑的需求,但 modify/repair 节点里仍用得上)。 +物理优先分类的系统提示(含易错例)加五 archetype 体系,本质就是一个 classify 节点加 JSON 容错解析,可以直接照搬。GDD 的"六节每节映射下游"契约加三铁律加按 archetype 动态拼三层规则,**是 OpenGame 最值钱的产物**——它把开放问题结构化成填空题,这正是我们用便宜模型卡 80% 成功率门最需要的杠杆,做成一个 design 节点,内置规则可以整段移植。确定性 bitmask 贴图是纯算法,与模型无关,直接搬。smart_edit 的三级匹配加 LLM 自纠错对便宜模型尤其必要,务必移植(虽然我们走 gameDefinition 结构化中间表示会弱化纯文本编辑的需求,但 modify/repair 节点里仍用得上)。 这里有个**范式级前提必须点破**:OpenGame 整条链能跑,根本前提是它有一套预建 Phaser 模板和每个 archetype 的 `template_api.md` hook 清单当"填空靶子"。**Hook Integrity 这条铁律之所以能约束便宜模型,是因为有一份明确的 API 清单让模型不能编造。** 我们要复刻,就必须**先有等价物:一份"LittleJS 增强发行版 + 插件库公开 API 清单"当我们的 `template_api`。** 没有这个,便宜模型一定会编造 API。这一块 OpenGame 抄不来、必须我们自建——而它恰好和创始人 2026-06-17 定的"游戏 = 长生命周期结构化源项目"基座、以及"玩法模板 = 品类框架"的定位是同一个东西。 @@ -406,4 +406,4 @@ flowchart TB --- -> **验证状态**:本文档为架构对照参考文档,由一份已评审源档(`2026-06-20-OpenGame对照分析与复刻缺口.md`,该档由 5 个 agent 分片深读 clone 下来的 OpenGame 真源码后综合)重写而成,未改任何代码。承重硬事实——OpenGame = Gemini-CLI→Qwen-Code 二次 fork 的三处铁证、四原子工具 + 六阶段 SOP、三铁律(Config-First/Zero Custom Code/Hook Integrity)、`MAX_TURNS=100`、Debug Skill 加权阈值(0.5/0.35/0.15,阈值 0.8)与重复 3 次升格、stability=min(1,项目数/5)、三大支柱中仅 Game Skill 是真代码而 GameCoder-27B 与三轴 VLM Bench 只在 README、我方 SAA 16 节点 / 九门 / 80% 门 / gamedef 双证、三处复刻缺口与四类取舍——均沿用源档已抽查属实的结论;品牌已统一为"绘境AI"。 +> **验证状态**:本文档为架构对照参考文档,由一份已被《生成主线架构演进路线》吸收的源档(`2026-06-20-OpenGame对照分析与复刻缺口.md`,status 为"分析 · reference",该档由 5 个 agent 分片深读 clone 下来的 OpenGame 真源码后综合)重写而成,未改任何代码。承重硬事实——OpenGame = Gemini-CLI→Qwen-Code 二次 fork 的三处铁证、四原子工具 + 六阶段 SOP、三铁律(Config-First/Zero Custom Code/Hook Integrity)、`MAX_TURNS=100`、Debug Skill 加权阈值(0.5/0.35/0.15,阈值 0.8)与重复 3 次升格、stability=min(1,项目数/5)、三大支柱中仅 Game Skill 是真代码而 GameCoder-27B 与三轴 VLM Bench 只在 README、我方 SAA 16 节点 / 九门 / 80% 门 / gamedef 双证、三处复刻缺口与四类取舍——均沿用源档已抽查属实的结论;品牌已统一为"绘境AI"。 diff --git a/docs/architecture/架构/生成引擎/README.md b/docs/architecture/架构/生成引擎/README.md index fdf13e10..5215f5c7 100644 --- a/docs/architecture/架构/生成引擎/README.md +++ b/docs/architecture/架构/生成引擎/README.md @@ -14,7 +14,7 @@ 这台机器有三个互相支撑的设计支点,理解了它们就理解了整条线为什么这么搭: -- **便宜模型 + 门兜底,而不是训一个专用大模型。** 模型这一层硬编码了 11 个便宜的通用模型(以 deepseek-v4-flash 打底),没有任何一个是为游戏代码专门训练过的。质量缺口不靠把模型做重来补,而靠模板约束和验收门来补。这是成本策略,也是差异化判断——大模型迟早会追上,真正的护城河不在生成引擎本身。 +- **便宜模型 + 门兜底,而不是训一个专用大模型。** 模型这一层硬编码了 11 个角色 → 模型的赋值(以便宜的 deepseek-v4-flash 打底,救场位升 deepseek-v4-pro 强档,视觉 / 分类 / 回退位用 MiniMax-M3),没有任何一个是为游戏代码专门训练过的通用模型。质量缺口不靠把模型做重来补,而靠模板约束和验收门来补。这是成本策略,也是差异化判断——大模型迟早会追上,真正的护城河不在生成引擎本身。 - **图编排约束控制流,而不是让模型自由决定下一步。** 整条线的骨架是 **SAA 裸 StateGraph**(SAA = Spring AI Alibaba,阿里的 Spring 生态 AI 编排框架;"裸 StateGraph"指直接用它的有向状态图原语手写编排,而不是用声明式 YAML 配置)。一共 16 个节点,每个节点是一段实打实的 Java 代码,节点之间的流转由图预先固定,而非由模型在运行时临场决定"下一步调什么工具"。 - **一套硬验收门当地板。** 这就是俗称的"**九门 harness**"(harness 指把生成产物放进一个真实运行环境去自动检验的测试夹具;"九门"是其中九道确定性检查):能不能装载、跑不跑帧、响不响应输入、到不到游戏终态……全部是确定性的判定。这一层是这套架构最大的工程价值,也是绝不动它的底座。 @@ -22,6 +22,8 @@ 这台机器当前的真实状态需要诚实说清:**结构正确、控制流确定、底层验收很硬的流水线已经建成并合入主干;但生成质量尚未稳定达到 80% 这道门,而且一部分本该可替换的"策略"被焊死进了不该重编译的"机制"代码里。** 换句话说,骨架立住了,接下来要解决的是"质量"和"策略外置"两件事——这正是 §4–§6 演进路线要回答的。 +还要钉死一条比技术债更根本的**范式定性**(出处:同目录[设计合理性裁决](设计合理性裁决.md),2026-06-20 对抗审查,status 待创始人拍板):这套"便宜模型 + 受限 schema + 九门验收"是一条**为超休闲轻游戏(Tier0:打砖块 / 合成 / 挂机 / 答题 / 网格点选)量身打造的可靠产线,而不是一个通用生成范式**。它最大的风险不在工程层,而在被当成通用范式去对标 demo 里的 **Marvel 平台动作 / KOF 格斗**那一档富交互游戏——那一档这套范式**结构性地够不着**(运行时没有承载那层复杂度的形状),不是补个分支能解决的,必须显式把愿景分层、复杂品类另开一轨。下文 §3/§5 把这台机器框成"护城河的关键路径""值钱的东西我们还没有",成立的前提正是把它锚在 Tier0 这档;读时务必带着这条天花板,别把它读成"再补几层就能通吃所有品类"。 + --- ## 2. 一张端到端流程图:一句话怎么变成一款游戏 @@ -110,15 +112,15 @@ game-project/ - **终态产物 = src/ 工程**(不可妥协); - **gameDefinition = 通往 src/ 的中间妥协态**——妥协只允许在"输入端"(让便宜模型先产一个极简的声明式描述,因为便宜模型确实更擅长产这种结构),**绝不允许妥协在"产物端"**;它必须经过一道真实的"gameDefinition 编译 / 展开成 src/ 工程"的构建,而不是停在 JSON 里被 `new Function` 跑掉; -- **当前实现(JSON 内嵌 JS 串 + `new Function` 解释执行)= 已知偏离终态的债**,缺的正是"gameDefinition → src/"产物侧这一段展开。 +- **当前实现(JSON 内嵌 JS 串 + `new Function` 解释执行)= 已知偏离终态的债**,缺的正是"gameDefinition → src/"产物侧这一段展开。更尖锐的一处名实不符:**承载 100% 玩法逻辑的 `behavior.code` 这个自由 JS 串,根本没进任何契约**——它是靠 schema 的 `additionalProperties` 偷渡进 gameDefinition 的,所以"声明式结构化源"这个名号只覆盖了外壳的数据字段,逻辑核仍是一坨未受契约约束的自由 JS(这正是上面那条机制门要堵的口子)。 需要把"双证地基成立"这件事说准:它证明的是一件真实但有限的事——**便宜模型能可靠地产出连贯的 gameDefinition 中间表示**;它没有、也不能证明"gameDefinition 就是合格的终态产物"。 这条定调过去"写了却传不到实现",所以它必须配一道**机制门(doc↔code 兑现门)**:生成产物要能被自动断言为"存在 src/ 多文件结构、玩法逻辑落在真实源码文件里、不存在'逻辑只以 JSON 字符串形态存在 / 运行时 new Function 跑内嵌串'"。设计声称要 src/,代码就必须可验证地兑现 src/——否则"产物必须是 src/"这条就只是又一条等人自觉的软约束。 -### 3.3 七质量 → 生成产出的硬契约 +### 3.3 六维质量 → 生成产出的硬契约 -这条范式原则不是口号,它落到生成产出上是七条可检验的硬约束。它们共同回答了一个被早期方案忽略的根本问题:**生成质量的真标尺不是"这次能不能玩",而是"工作室将来能不能维护它"。** +这条范式原则不是口号,它落到生成产出上是六条可检验的硬约束(对应下表六行,其中"长期 / 可维护"是同一维的两面)。它们共同回答了一个被早期方案忽略的根本问题:**生成质量的真标尺不是"这次能不能玩",而是"工作室将来能不能维护它"。** | 质量 | 落到生成产出的硬约束 | |---|---| @@ -137,7 +139,7 @@ game-project/ **第一类是策略下沉进机制层。** 本该作为可替换数据的策略,被焊死进了不该重编译重部署的代码里,造成三处倒置: -- **模型路由**:11 个便宜模型的名字和每个角色的采样配置,全是 Java 常量,换一个模型要改代码、重新构建。 +- **模型路由**:11 个角色的模型名(便宜打底 + 强档 + 视觉 / 回退位)和每个角色的采样配置,全是 Java 常量,换一个模型要改代码、重新构建。 - **prompt 正文**:gameDefinition 的生成约定(系统提示、运行时写法约定、命名对齐)是 Java 字面量,而另一侧的 Python worker(worker 指实际跑生成的独立工作进程)又镜像了一份。同一份约定存在两个源,这是一个潜在的 **split-brain**(直译"裂脑",指同一份事实存在两个独立副本、迟早会不一致的隐患)。当前 worker 走的还是纯 iife 路(iife 即立即执行函数,指把游戏打成一个单文件代码块的老路),这条裂缝尚未真正激活;但只要后续切换依赖 worker 线的数据,它就会立刻变成承重的坑。 - **品类骨架**:由 design 节点自己产出,没有外部锚点。 @@ -155,7 +157,7 @@ game-project/ 双轨并存本身是健康的演进态——新路没稳前不该贸然切换——但如果不立一道硬退役门,演进态就会沉淀成永久债。与之伴生还有一个成本侧盲区:generate 节点内部有一条回退链会静默切模型,但它不计入失败计数、也不进升档事件,与图层的 escalate 升档是两套互不相通的机制;这导致"一次失败到底走了几层模型"算不清,而切换的成本归因恰恰依赖这个数。 -> **一处已被实证反掉的误判,记在这里免得重复建设**:源项目持久层不是悬空的。`game_source_project` 的建表迁移真实存在(V18/V20 双副本),落库与标记构建完成的调用在回调实现里被真正调用(事务外层、按内容哈希幂等)。所以它已经是一等公民,真实缺口只是血缘丰富度和 gamedef 路的端到端验证——这是 P2,不是要去补一条根本不存在的落库链。 +> **一处已被实证反掉的误判,记在这里免得重复建设**:源项目持久层不是悬空的。`game_source_project` 的持久层真实存在(V18 建表 + V20 加并发幂等唯一键 `uk_game_source_hash`,这两个是两道不同的迁移而非同一迁移的两份拷贝),落库与标记构建完成的调用在回调实现里被真正调用(事务外层、按内容哈希幂等)。所以它已经是一等公民,真实缺口只是血缘丰富度和 gamedef 路的端到端验证——这是 P2,不是要去补一条根本不存在的落库链。 --- @@ -330,10 +332,11 @@ flowchart LR ## 9. 源档导航 -本文档是生成引擎子树的策展层主档,把三份源档合成了一张可读的全景。要看更深的设计推演、逐条裁决与证据,从下面进去: +本文档是生成引擎子树的策展层主档,把源档合成了一张可读的全景。要看更深的设计推演、逐条裁决与证据,从下面进去: | 源档 | 回答什么 | |---|---| +| [设计合理性裁决](设计合理性裁决.md) | 对这套生成范式"到底合不合理"的对抗式审查裁决:它合理在哪、天花板与裂缝在哪(本文 §1/§3/§5 那条"Tier0 可靠产线、非通用范式"警示的权威源) | | [生成主线架构演进路线](../../../agent-specs/生成主线架构演进路线.md) | 生成主线"往哪走、先做什么"的单一 SoT:现状诊断、OpenGame 对标、统一演进路线(本文 §4–§7 的权威源) | | [生命周期项目管理 review](../../../agent-specs/2026-06-17-生成主线-游戏生命周期项目管理-review.md) | "游戏 = 长生命周期源项目、LLM as 工作室"范式的完整裁定与契约 delta(本文 §3 的权威源) | | [游戏生成系统总体架构 review](../../../agent-specs/2026-06-12-游戏生成系统总体架构-review.md) | 三级生成、第 9 契约组、控制平面、灰度矩阵、29 条意图覆盖矩阵(本文 §8 的权威源) | @@ -342,4 +345,4 @@ flowchart LR --- -> **验证状态**:本文档为架构策展文档,由三份已评审源档合成,未改任何代码。承重硬事实(V18/V20 建表、prompt registry 已存在、SAA 16 节点、九门、80% 门、¥0.15 / P75≤30s 预算时延门、76%–93% 缓存命中、OpenGame 结论锚在其真源码)均沿用源档已抽查属实的结论;品牌已统一为"绘境AI"。 +> **验证状态**:本文档为架构策展文档,由四份已评审源档(含 2026-06-20 设计合理性裁决)合成,未改任何代码。承重硬事实(V18 建表 + V20 加并发幂等唯一键、prompt registry 已存在、SAA 16 节点、九门、80% 门、¥0.15 / P75≤30s 预算时延门、76%–93% 缓存命中、OpenGame 结论锚在其真源码、Tier0 范式定性锚在裁决档)均沿用源档已抽查属实的结论;品牌已统一为"绘境AI"。 diff --git a/docs/architecture/架构/生成引擎/SAA编排.md b/docs/architecture/架构/生成引擎/SAA编排.md index 4c580af7..40813cbd 100644 --- a/docs/architecture/架构/生成引擎/SAA编排.md +++ b/docs/architecture/架构/生成引擎/SAA编排.md @@ -101,7 +101,9 @@ flowchart TD **为什么 build 和 play 是 shell 子进程调用,而不是 Java 内嵌?** 这两步复用了已经验证过的一套 JavaScript harness——esbuild 打包工具和 CDP 浏览器驱动脚本(CDP = Chrome DevTools Protocol,Chrome 提供的调试协议,可以用程序去操控一个真实浏览器)。把它们保持为子进程调用,既省掉了在 JVM 里重写整条 JS 工具链的成本,也让这套 harness 能独立演进、与 SAA 图解耦。这是"零重写、复用既有 harness"原则的直接体现。 -**"九门"(9-gate harness)到底是什么?** 它是一套在真实浏览器里自动执行的验收检测,涵盖游戏能否加载、能否渲染、能否响应输入、能否到达胜负终态等**九道门**。所有门都是确定性的代码判断(检测 DOM 状态、读 Canvas 像素、监听 JS 事件……),没有任何主观评分。只有九门**全部通过**,这款游戏才被认为"机制可玩"。这一层是整套架构最大的工程价值,也是绝不能动的地板——它是"完成"二字唯一的裁判。 +**"九门"(9-gate harness)到底是什么?** 它是一套在真实浏览器里自动执行的验收检测,涵盖游戏能否加载、能否渲染、能否响应输入、能否到达胜负终态等**九道门**。所有门都是确定性的代码判断(检测 DOM 状态、读 Canvas 像素、监听 JS 事件……),没有任何主观评分。只有九门**全部通过**,这款游戏才被认为"机制可玩"。这一层是整套架构最大的工程价值,也是绝不能动的地板——它是"机制能不能玩"这件事唯一的裁判。 + +**但要点清九门的有效性边界**:九门是**机制 CI**(判能不能玩),**不是质量 oracle**(不判"好玩 / 好看")——中间整段"是不是题面要的那个游戏""好不好看",九门没有任何门兜底。它当前还有两个已知 Goodhart 口子:**latch 终态语义不分胜负**(latch 由系统强加恒期望为真,空壳游戏弃守排空也能逼出一个 gameover 蹭过门),以及**出题与被考同源**(classify 自产品类、design 自产验收规格,而便宜模型恰恰连 `ball.x`、`driver:none` 这种基本写法都会反复写错)。这两件事的修法——"player 软门做厚 / oracle 去自评"——是**在飞演进项**,详见 [设计合理性裁决](设计合理性裁决.md) §3.3(裂缝三)与 [生成主线架构演进路线](../../../agent-specs/生成主线架构演进路线.md)。所以读者不要据此高估验收闭环对"质量"的鉴别力:九门兜的是机制地板,质量上限当前由便宜模型单点决定。 **engineBundle 是什么?** 它是最终的打包产物:build 节点把 gameDefinition(声明式的游戏描述)和 LittleJS(绘境AI 选用的 Tier-1 游戏引擎,详见[引擎与运行时](引擎与运行时.md))装配在一起,产出一个可以直接在浏览器里运行的 bundle。 @@ -117,16 +119,16 @@ flowchart TD 在这条路上,generate 节点产出的是一段 **IIFE**(Immediately Invoked Function Expression,立即执行函数表达式)格式的 `factorySrc`,build 节点直接打包这段代码字符串,**不读取结构化的源文件**。这是当前 `dispatcher=saa` 进程内派发在生产里走的路。它的端到端测试 `SaaFullGraphE2eTest` 成功率为 **60%**,线上零 prod bug,但 worker 切 SAA 的 cutover(U7 门)按门尚未切。 -### 3.2 目标态产线:gameDefinition 真结构化 studio +### 3.2 目标态产线:gameDefinition 中间表示 studio -目标态把 generate 节点改为产出**声明式 gameDefinition**——一个结构化描述对象,包含 entities(实体)、components(组件)、scenes(场景)、rules(规则),以及 behaviors(行为逻辑,每个行为带一段真实可跑的 JS)。build 节点相应改走 **build-from-source** 路径:从 gameDefinition 出发,装配成 engineBundle,而九门 harness 一行都不用改。 +目标态把 generate 节点改为产出**声明式 gameDefinition**——一个结构化描述对象,包含 entities(实体)、components(组件)、scenes(场景)、rules(规则),以及 behaviors(行为逻辑)。需要先把它的真实范式说准:它是一种**混合范式**——entities / components / scenes / rules 那层是声明式结构化外壳,但承载 100% 玩法逻辑的 `behavior.code` 字段当前**并未进契约**(schema 里 behavior 的 `required` 只有 `id` / `trigger`,逻辑核靠 `additionalProperties: true` 偷渡,运行时还接受未文档化的 `js` 别名)。所以它的准确定性是"声明式数据壳 + 受限逻辑的自由 JS 核",而不是名副其实的"真结构化源"——这一点与同目录 [设计合理性裁决](设计合理性裁决.md) §3.1(裂缝一·名实不符)、[README](README.md) §3.2 口径一致。build 节点相应改走 **build-from-source** 路径:从 gameDefinition 出发,装配成 engineBundle,而九门 harness 一行都不用改。 这条路线已经完成**双证验证(2026-06-18)**——所谓"双证",指它在两个相互独立的环节各自拿到了真实证据: - **Spike 验证(生成段)**:便宜模型针对 `source-project.schema.json` 这份 schema 产出连贯的 gameDefinition,成功率 **92–100%**,每款游戏成本约 **¥0.011**,且 behaviors 字段里是真实可运行的逻辑 JS,不是空壳。 - **Build 段验证(构建+验收段)**:gameDefinition → build-from-source → 真浏览器过九门;其中 deepseek-v4-flash 满分,4 款便宜模型里 3 款通过门,有截图实证。 -至此,"改源不改包 / 可维护源项目 / LLM 作工作室"这个核心设计命题,已在**代码层面成立**。目标产线正在产线化(执行计划 `docs/plans/2026-06-18-001`,分 U1–U4 四个阶段),完成后将替换掉 iife 路。 +但这里要把"双证"证明了什么、没证明什么说准——**创始人已于 2026-06-20 拍下终态定调**(见 [README](README.md) §3.2 与 [生成主线架构演进路线](../../../agent-specs/生成主线架构演进路线.md) ★ 段):生成游戏的**终态产物必须是一个 `src/` 多文件代码工程**(结构化、模块化、agent 能快速定位),这条不可妥协。据此:gameDefinition **不是**合格终态产物,只是**通往 src/ 的中间妥协态**——妥协只允许在"输入端"(让便宜模型先产一个极简声明式描述),绝不允许妥协在"产物端"。所以"双证"证明的是一件真实但**有限**的事:**便宜模型能可靠产出连贯的 gameDefinition 中间表示,且该中间表示能 build-from-source 过九门**;它没有、也不能证明 gameDefinition 就是合格终态产物。当前实现把整段玩法逻辑塞进 `behavior.code` JSON 字符串、运行时用 `new Function`(把字符串当代码执行)解释跑掉,正是设计明令反对的"硬编码 blob"——**这是已知偏离终态的债**,缺的正是"gameDefinition → src/ 工程"产物侧的展开段(具体怎么补属后续 plan,不在此展开)。目标产线正在产线化(执行计划 `docs/plans/2026-06-18-001`,分 U1–U4 四个阶段)。 > 这里有两个内部代号要点清:**接法A** 指当前这套"裸图确定性编排"——图把控制流焊死,模型只在节点内干活;它已建成约七成、是整条线的躯干。**接法B** 指未来给 generate/repair 节点装上真实工具、让它们逐步长成自治 ReactAgent 的演进方向(详见第 9 节"进行中")。先用接法A 把地基打稳,再用接法B 增量演进,避免返工——这是刻意的先后次序。 @@ -280,16 +282,17 @@ flowchart TB - **trace split-brain 真库闭合**(commit `703e462c` + `a09a03e9`,round3 verdict)。 - **依赖 / 编译 / checkpoint 真恢复门全绿**(门 A–F)。 - **16 节点 studio 全图已建并合入 dev/2.0.0**:包含固定架构图新增的 5 个节点(classify / asset / modify / escalate / nreview)、救场阶梯,以及 8 个契约冻结。`SaaFullGraphE2eTest` 提供真全图 e2e 首证,iife 路当前成功率 60%、零 prod bug。 -- **真结构化地基双证成立(2026-06-18)**:Spike 段验证 gameDefinition 产出质量 92–100%(¥0.011/款,behaviors 带真逻辑 JS);Build 段验证 gameDefinition → build-from-source → 真浏览器过九门(deepseek-v4-flash 满分,便宜模型 3/4 过门,有截图实证)。同时产出"运行时访问约定 v0"(一个受控的 `rt` 对象,统一收口 getEntity / spawn / input / 受控的 time-random / score-win-lose latch / fx 真调引擎)和 build-from-source 装配 PoC。 +- **gameDefinition 中间表示双证(2026-06-18)**:证明的是一件真实但**有限**的事——便宜模型能可靠产出连贯的 gameDefinition 中间表示(Spike 段质量 92–100%,¥0.011/款),且该中间表示能 build-from-source 过九门(Build 段:deepseek-v4-flash 满分,便宜模型 3/4 过门,有截图实证)。它**不等于**"真结构化终态产物已落地"(终态 = src/ 工程,见下方【待办】与 §3.2)。同时产出"运行时访问约定 v0"(一个受控的 `rt` 对象,统一收口 getEntity / spawn / input / 受控的 time-random / score-win-lose latch / fx 真调引擎)和 build-from-source 装配 PoC。 ### 进行中(本 session 独家开发) -- **gameDefinition 真结构化 studio 产线化**(计划 `docs/plans/2026-06-18-001`,U1–U4,已合入 dev/2.0.0):U1 运行时约定 2D 适配器契约 / U2 build-from-source 产线化 / U3 让 generate 真正产出 gameDefinition / U4 模型可靠性兜底。这就是上面说的**接法A**的产线化收尾。 +- **gameDefinition 中间表示 studio 产线化**(计划 `docs/plans/2026-06-18-001`,U1–U4,已合入 dev/2.0.0):U1 运行时约定 2D 适配器契约 / U2 build-from-source 产线化 / U3 让 generate 真正产出 gameDefinition / U4 模型可靠性兜底。这就是上面说的**接法A**的产线化收尾(注:它收的是中间表示这条线;产物侧"展开成 src/ 工程"那段是另立的债,见【待办】)。 - **接法B(ReAct 自治 loop)= 演进方向 = P2 / Phase-1.5 的 agent-native 轨**:给 generate / repair 节点装上真实工具(写源 / build / 跑九门 / 读错误 / 改配置资产),让它们逐步长成 ReactAgent。这里的张力——"自治会不会失控"——由九门兜底来化解:**自治在门内、发布裁决在门外**。先用接法A(已建七成、是躯干)把地基稳住,再用接法B 增量演进,不返工。(该演进任务由创始人于 2026-06-18 从 plan `001` 移出、归入本轨;`001` 的范围就是 U1–U4。) - **W-G1 开闸验收门**(与上并行)。 ### 待办 follow-up +- **产物侧 gameDefinition → src/ 工程展开段(偏离终态的债)**:终态产物必须是 `src/` 多文件工程(创始人 2026-06-20 拍板,见 §3.2 与 [生成主线架构演进路线](../../../agent-specs/生成主线架构演进路线.md) ★)。当前实现停在 JSON 内嵌 JS 串 + `new Function` 解释执行,缺的正是"gameDefinition 编译/展开成 src/ 工程"这一段;且须配一道 doc↔code 兑现门(断言产物存在 src/ 多文件结构、逻辑落在真实源码文件里)。具体怎么补属后续 plan。 - **F3**:SAA 的 cost 字段目前只落 `tokens` 数,未折算为人民币金额(token ≠ ¥)。所以效率分现在取中性值 0.5 作占位。 - **F5**:`ReadinessScorer.scoreFirstPlay` 里,嵌套的 `H_progress` 字段被 `asBool` 方法读取时恒返回 false,导致 firstPlay 分数永远卡在 0.5。这是 HTTP 路和 SAA 路**共有的既存 bug**,修复须另立 ticket、改读 `guards.H_progress.pass`;本线不动(改了会破字节兼容)。 - **F2**:SAA 路接入 D9 去重(独立 spec 规划)。 @@ -305,8 +308,10 @@ flowchart TB | 主题 | 位置 | |---|---| +| 生成主线"往哪走、先做什么"(现行 SoT:现状诊断 / OpenGame 对标 / 统一演进路线 / 产物终态=src/ 定调) | [生成主线架构演进路线](../../../agent-specs/生成主线架构演进路线.md) | +| 范式合理性裁决(名实不符 / 表达力天花板 / 九门质量边界 / 终态定调 / Tier0 分层) | [设计合理性裁决](设计合理性裁决.md) | | 完整落地坑清单(HumanNode 已废 / 无 streamEvents / supervisor 未实现 / `Semaphore(1)` 串行守端口 4320·9222 等) | `.agents/skills/saa-graph-orchestration.md` | | API 逐键源码旁证(API 速查 / 能力矩阵 / 接入部署 / 用法范式) | `docs/agent-specs/` 下的 dossier 文档 | | gameDefinition 固定架构与 studio execution 规范(16 节点全图拓扑 / 8 契约 / 救场阶梯) | [`固定游戏架构.md`](固定游戏架构.md) · `docs/agent-specs/2026-06-17-固定游戏架构与SAA-agentic-studio-execution.md` | -| 真结构化产线化执行计划(U1–U4) | `docs/plans/2026-06-18-001-feat-gen-lifecycle-and-tier1-breadth-plan.md` | +| gameDefinition 中间表示产线化执行计划(U1–U4) | `docs/plans/2026-06-18-001-feat-gen-lifecycle-and-tier1-breadth-plan.md` | | 游戏跑在什么引擎上 / 运行时访问约定 | [`引擎与运行时.md`](引擎与运行时.md) | diff --git a/docs/architecture/架构/生成引擎/WG1基准.md b/docs/architecture/架构/生成引擎/WG1基准.md index 05c40f02..8e9b323e 100644 --- a/docs/architecture/架构/生成引擎/WG1基准.md +++ b/docs/architecture/架构/生成引擎/WG1基准.md @@ -8,6 +8,12 @@ 生成引擎主文档([README.md](README.md))讲的是"一句话怎么变成一款游戏"那条技术主线,验收门文档([验收门-W-G1.md](验收门-W-G1.md))讲的是"那条主线怎么对真实用户安全开闸"。本文讲的是第三件事:**开闸之后,我们到底拿什么去喂这台机器、又该期待它产出什么质量**。20 款经典游戏就是那批"考题",它们的覆盖判定和暴露的缺口,直接决定了批量放量时该先做哪些品类、又该先补哪层能力。 +> ## ⚠️ 实测后修订(2026-06-14 / 06-15 放量已跑完,务必先读) +> **本档 §3 / §4 的覆盖判定与"4 类门面缺口"是一份 *实测前预判*;放量实测(scale-20,14 款真跑)已把其中的门面缺口判断几乎全部证伪。** 现行结论以 [`.agents/skills/cheap-model-game-generation.md`](../../../../.agents/skills/cheap-model-game-generation.md) §8–§9 与 [scale-20 短板量化报告](../../../agent-specs/_archive/2026-06-14-WG1-scale20-短板量化报告.md) 为准。三条要点: +> 1. **4 类预判门面缺口几乎全部证伪**:便宜模型(flash 这档)**自带或自写** CCD(子步 swept,见 asteroids/multiball)、文本 HUD、网格状态机(井字棋胜负+AI、扫雷洪泛)、match-finding、手势——**均非"造不出"**。文本 / 网格门面价值仅剩"省 token / 一致性",而非"造不出"。 +> 2. **真实的唯一 L0 门面缺口 = 宿主键盘桥**(`getInput` 早期不透 keydown/keyup,导致 2048/Tetris/Asteroids 三款键盘游戏集体挂)——**已修**(commit `d754b71` `fix(host): attachInput 补 keydown/keyup window 桥接`,2026-06-14)。 +> 3. **下文 §1 图、§4 诊断、§5.4 的"补门面优先级预判(文本>网格>swipe>CCD)"均属预判,已被实测推翻**——保留它们是为了让读者看清"预判 vs 实测"的对照,**不要再据此排门面优先级**。失败的真实归因是实例 bug / driver-coverage(harness 适配 driver 不够)/ 宿主键盘桥,**而非模型能力**(scale-20 闭口:**0 个模型造不出 / 0 个 3D 硬界**)。 + --- ## 1. 一句话与一张图:W-G1 靶集是什么、为什么这么排 @@ -63,6 +69,8 @@ flowchart LR 这里要钉死一个**最关键的判断,它纠正了一个直觉误区**:真正的短板不在于"造不出来",而在于"**agent 每次都要自己重新补一层**"。上面的 ①②④ 其实引擎或插件库里都有底层原语,或者本就属于"agent 写码生成"的范畴(比如引擎的 `LJS.drawText` 文本绘制函数是存在的,只是没被插件包装出来;网格状态本就该由 agent 自己管)。**但"没有插件门面"意味着每一款游戏的便宜模型都得把这个轮子重造一遍**——结果就是一致性差、token 贵、容易出错。所以本基准给出的核心建议是:**W-G1 实测之后,把高频缺口(文本 HUD、网格)补成插件门面**,而不是放任 20 个 prompt 各自硬写。 +> **实测修订(2026-06-14):** 上一段的"agent 每次都要重补一层、容易出错"是 *实测前预判*。放量实证显示:flash 这档**自写文本 HUD / 网格状态机 / 子步 swept CCD 均正确**,补门面的价值只剩"省 token / 一致性",而非"造不出来"。即"高频缺口补成插件门面"应理解为**优化项而非必备项**——详见档首"实测后修订"横幅。 + > 这里反复出现的两个词先解释清楚。**门面(façade)**:指插件对外暴露的那层公开 API——便宜模型只能用这层 API,看不到也碰不到引擎底层。**生成域**:指那些约定让 agent 自己写码实现、不归插件管的东西(玩法逻辑、美术、关卡、UI)。一个能力到底"算不算缺口",判据就是它需要的底层原语有没有门面或引擎透传面兜底(详见 §2.4)。 --- @@ -90,15 +98,17 @@ flowchart LR > **郊狼时间(coyote time)** 是个游戏手感术语:角色刚离开平台边缘的一小段时间内仍允许起跳,避免"明明踩着了却没跳起来"的挫败感。**输入缓冲(input buffer)** 则是提前一点点按键也能被记下来、等条件满足时生效。这两个是平台跳跃类游戏的"手感润滑剂"。 -### 2.2 引擎透传真实粒度(`makeEngineCaps()`,只此三面) +### 2.2 引擎透传真实粒度(`createEngineCaps()`,只此三面) 除了上面 7 个插件,宿主还从引擎本体直接透出了三面能力。**注意:只有这三面**——引擎(LittleJS)本身远不止这点(它有文本绘制 `drawText`、贴图绘制 `drawTile`、瓦片碰撞、相机等等),但插件墙内**只透出这三面**,其余引擎能力都不构成 agent 的能力词汇: +> **锚点说明:** 这个能力背书工厂原是 `host.js` 闭包里的 `makeEngineCaps`,已被提升为独立可 import 模块 `host-dev/engine-caps.js` 的 `createEngineCaps()`(搬运·语义零变,见 `host.js:188-190` 的迁移注与 `engine-caps.js:8`)。host-dev 与 wanglanmei-ref real 通道共用同一份。下表锚点已指向 `engine-caps.js`。 + | 透传面 | 真实粒度 | 证据锚点 | |---|---|---| -| **particles**(粒子) | 薄包装引擎的 `ParticleEmitter`(27 个参数全映射),做了像素↔世界坐标的阻抗换算 | `host.js:213-273` | -| **audio.synth**(音频合成) | 把音效 / 音乐合成为 PCM 样本(只合成不播放,播放层另补) | `host.js:279-316` | -| **math**(数学) | `lerp` 线性插值 / `smoothStep` 平滑步进 + 11 条等价缓动曲线(POWER/BACK/ELASTIC 族),纯函数 | `host.js:204-209` + `engine-math.js:56-87` | +| **particles**(粒子) | 薄包装引擎的 `ParticleEmitter`(全参数映射),做了像素↔世界坐标的阻抗换算 | `engine-caps.js:61-120`(`new ParticleEmitter:91`) | +| **audio.synth**(音频合成) | 把音效 / 音乐合成为 PCM 样本(只合成不播放,播放层另补) | `engine-caps.js:122-145`(`synthSfx:134`) | +| **math**(数学) | `lerp` 线性插值 / `smoothStep` 平滑步进 + 11 条等价缓动曲线(POWER/BACK/ELASTIC 族),纯函数 | `engine-caps.js:51-61` + `engine-math.js:56-87` | ### 2.3 受控面 6 项(引擎可换边界) @@ -169,17 +179,20 @@ flowchart TB GEST["手势识别(swipe / 拖拽)
暴露:#2/13 swipe / #15 拖拽 / #16
→ 触屏轻游戏刚需,宜并入 gamefeel"] FSM["④ 通用状态机 FSM
暴露:#8 Simon / #11 Tetris / 回合制类
→ 属生成域,优先级最低"] end - 真缺口 -->|"等批次3实测再拍是否补门面"| DECIDE["决策:补哪个门面
预判优先级
文本 > 网格 > swipe/拖拽 > CCD swept"] - 半缺口 -->|"量化便宜模型自写出错率"| DECIDE + 真缺口 -->|"批次3已跑(06-14/15)
结论:门面非必需"| DECIDE["决策:补哪个门面
预判优先级(已被实测推翻)
文本 > 网格 > swipe/拖拽 > CCD swept"] + 半缺口 -->|"已量化:flash 自写多正确"| DECIDE ``` +> **实测修订(2026-06-14 / 06-15):** 上图的"补门面优先级预判(文本>网格>swipe>CCD swept)"已被放量实测推翻——这四类**经放量验证均非缺口、不需补门面**(文本/网格门面价值仅剩"省 token/一致性")。下文 §4.1–§4.6 逐条诊断同属*实测前预判*,每条已就地标注实测反证;现行结论以 [`.agents/skills/cheap-model-game-generation.md`](../../../../.agents/skills/cheap-model-game-generation.md) §9 与 [scale-20 报告](../../../agent-specs/_archive/2026-06-14-WG1-scale20-短板量化报告.md) §六/§八为准。真实的唯一 L0 门面缺口=宿主键盘桥(已修 `d754b71`)。 + ### 4.1 真缺口之一:连续碰撞 CCD(高速小目标会穿透) **CCD**(Continuous Collision Detection,连续碰撞检测;也叫 swept,扫掠碰撞)指的是这样一种能力:当一个物体一帧之内移动得太快、跨度超过了目标的厚度时,普通的"逐帧看现在有没有重叠"会漏判——物体在两帧之间就"穿"过去了(术语叫 tunneling,隧穿)。CCD 的做法是检查整段移动轨迹有没有掠过目标,而不只看落点。 - **性质**:我们的 collision 插件**只有离散的 MTV / 穿透判定**(`circleVsAabb:295`),没有 swept / toi(toi = time of impact,碰撞时刻)。`grep` 搜 `swept|ccd|continuous|toi|tunnel` 全空,`impl.js:21` 也自述能力止于"MTV / 穿透 / RayHit"。 -- **后果**:**高速小球会穿砖、穿墙**,便宜模型多半会产出"球偶尔卡进砖里 / 直接穿透"的 bug 件。暴露这个缺口的是 **#5 高速打砖块、#12 小行星子弹、#20 多球弹球**。 +- **后果(预判)**:**高速小球会穿砖、穿墙**,便宜模型多半会产出"球偶尔卡进砖里 / 直接穿透"的 bug 件。暴露这个缺口的是 **#5 高速打砖块、#12 小行星子弹、#20 多球弹球**。 - **绕法与建议**:agent 可以用射线 `raycastAabb:500` 沿速度向量手做一个粗糙的 toi(可行,但每款都得重写、容易错)。如果实测发现高频,就给 collision 补一个 swept 门面。**是否本期补,建议等批次 3 实测数据再拍**,不预先投入。 +- **★ 实测反证(2026-06-14 / 06-15,批次 3 已跑)**:这条"造不出 / 易穿透"的预判**未成立**——asteroids 子弹、multiball 弹球的源码经审计**已是子步 swept CCD、本体正确**,便宜模型自写正确。multiball 的 latch 未过是 driver-coverage(9s 内既清不完砖又护不住末球),asteroids 早期挂在宿主键盘桥(已修);**均非 CCD 能力缺口**。故"碰撞穿透门 J / swept 门面"已非急需。 ### 4.2 真缺口之二:寻路 A* / 导航(已主动规避) @@ -190,21 +203,23 @@ flowchart TB **HUD**(Heads-Up Display,抬头显示)指叠在游戏画面上的那层信息——分数、生命、计时之类。这是 20 款里**最高频**的能力需求,却恰恰没有门面: -- **性质**:没有任何文本渲染门面(`grep` 搜 `drawText|renderText` 全空)。引擎的 `LJS.drawText` 是存在的,但没经插件透出,`makeEngineCaps()` 那三面也不含文本(`host.js:210-317`)。 +- **性质**:没有任何文本渲染门面(`grep` 搜 `drawText|renderText` 全空)。引擎的 `LJS.drawText` 是存在的,但没经插件透出,引擎能力背书工厂(`createEngineCaps`)那三面也不含文本(`host-dev/engine-caps.js:51-145`)。 - **后果**:每个游戏的便宜模型都得自己去 `ctx.getContext2d().fillText` 手画 HUD——结果就是风格各异、字体和对齐到处出错。 - **判定**:**这是最高频缺口**,20 款里约 15 款需要文本。所以**强烈建议补一个 text / HUD 门面插件,作为 W-G1 实测后的第一优先**。 ### 4.4 半缺口之二:网格 / 棋盘状态抽象 - **性质**:没有 grid / tilemap 门面(`grep` 搜 `tilemap|gridMap` 全空)。网格状态本属 agent 生成域,但"坐标↔索引转换、邻接查询、遍历、合并"这些操作每款都得重写。 -- **后果**:2048、Tetris、Match-3 的网格状态机正是它们的核心难度所在,便宜模型自管很容易出"合并方向错 / 消行错 / 连锁错"的 bug。暴露这个缺口的是 **#1/2/3/7/9/11/13**。 +- **后果(预判)**:2048、Tetris、Match-3 的网格状态机正是它们的核心难度所在,便宜模型自管很容易出"合并方向错 / 消行错 / 连锁错"的 bug。暴露这个缺口的是 **#1/2/3/7/9/11/13**。 - **建议**:W-G1 重点观察便宜模型自写网格的出错率;如果高,就补一个 grid 工具门面。 +- **★ 实测反证(2026-06-14)**:flash 这档**自写网格状态机正确**——井字棋(3×3 状态机+胜负+AI)、扫雷(洪水填充+雷数文本)、Match-3(score 0→40 真消除)均跑通。2048/Tetris 早期挂在**宿主键盘桥**(键盘没透出 → 棋盘零变化 / 重力假性锁定),修键盘桥(`d754b71`)后 Tetris 整盘翻绿、2048 真合并;**根因是键盘桥、非网格能力**。故 grid 门面价值降为"省 token / 一致性",非"造不出"。 ### 4.5 半缺口之三:手势识别(swipe / 拖拽) - **性质**:受控面 `getInput` 只给 5 类原始事件(`api.d.ts:218`),没有 swipe / drag 的合成。 -- **后果**:agent 必须自己缓存 pointerdown→move→up 这串序列、算出方向和距离;愤怒小鸟那种拖拽蓄力尤其容易错。暴露这个缺口的是 **#2 / #13(swipe)、#15(拖拽)、#16**。 +- **后果(预判)**:agent 必须自己缓存 pointerdown→move→up 这串序列、算出方向和距离;愤怒小鸟那种拖拽蓄力尤其容易错。暴露这个缺口的是 **#2 / #13(swipe)、#15(拖拽)、#16**。 - **建议**:swipe / drag 是触屏轻游戏的刚需,可以补进 gamefeel 插件——它本就管输入缓冲,手势识别归它最自然。 +- **★ 实测反证(2026-06-14 / 06-15)**:手势"易错"的预判**未成立**——Match-3 的盲态 swipe 交换凑三连真消除(本体正确),愤怒小鸟的拖拽蓄力**本体弹道正确**(F_wiring 过);二者的 score 缺口是 **harness 适配 driver 覆盖**(固定盲拖打不准 / 关卡 tuning),经 enrich 导出 launch 物理常数 + 加 drag-aiming driver 后**愤怒小鸟 0→20 清场**。**根因是可测性 / driver,非模型合成手势的能力。** ### 4.6 半缺口之四:通用状态机 FSM @@ -242,6 +257,8 @@ flowchart TB 有了上面的判定,W-G1 就不该 20 款一拥而上,而应**先用能力面齐备的易档验通管线(冒烟),再用中 / 难档加缺口款去压测能力上限、量化便宜模型在缺口处的产出质量**。据此分成三批,逐批加难: +> **实测进度(2026-06-14 / 06-15,本分批计划已执行完毕):** 三批均已实跑,结论已出——**主力批 flash 实过 7/8**(flappy 唯一未过=driver-coverage 非模型);**压测批 6 款 0 个"造不出"**,3 款键盘游戏集体挂于**同一处宿主键盘桥**(已修 `d754b71`,修后 Tetris 翻绿 / 2048 真合并 / asteroids 解冻),multiball / 愤怒小鸟挂在 driver-coverage(重生成 / 增强 driver 后翻绿,愤怒小鸟 0→20)。下文各批的验收口径保留原文;**"等批次 3 再拍"一类的待办均已闭口**,结论见 [scale-20 报告](../../../agent-specs/_archive/2026-06-14-WG1-scale20-短板量化报告.md) 与 [`cheap-model-game-generation.md`](../../../../.agents/skills/cheap-model-game-generation.md) §9。 + ```mermaid flowchart LR B1["批次1 · 冒烟批
6 款 · 全 ✅ · 难度易
Pong / Simon / 打地鼠
记忆翻牌 / 贪吃蛇 / 节奏点击"] @@ -274,12 +291,14 @@ flowchart LR 理由是每款都压一到多个短板——Tetris / Match-3 / 2048 压**网格状态机上限**,小行星 / 多球弹球压**CCD 缺口**,愤怒小鸟压**拖拽手势缺口**。它的核心产出是**证实 §4 的缺口判定**:便宜模型在 CCD / 网格 / 拖拽处的产出质量到底如何(会不会穿透?消行对不对?蓄力准不准?),给创始人一张"引擎短板实测画像"。验收标准比较特殊:**不强求高通过率**(本批就是测上限的);**重点是产出缺口实证报告**,去喂"是否补 text / grid / swipe / swept 门面"那个决策。 +> **实测结果(2026-06-14 / 06-15,本批已跑完):** 实证画像与 §4 预判**相反**——便宜模型**不会穿透**(asteroids/multiball 子弹已是子步 swept CCD)、**消行/网格对**(Tetris 修键盘桥后整盘翻绿、Match-3 真消除)、**蓄力准**(愤怒小鸟本体弹道正确)。6 款失败 **0 个"造不出"**:3 款键盘款挂宿主键盘桥(已修 `d754b71`)、multiball / 愤怒小鸟挂 driver-coverage(增强 driver 后翻绿)。**喂决策的结论 = text / grid / swipe / swept 四类门面均非必需**(若补,价值在省 token / 一致性)。详见 [scale-20 报告](../../../agent-specs/_archive/2026-06-14-WG1-scale20-短板量化报告.md) §六/§八。 + ### 5.4 跨批观测项(W-G1 真正要回答的三个问题) 不管哪一批,W-G1 全程要盯着三个问题——它们才是这次实测真正的产出: 1. **便宜模型在三档的产出质量梯度**:M3 / M2.7 / DS-V4 从易到难,哪一档开始崩?这定下能力天花板。 -2. **四类短板各拖垮多少款**:文本 / 网格 / CCD / 拖拽各自影响几款,据此排补门面的优先级。**预判是:文本 HUD > 网格 > swipe / 拖拽 > CCD swept**。 +2. **四类短板各拖垮多少款**:文本 / 网格 / CCD / 拖拽各自影响几款,据此排补门面的优先级。**预判是:文本 HUD > 网格 > swipe / 拖拽 > CCD swept**。 ⚠️ **此优先级已被 06-14 scale-20 实测推翻**:这四类经放量验证**均非缺口、门面非必需**(便宜模型自带或自写正确)——真实唯一 L0 门面缺口=宿主键盘桥(已修 `d754b71`);不要再据此预判排门面优先级。 3. **harness 门的判定有效性**:那套门能不能稳定逮住"穿透 / 消行错 / 不可玩"?门兜底是便宜模型路线的命门——门不硬,整条路线就立不住。 --- @@ -312,4 +331,4 @@ flowchart LR --- -> **验证状态**:本文档为架构策展文档,由 W-G1 基准调研产出(只读盘点,未改任何运行时代码)改写而成。承重硬事实——约 12 款 ✅ 可立即冒烟、4 类能力缺口(文本 HUD / 网格 / CCD / FSM)、2 条硬边界(CCD swept 与寻路 A*)、7 插件 + 引擎三透传面 + 受控面 6 项、各能力的 `文件:行号` 证据锚点、三批分档(冒烟 6 款 / 主力 8 款 / 压测 6 款)与各自验收口径、补门面优先级预判(文本 > 网格 > swipe / 拖拽 > CCD swept)、源码证伪法纪律——均沿用源档已抽查属实的结论;品牌统一为"绘境AI",无旧名残留。 +> **验证状态**:本文档为架构策展文档,由 W-G1 基准调研产出(只读盘点)改写而成,本身未改任何运行时代码。承重硬事实分两类:**(a) 仍成立的事实基**——7 插件 + 引擎三透传面 + 受控面 6 项、各能力的 `文件:行号` 证据锚点(`makeEngineCaps` 已迁 `host-dev/engine-caps.js`,见 §2.2)、三批分档(冒烟 6 款 / 主力 8 款 / 压测 6 款)及源码证伪法纪律,均沿用源档已抽查属实的结论。**(b) 已被实测推翻的*预判***——§3 / §4 的覆盖判定、"4 类能力缺口(文本 HUD / 网格 / CCD / FSM)"、"约 12 款 ✅ 可立即冒烟"、"补门面优先级预判(文本 > 网格 > swipe / 拖拽 > CCD swept)"均属*实测前预判*;2026-06-14 / 06-15 放量(scale-20,14 款真跑)已将其中的门面缺口判断几乎全部证伪(便宜模型自写正确),**真实唯一 L0 门面缺口=宿主键盘桥(已修 `d754b71`)**,现行结论以档首"实测后修订"横幅及其引用的 [`cheap-model-game-generation.md`](../../../../.agents/skills/cheap-model-game-generation.md) §8–§9 / [scale-20 报告](../../../agent-specs/_archive/2026-06-14-WG1-scale20-短板量化报告.md) 为准。品牌统一为"绘境AI",无旧名残留。 diff --git a/docs/architecture/架构/生成引擎/prompt治理.md b/docs/architecture/架构/生成引擎/prompt治理.md index 5330348e..41805f68 100644 --- a/docs/architecture/架构/生成引擎/prompt治理.md +++ b/docs/architecture/架构/生成引擎/prompt治理.md @@ -73,7 +73,7 @@ flowchart LR 读这张图抓住三点就够了: - **供给侧是只读的、轻量的。** 生成链路的每个节点要 prompt 时,经 `PromptRegistryLoader`(加载器)按编号从 Registry 取文本、填入变量、注入给模型。Registry 是一份**文件契约,不是一个服务**——所以它不引入新的跨模块强耦合,也不会成为一个会宕机的依赖。 -- **治理侧是闭环的、有门的。** 任何人想改 prompt,都得提一个 PR(Pull Request,代码改动的评审请求),并且**必须升 version**(改了不升版号会被 CI 直接拒)。PR 一提,持续集成(CI)就自动跑"四道闸"——这是本体系最核心的质量门,§4 详述。四闸全绿,再交人工抽检批准,才允许合入并同步到生产。 +- **治理侧是闭环的、有门的。** 任何人想改 prompt,都得提一个 PR(Pull Request,代码改动的评审请求),并且**必须升 version**(改了不升版号该被拒)。设计目标是 PR 一提就由持续集成(CI)自动跑"四道闸"——这是本体系最核心的质量门,§4 详述。**现状**:四道闸的判定逻辑已由 W-G1 的批跑编排(`evalflow.py`,每批强制把样本回流进 eval 集)实现并跑出数据,但**PR 触发的 `prompt-eval` GitHub Actions 尚未接线**(集成仓根目录暂无 `.github/workflows`)——即图中那条 CI 虚线现阶段以"人工发起的批跑编排"执行,CI 接线为待建项。四闸全绿,再交人工抽检批准,才允许合入并同步到生产。 - **数据回流让 prompt 越改越准。** 线上的 telemetry(遥测,即用户真实行为埋点数据)会反哺回来:哪类 prompt 产出的游戏没人玩、留存差,就成为下一轮改 prompt 的依据。这一条把"治理"从被动防退化,升级成主动求进步。 依赖方向很干净:**壳层 → Registry(读);CI → Registry(读)+ 模型(跑样本);运行时构建流水线 → 测试原子(执行)。** 没有任何一条引入新的服务级强耦合。 @@ -82,21 +82,24 @@ flowchart LR ## 3. Registry 长什么样:目录结构与一条 prompt 的构造 -Registry 的物理形态就是 `contracts/prompts/` 下的一棵目录树。它按**生成生命周期的阶段**分目录,每个阶段放该阶段会用到的 prompt。当前实现采用 **8 阶段编号命名**(便于一眼看清执行顺序),其中已投产的几个阶段如下: +Registry 的物理形态就是 `contracts/prompts/` 下的一棵目录树。它按**生成生命周期的阶段**分目录,每个阶段放该阶段会用到的 prompt。当前实现采用 **8 阶段编号命名**(便于一眼看清执行顺序),其中已入库的几个阶段如下: ``` contracts/prompts/ ├── registry.yaml # 索引:所有 prompt 的 id / 版本 / owner / 绑定 schema / eval 集 -├── _schemas/ # 输入 / 输出 JSON Schema(prompt 的格式契约) +├── _schemas/ # (规划,未落地)输入 / 输出 JSON Schema(prompt 的格式契约) +│ # 现状:此目录暂缺位,frontmatter 的 schema 字段直接指向真实契约文件(见 §3 示例) ├── 01-safety/ # 创作者输入的安全 / 注入检测(生成链路第 1 道节点) ├── 04-config/ # 各玩法的策划 prompt(clicker / merge / idle / tycoon ... designer) -│ # + generic-coder(P3 编码 prompt,产出可玩产物源码) +│ # + generic-coder(P3 编码 prompt,⚠️ 当前为 STUB 占位骨架,待 L1 出正式草案) ├── 06-quality/ # 对抗式质量评审 prompt(adversary-review) ├── 07-fix/ # 按评审意见回灌重出的修订 prompt(design-revise) └── eval/ # 每条 prompt 的 Golden 样本集,目录名 = prompt id ``` > 阶段编号的完整规划是 `01-safety 02-intent 03-template 04-config 05-asset 06-quality 07-fix 08-meta`;上面只列出当前已落地的几个。其余阶段随生成链路演进逐步迁入,Registry 的设计本就允许增量入库。 +> +> **"已入库"≠"已接 live 生成路径",两者要分清**:① 已接 live 后端生成路径的是 01-safety 与 04-config 的四个策划模板(clicker / merge / idle / tycoon——由 `PromptResourceLoader` 在进程内渲染注入);其余 04-config 模板(generic-coder 等)与 06-quality / 07-fix,目前仅被 W-G1 批跑编排(`evalflow.py` 等 `orchestrator/*.py`)消费,尚未接入 live game-cloud 服务。② generic-coder 还额外是 STUB:`registry.yaml` 标其 `version 0.0.1 ⚠️ STUB 占位骨架`(仅 frontmatter + 三要点提纲,非正式 prompt),后端入库它只为让加载器 `isReady()` 通过、schema 进校验缓存,**不在进程内拿它喂 LLM**。 **每条 prompt 的构造 = 一段 frontmatter 契约头 + 模板体。** frontmatter(前置元数据,写在文件顶部 `---` 之间的结构化字段)就是这条 prompt 的"契约头",声明它的身份、版本、归属和绑定的 schema/eval。模板体则是真正发给模型的文本,里面带变量槽(运行时填入)。一个示意: @@ -107,8 +110,9 @@ version: 1.1.0 # 语义化版本号,改一字也要升 owner: WS2 # 唯一负责工位(改它必须经其批准) tier: tier1 # tier1 | tier2 | tier3(梯队) stage: "04-config" # 所属生命周期阶段 -input_schema: _schemas/... # 输入格式契约 -output_schema: contracts/templates/clicker.schema.json # 输出格式契约 +engine: newapi-chat # 目标引擎(单引擎 new-api/SAA 下已退化为假设值,枚举未定,见下注) +input_schema: "../../agent-loop/game-design.schema.json#/properties/idea" # 输入格式契约(真实路径) +output_schema: "../../agent-loop/game-design.schema.json" # 输出格式契约;config 段逐字段真源 = ../../templates/clicker.schema.json constraints: # 硬约束块(产物必须满足的红线) - 首屏 ≤ 2MB,总包 ≤ 10MB - 游戏内零网络请求 @@ -119,15 +123,15 @@ guardrails: [injection-detect, schema-validate] # 护栏:注入检测 / schema ... 模板体,带 {{变量槽}} ... ``` -frontmatter 里几个字段值得点名:**owner**(归属工位)规定了"谁能改这条 prompt"——本项目把工位编号为 WS1~WS5(WorkStation,工位),改一条 prompt 要经它的 owner 批准,杜绝无主乱改;**tier**(梯队)区分 prompt 的重要性,tier1 是 MVP 生产主线必须治理的,tier2/3 是更长期的增强轨;**constraints**(硬约束块)是产物必须守住的红线(如包体大小、零网络请求),**guardrails**(护栏)是运行时挂的自动检查(如注入检测、schema 校验)。 +frontmatter 里几个字段值得点名:**owner**(归属工位)规定了"谁能改这条 prompt"——本项目把工位编号为 WS1~WS5(WorkStation,工位),改一条 prompt 要经它的 owner 批准,杜绝无主乱改;**tier**(梯队)区分 prompt 的重要性,tier1 是 MVP 生产主线必须治理的,tier2/3 是更长期的增强轨;**constraints**(硬约束块)是产物必须守住的红线(如包体大小、零网络请求),**guardrails**(护栏)是运行时挂的自动检查(如注入检测、schema 校验)。**engine**(目标引擎)在设计期是区分注入载体的必填枚举,但在现行**单引擎**(new-api / SAA)语境下已退化为假设占位值(真实文件里写作 `engine: newapi-chat` 并自注"枚举未定"),不再是有效的区分维度——保留它只为与真实 frontmatter 一致。另注:示例里的 `input_schema` / `output_schema` 指向真实契约文件(`../../agent-loop/game-design.schema.json` 等),因为 §3 目录里那个 `_schemas/` 目录尚未落地(见上文目录树标注)。 -`registry.yaml` 是这棵树的总索引,逐条登记每个 prompt 的 id、版本、owner、绑定的 schema 和 eval 目录。它和文件系统的实际内容必须**严格一致**——启动期会做全量校验,对不上就阻止部署(见 §7)。 +`registry.yaml` 是这棵树的总索引,逐条登记每个 prompt 的 id、版本、owner、绑定的 schema 和 eval 目录。它和文件系统的实际内容必须**严格一致**——这份索引↔文件的对账由 §4 四道闸 CI 负责,在合入前挡下"配置漂移"(加载器自身只逐模板自检自禁用、不复制此对账逻辑,见 §5/§7)。 --- ## 4. 心脏:改一条 prompt 要过的"四道闸" -这套体系真正的价值,在于**让"改 prompt"这件高风险的事变得可回归、可拦截**。机制是:任何 prompt 改动的 PR,都会触发一段叫 `prompt-eval` 的 CI 流程,它对这条 prompt 跑四道自动闸门,全绿才放行。"四道闸"是本体系的核心门控,逐一解释: +这套体系真正的价值,在于**让"改 prompt"这件高风险的事变得可回归、可拦截**。机制是:对一条 prompt 跑四道自动闸门,全绿才放行——这套判定逻辑当前由 W-G1 批跑编排(`evalflow.py`)执行并跑数据,**目标是接成 PR 触发的 `prompt-eval` CI 流程**(接线为待建项,见 §2)。"四道闸"是本体系的核心门控,逐一解释: ```mermaid flowchart TB @@ -162,7 +166,7 @@ flowchart TB ## 5. 接口契约:加载器与测试原子 -这套体系对外暴露两组关键契约。第一组是 **`PromptRegistryLoader`**(prompt 加载器),它是生成链路读取 prompt 的唯一入口,接口形态(契约,非实现)如下: +这套体系对外暴露两组关键契约。第一组是 **prompt 加载器**(设计期称 `PromptRegistryLoader`,现行落地实现为 `PromptResourceLoader`),它是生成链路读取 prompt 的唯一入口,接口形态(契约,非实现)如下: ``` PromptTemplate load(id, version) # 取一条 prompt(含 frontmatter + 模板体);缺失抛 PromptNotFoundException @@ -171,16 +175,20 @@ List list(stageOrEngine) # 按阶段 / 引擎列出 pro boolean validate(PromptTemplate) # 校验 frontmatter 与 schema 绑定是否有效 ``` -**加载策略是"内存镜像优先、回源兜底":** 优先读数据库里的只读镜像(命中即返回,快);未命中再回源到 git 取文件。而且**启动期会全量校验** `registry.yaml` 与实际文件是否一致——索引和文件对不上就拒绝启动,把"配置漂移"挡在上线之前。 +**现行加载策略是"构建期快照、缺失即自禁用"**(对应实现 `PromptResourceLoader`,方案 A):构建时由 maven-resources 插件把 `contracts/prompts/` 与对应 schema 复制进 jar 的 `classpath:wanxiang-contracts/`(jar 内只是构建快照,**git `contracts/` 仍是唯一事实源**——改 prompt = 改原文件 + 升 version + 过四道闸,下次构建部署自动携带新版)。加载器启动时**逐模板自检**,任一模板的 prompt/schema 资源缺失或形态非法,就把整体 `ready` 置为 `false`(自禁用信号),执行器据此永不带病认领任务——不抛异常、不崩进程。 -第二组契约值得专门点名,因为它把"prompt 治理"和"产物质量"接到了一起——这就是 **T-AGC-09 测试脚本原子**(原子 = 生成流水线里一个不可再分的处理单元;T-AGC-09 是它的工序编号): +> 这里不存在"数据库只读镜像",也没有"运行时回源 git checkout":那是早期设计期契约里设想的载体,工程落地改走了更简单的构建期快照路。`registry.yaml` 与文件是否一致的对账是 §4 四道闸 CI 的职责,加载器不复制治理逻辑。 + +第二组契约值得专门点名,因为它把"prompt 治理"和"产物质量"接到了一起——这就是 **T-AGC-09 测试脚本原子**(原子 = 生成流水线里一个不可再分的处理单元;T-AGC-09 是它的工序编号)。**注意它当前是设计/规划态契约,尚未实现**(game-cloud 内暂无对应实现);其规划接口形态如下: ``` TestScript generate(GameConfig config) # 输入游戏配置 → 输出测试脚本(启动 / 输入响应 / 边界断言) // runtime 编译后执行该脚本:通过 = 准许入库;失败 = 拒绝入库 + 原因分类 ``` -它的意义在于:生成出来的游戏**在入库发布之前,必须先被一段自动生成的测试脚本验证"真的能跑"**——能不能启动、按键有没有响应、边界条件会不会崩。跑不过就拒绝入库,并对失败原因分类。这是 prompt 治理体系在"产物侧"埋的最后一道闸:**prompt 把关的是"怎么生成",T-AGC-09 把关的是"生成出来的到底能不能玩"。** 它与生成引擎的"九门 harness"(把产物放进真实运行环境自动检验的九道确定性门)是同一种工程哲学的延伸——宁可显式拦截,绝不让坏产物进库。 +它的意义在于:生成出来的游戏**在入库发布之前,应先被一段自动生成的测试脚本验证"真的能跑"**——能不能启动、按键有没有响应、边界条件会不会崩。跑不过就拒绝入库,并对失败原因分类。这是 prompt 治理体系规划在"产物侧"埋的一道闸:**prompt 把关的是"怎么生成",T-AGC-09 要把关的是"生成出来的到底能不能玩"。** + +> **现状口径**:当前真正生效的入库实拦是生成引擎的**九门 harness**(把产物放进真实运行环境自动检验的九道确定性门——见同目录 [README §3.2 区](README.md));T-AGC-09 是产物侧的**规划门**,与九门是同一种工程哲学的延伸(宁可显式拦截,绝不让坏产物进库),待落地后补强 GameConfig 模板这条路的产物自测。 --- @@ -202,10 +210,10 @@ HITL 在整条链路里的位置很明确:**它永远站在机器闸之后**。 | 失败场景 | 处理方式 | |---|---| | prompt id/version 不存在 | `load` 抛异常 → 壳层**回退到内置默认 prompt** + 告警,**不中断生成** | -| frontmatter / schema 校验失败 | 启动期或 CI 拒绝该 prompt 上线,报出具体字段 | +| frontmatter / schema 形态非法 | 加载器启动逐模板自检不过 → 整体 `ready=false` **自禁用**(执行器不带病认领任务),并由 CI 报出具体字段;**不抛异常、不崩进程** | | eval 跑不通(模型限流 / 超时) | CI 标记 skip + 通知人工兜底审,**不阻塞紧急修复** | | 改 prompt 未升 version | CI 卡死:version 未变 → 拒绝合入(即 §4 的闸 0) | -| registry.yaml 与文件不一致 | 启动期校验失败 → 阻止部署 | +| registry.yaml 与文件不一致 | 由 CI 四道闸对账拦截(加载器不复制此治理逻辑,见 §5);合入前挡下漂移 | 回滚同样是分层设计的,**整体回滚成本极低**,因为 Registry 是一个**叠加层**——它叠在原有调用方式之上,而不是替换掉: @@ -223,8 +231,8 @@ HITL 在整条链路里的位置很明确:**它永远站在机器闸之后**。 1. **入库完整**:Tier1 全链路 prompt 都进了 `contracts/prompts/`,`registry.yaml` 索引完整、与文件一致。 2. **加载跑通**:生成时 prompt 真实来自 Registry(而非节点内嵌),改文件即生效。 -3. **门禁生效**:`prompt-eval` CI 至少对一条 prompt 生效——**故意改坏一条 prompt,PR 应被四道闸拦下;正常改动则放行**。 -4. **产物把关**:T-AGC-09 产出测试脚本,生成流水线在入库前执行它,能拦住"不可运行"的产物。 +3. **门禁生效**:四道闸至少对一条 prompt 生效——**故意改坏一条 prompt,应被四闸拦下;正常改动则放行**(现状由 W-G1 批跑编排执行四闸;目标是接成 PR 触发的 `prompt-eval` CI,接线为待达成项)。 +4. **产物把关**(规划态):T-AGC-09 产出测试脚本、生成流水线在入库前执行它以拦住"不可运行"的产物——此为待达成条件;当前入库实拦由九门 harness 承担(见 §5)。 5. **HITL 闭环可走**:运营能完整走通"改 prompt → eval → 批准"流程(页面或文档化流程均可)。 一句话收尾:**Prompt 治理把生成引擎里最易变、最易失控的一环,变成了和数据库、API 同级的工程契约——可版本化、改动可自动回归、人能在关键节点把关,而这一切都以"不拖慢、不阻断生成主线"为前提。** 这是绘境AI 让一个普通模型稳定产出可上线游戏的关键支撑之一。 diff --git a/docs/architecture/架构/生成引擎/固定游戏架构.md b/docs/architecture/架构/生成引擎/固定游戏架构.md index e5e397f2..e425cbea 100644 --- a/docs/architecture/架构/生成引擎/固定游戏架构.md +++ b/docs/architecture/架构/生成引擎/固定游戏架构.md @@ -35,7 +35,7 @@ flowchart LR 四样东西合起来,才把便宜模型榨满:**SAA 提供编排、固定架构提供结构、便宜模型提供生成、自动质量门提供把关**。给定单款生成预算 **< $1**(便宜模型单价低,一美元容得下几十次调用),这个环境就能放心地多 agent、多迭代、多重试。 -> 这套设计不是空想。便宜模型在固定结构上填出连贯游戏定义、再构建成真能过门的游戏,已在代码层得到双重验证(见 §9 实测证据),核心立论"改源不改包 / 可维护源项目 / 把大模型当工作室"已经成立。 +> 这套设计不是空想——但要把"成立到哪一步"说准。便宜模型在固定结构上填出连贯的**游戏定义中间表示**(gameDefinition)、再构建成真能过门的游戏,这一段已在代码层得到双重验证(见 §9 实测证据):**双证证明的是"便宜模型能可靠产出连贯的 gameDefinition 中间表示",并未、也不能证明"gameDefinition 就是合格的终态产物"。** 创始人 2026-06-20 已就产物终态定调:**终态产物必须是 `src/` 多文件代码工程,gameDefinition 只是"通往 src/ 的中间脚手架"**;当前实现把玩法逻辑塞进 `behavior.code` JSON 串、运行时用 `new Function` 解释执行,属"**已知偏离终态的债**",缺的正是"gameDefinition → src/"产物侧那一段展开。所以本档凡言"可维护源项目 / 把大模型当工作室",均指**方向已经走通、终态尚待兑现**,不是已闭合的终局——口径以同目录 [README §3.2 终态硬约束](README.md) 与 [设计合理性裁决](设计合理性裁决.md)(Tier0 混合范式 · 名实分层)为准。 --- @@ -168,11 +168,11 @@ graph TB - `profile` **三维画像**:`tickModel`(realtime / turn-based / event,游戏怎么推进时间)、`inputModel`(continuous / discrete-choice / text-command,玩家怎么输入)、`progressModel`(metric / narrative,靠数值还是靠叙事推进)。**为什么必须三维**:只有纯物理一维会让剧情 / TRPG 类绷断,三维才覆盖得住。`progressModel=narrative` 会走叙事评审质量门。 - `gameDefinition`(§3 那套实体 / 组件 / 行为 / 场景 / 规则)、`assets`(六类资产规格)、`config`(平衡参数,确定性修改就改这里、免调用 LLM)。 -> **一条诚实边界**:`behaviors` 是声明式的**模块描述**,真正的逻辑代码仍由核心代码 agent 产出、再由构建编译进 bundle。源项目存的是"可维护的结构化定义",**不是一坨裸 iife**(iife = 立即执行函数表达式,这里指那种逻辑只以 JSON 字符串或 `new Function` blob 形式塞着的黑盒产物)。这正是设计要兑现的关键约束:逻辑必须以可维护的多文件源项目存在。 +> **一条诚实边界(含一处尚未兑现的缺口)**:`behaviors` 是声明式的**模块描述**,真正的逻辑代码由核心代码 agent 产出。设计的终态目标是——逻辑必须以**可维护的多文件 `src/` 源项目**存在,而**不是一坨裸 iife**(iife = 立即执行函数表达式,这里指那种逻辑只以 JSON 字符串或 `new Function` blob 形式塞着的黑盒产物)。**但这条目标当前并未兑现**:gameDefinition 仍把整段玩法逻辑塞进 `behavior.code` 这个 JSON 字符串字段,运行时用 `new Function` 直接解释执行(见 `game-runtime/src/host/gd-runtime.js:236/251`)——这恰恰是设计明令反对的"硬编码 blob",是**已知偏离终态的债**(创始人 2026-06-20 定调,见 [README §3.2](README.md))。缺的正是"gameDefinition → `src/` 工程"这一段产物侧展开:gameDefinition 只是**通往 `src/` 的中间脚手架**,必须再经一道"编译/展开成 `src/` 工程"的构建,而不是停在 JSON 里被 `new Function` 跑掉。这条债要由一道 **doc↔code 兑现门**(断言产物存在 `src/` 多文件结构、逻辑落在真实源码文件、不存在"逻辑只以 JSON 串形态存在 / 运行时 `new Function` 跑内嵌串")来守住,属后续 plan,不在本期展开。 ### 契约② 源项目 DB 存储 —— 独立的 `game_source_project` 表 -源项目落在一张**全新的独立表** `game_source_project`(走 Flyway 迁移 V18.0.0,接在已合入的 V17 之后;Flyway 已合入的脚本禁改,回滚只能写补偿迁移)。 +源项目落在一张**全新的独立表** `game_source_project`(建表走 Flyway 迁移 V18.0.0,接在已合入的 V17 之后;后续 V20.0.0 追加并发兜底唯一键 `uk_game_source_hash`,见 commit `d57032a6` U2 数据完整性,属 additive 完整性补丁。Flyway 已合入的脚本禁改,回滚只能写补偿迁移)。 **为什么必须独立建表、绝不塞进 `game_version`**:这是架构评审的明令。源项目(可维护、会被改)和打包产物(可玩、冻结)是两个物理解耦的存储面,塞在一起会破坏 GamePackage 产物的纯净性。这里曾与另一份 DB 评审的"game_version 双存"口径冲突,本架构采**独立表**口径胜出。 @@ -326,18 +326,18 @@ flowchart LR ## 9. 实测证据与验收口径 -这套架构的核心立论已在代码层**双重验证**,不是纸面设计: +这套架构的**地基**已在代码层**双重验证**,不是纸面设计——但要把验证范围说准:**双证证明的是"便宜模型能可靠产出连贯的 gameDefinition 中间表示",而非"它已是合格的终态产物"**: -1. **spike(小范围验证性实验)证地基**:便宜模型对 `source-project.schema.json` 产出连贯的游戏定义,准确率 **92–100%**,单款成本约 **¥0.011**,行为模块带真逻辑 JS。 -2. **build 段证可玩**:游戏定义经"从源构建"流程,在**真浏览器里跑过九门**——deepseek-v4-flash 满分、便宜模型 3/4 款过门,有截图实证。 +1. **spike(小范围验证性实验)证地基**:便宜模型对 `source-project.schema.json` 产出连贯的游戏定义(gameDefinition 中间表示),准确率 **92–100%**,单款成本约 **¥0.011**,行为模块带真逻辑 JS。 +2. **build 段证可玩**:游戏定义经"从源构建"流程,在**真浏览器里跑过九门**——deepseek-v4-flash 满分、便宜模型 3/4 款过门,有截图实证。**口径限定**:这是 **spike 阶段**的证据,**不是现行产线成绩**——gamedef 路尚未切为默认产线(U7 cutover 按门未切),现默认产线仍为 factory/iife 路;SAA 真全图 e2e(`SaaFullGraphE2eTest`)当前成功率 **3/5=60% < 80% 门**,端到端达标与 cutover 尚未完成(见 [MVP进度总账 §2 M2 行](../../../mvp/MVP进度总账.md) 与 [生成主线架构演进路线 cutover 阶段](../../../agent-specs/生成主线架构演进路线.md))。 -由此"改源不改包 / 可维护源项目 / 把大模型当工作室"在代码层成立。配套产出了"运行时访问约定 v0"(便宜模型只能经一个受控的 `rt` 对象访问引擎能力)和"从源构建"的装配原型。 +由此**方向已经走通**:"改源不改包 / 可维护源项目 / 把大模型当工作室"的中间表示一段在代码层成立,配套产出了"运行时访问约定 v0"(便宜模型只能经一个受控的 `rt` 对象访问引擎能力)和"从源构建"的装配原型。但**终态尚待兑现**——产物侧"gameDefinition → `src/` 工程"那一段展开仍缺(创始人 2026-06-20 定调,见 §1、[README §3.2](README.md)、[设计合理性裁决](设计合理性裁决.md)),当前 `new Function` 内嵌串属已知债,不是已闭合的终局。 **九门**是这套质检的核心,指九道确定性的真玩自动门(serve-and-play 起服务、CDP 真浏览器玩、build 构建等组成的 harness),它们的脚本是子进程复用、**禁止重写**的既有资产。 最终验收口径分三层: -- **后端线门**:编译 + 单测绿、Flyway V18 迁移绿、救场阶梯单测(5 次升档 / 8 次 giveup + dump 落盘)、trace 字节兼容、modify 局部性。 +- **后端线门**:编译 + 单测绿、Flyway V18/V20 迁移绿(V18 建表 + V20 唯一键)、救场阶梯单测(5 次升档 / 8 次 giveup + dump 落盘)、trace 字节兼容、modify 局部性。 - **引擎+前端线门**:2D 适配器把定义渲成可玩、九门真玩绿、asset 产消打通、构建确定性(字节等价)、前端创作/修改/预览真机走查。 - **联合 spike 门**:缓存透传 ✅ 已绿(76–93%);classify 准确率 ✅ 已绿(tickModel 100% / archetype 93%、约 $0.003/次);端到端门(待实施后验)= 一句话 → 工作室 → 源项目 → 构建 → 九门过门 → GamePackage → 信息流真玩,成功率对齐 MVP **≥80%**、单款 **< $1**(¥0.15 门)、modify 局部性达标。 @@ -353,11 +353,11 @@ flowchart LR 仍需在开工门逐条收口的**待解项**(诚实列出,不糊弄): -1. **源项目物理归属**:`game_source_project` 归 studio 模块还是 project 模块?**倾向 studio 模块**(create/modify 编排入口在此),待创始人/两线拍板。 +1. **源项目物理归属**:**已收口 = 归 studio 模块**(已落地——`game-module-studio` 下有 `SourceProjectApi` / `SourceProjectLandReqDTO` / `SourceProjectStatusEnum`,落库挂在 `DifyCallbackServiceImpl` 外层回调,commit `d57032a6`)。create/modify 编排入口本就在 studio,归属与之一致,不再悬而未决。 2. **后端构建桩的范围**:`RuntimeBuildServiceImpl` 本期建议只接"消费构建产物落包"路(已通),不强求它自驱 esbuild。 3. **classify→archetype 映射语义**:确认是"引导"而非"校验"。 4. **叙事失败计入救场口径**:确认 narrative 评审的 `needsRepair=true` 等价一次九门失败计入 failCount,且评审自身 LLM 失败也计入(避免抖动卡死)。 -5. **studio 路由形态**:`/studio/{create,modify,extend}` 为净新增,`create` 建议做成 `draft+generate` 的一步式封装(additive,不破现有两步路)。 +5. **studio 路由形态**:**已收口 = 三路由已建**(`/studio/{create,modify,extend}` 均已存在于 `AppStudioController`,见 line 89/97/105;`create` 一步式封装与既有 `/draft`+`/generate` 两步路并存,additive 未破存量)。残留子问题仅一处:`create` 一步式与两步式的职责边界(何时用哪条)随产线化沉淀,不必整条当未决。 --- diff --git a/docs/architecture/架构/生成引擎/开闸接线.md b/docs/architecture/架构/生成引擎/开闸接线.md index c8b16e60..449335c0 100644 --- a/docs/architecture/架构/生成引擎/开闸接线.md +++ b/docs/architecture/架构/生成引擎/开闸接线.md @@ -1,10 +1,10 @@ # 开闸接线 · 一句话入口的端到端接线 -> **这是什么**:本文讲清楚"开闸"这件事——把绘境AI 的一句话创作主链,从用户在创作页敲下一句话,一路接到这款游戏被种子用户在游戏信息流里真人试玩。它回答的不是"生成引擎内部怎么造游戏"(那条线在[生成引擎主文档](README.md)与 [SAA 编排](SAA编排.md)里),而是"造游戏这台机器已经就绪,但用户却按不动开始键——这道门为什么关着、怎么把它打开"。 -> **给谁看**:接这条链路的后端与前端工程师、做开闸决策的创始人、想看清"护城河闭环对外开放的最后一公里卡在哪"的人。 -> **怎么读**:先读 §1 拿到结论(堵点在哪、怎么解、为什么风险低),再看 §2 那张接线图建立全局,然后按需深入 §3 的现状取证与 §4 的三处协同改动。 +> **这是什么**:本文讲清楚"开闸"这件事——把绘境AI 的一句话创作主链,从用户在创作页敲下一句话,一路接到这款游戏被种子用户在游戏信息流里真人试玩。它回答的不是"生成引擎内部怎么造游戏"(那条线在[生成引擎主文档](README.md)与 [SAA 编排](SAA编排.md)里),而是"造游戏这台机器已经就绪,创作页那道『必须先选模板』的门又是怎么被拆掉、让一句话能直接驱动生成的"。 +> **给谁看**:接这条链路的后端与前端工程师、做开闸决策的创始人、想看清"护城河闭环对外开放的最后一公里走到哪了"的人。 +> **怎么读**:先读 §1 拿到结论(接线已落地、为什么风险低),再看 §2 那张接线图建立全局,然后按需深入 §3 的取证与 §4 的三处协同改动(均已上线,标注落地 commit)。 -开闸是绘境AI 护城河闭环"对外迈出第一步"的动作。后端那台生成机器已经建成、也真机验过;真正卡住的,是创作页一道**已经没有钥匙的门**——它要求用户"先选一个玩法模板",而模板这一层早已被清理掉了。本文讲的就是怎么把这道门拆掉,让一句话能直接驱动生成。 +开闸是绘境AI 护城河闭环"对外迈出第一步"的动作。后端那台生成机器已经建成、也真机验过;曾经卡住的,是创作页一道**要求用户"先选一个玩法模板"的门**——而旧的"游戏模板 / 填参"产线已随 W-CLEAN 清理退役,这道门一度失去可执行模板。本文讲的就是怎么把这道门拆掉、让一句话直接驱动生成,以及这件事**已经在 2026-06-17 落地**(commit `7534bdf9`)。 --- @@ -12,9 +12,10 @@ 把整件事浓缩成几句话: -- **后端的生成引擎和游戏信息流,已经就绪并真机验过。** 提交生成的入口(submitGenerate)、生成前的控制平面(下文 D12)、生成前的合规审查(下文 GP9)、一句话生成主路(基于 SAA 编排,已真库验)、管理员审核台、信息流翻转上架——这整条链都已打通。开闸**唯一的工程堵点,是创作页正处在一个"迁移空窗"里**。 -- **病根是一道关着、却已没有钥匙的门。** 创作页 `Create.vue` 把整条创作流**硬门控在"必须先选模板"**上:能不能点"开始生成"的判断是"选了模板 且 输入框非空",提交时也是先建一份必须带模板 ID 的草稿、再带着模板 ID 去生成。但与此同时,一项叫 **W-CLEAN** 的清理工作(把旧的"游戏模板 / 填参"产线整套拆掉)已经把玩法模板层废掉了——于是模板列表接口返回空,用户没有任何模板可选,"开始生成"按钮被永久禁用,**一句话创作主链就此结构性断裂**。 -- **接线的本质,是把创作流从"模板驱动"改成"一句话驱动"。** 这要三处协同:契约层把模板 ID 改成可选(缺省走通用生成路)、前端拆掉创作页的模板门、后端让建项目与提交生成都能接受"没有模板"的请求(通用生成路本就不依赖模板,且已真机验过)。**改动小、向后兼容、风险低**——不是要造新东西,只是拆掉一道已经没有钥匙的门。 +- **后端的生成引擎和游戏信息流,已经就绪并真机验过。** 提交生成的入口(submitGenerate)、生成前的控制平面(下文 D12)、生成前的合规审查(下文 GP9)、一句话生成主路(基于 SAA 编排,已真库验)、管理员审核台、信息流翻转上架——这整条链都已打通。 +- **曾经的堵点是创作页一道"必须先选模板"的门——现已拆除。** 旧版创作页 `Create.vue` 把整条创作流**硬门控在"必须先选模板"**上(能不能点"开始生成" = 选了模板 且 输入框非空)。而一项叫 **W-CLEAN** 的清理工作把旧的"游戏模板 / 填参"产线整套拆掉后,这道门一度失去可执行模板,一句话创作主链曾结构性断裂。**这道门已于 2026-06-17(commit `7534bdf9`)拆除**:`Create.vue` 的提交条件改为"输入非空即可"(`canSubmit = prompt.trim().length > 0 && !submitting`,见 `Create.vue:70-72`),缺省 `templateId` 归一为 `generic`。 +- **"玩法模板层"并未被废,只是品类框架而非可执行壳。** 要分清两个概念:W-CLEAN 废的是旧的"游戏模板 / 填参"产线(同质化的根源);而绘境AI 语义里的"玩法模板"= **品类引导框架**(影响生成 prompt 与脚手架,不是可执行的游戏壳),未废、有效。它已于 2026-06-18(commit `046c061d`,U7 R-TPL)以 **5 个品类**回填到模板选单(经营模拟 / 剧情互动 / 解谜闯关 / TRPG / 非遗科普),叠在 `generic` 之上(品类区分留 prompt 层 = agent 按品类写代码)。所以创作页**既能一句话直接生成、也能显式选一个品类模板**。 +- **接线的本质,是把创作流从"模板驱动"改成"一句话驱动"——这件事已落地。** 它由三处协同构成(均见 §4,已上线):契约层把模板 ID 改成可选(缺省走通用生成路)、前端拆掉创作页的模板门、后端让建项目与提交生成都能接受"没有模板"的请求(通用生成路本就不依赖模板,且已真机验过)。**改动小、向后兼容、风险低**——不是造新东西,只是拆掉一道门。 - **开闸放种子需要三件齐备,缺一不可。** 它们分属三类不同的资源,必须同时到位:本文这条接线(前端 + 后端)、把两个安全漏洞收进内网(运维侧)、以及一份创作者白名单(让创始人能亲自下场试玩)。本文只负责其中第一件——接线。 这里出现了几个内部代号,先一次性解释清楚,后文不再重复: @@ -48,7 +49,7 @@ flowchart LR 图里几处值得展开: -- **左端"拆掉模板门"是本次接线的全部工程动作所在。** 当前这里卡死的逻辑是"选了模板 且 输入非空才能提交";改完之后变成"输入非空即可提交",模板 ID 在提交时不再强制携带。 +- **左端"拆掉模板门"是本次接线的全部工程动作所在,且已完成。** 旧逻辑是"选了模板 且 输入非空才能提交";改后(commit `7534bdf9`)变成"输入非空即可提交",模板 ID 在提交时不再强制携带(缺省归一 `generic`),创作者也可显式从 5 个品类模板里选一个。 - **中段标红的 submitGenerate,是所有保护门的汇聚点。** 请求进来先过 D12 的配额 / 并发 / 背压,再过 GP9 的合规审查,全部放行才真正入队走生成。这两道门在本次接线中**原封不动**——开闸只是让请求能走到它们面前,而不是绕过它们。 - **生成走的是标绿的通用路(generic),不是任何新机制。** 这条路 W-CLEAN 之后就是主线,且已被 R3 真库验过。开闸不引入任何新的生成方式,这正是风险低的根本原因。 - **进度页与轮询已经接好,不在本次改动范围内。** 进度页 `/create/task/:taskId` 走轮询 `/aigc/task/{id}` 已经能用;采用轮询而非服务端推流(SSE),是一个有意的简化——现阶段轮询足够,流式推送是后续增强项。 @@ -56,44 +57,44 @@ flowchart LR --- -## 3. 现状:这道门确实关着(已取证) +## 3. 取证:门曾关着、现已拆除(逐条落到代码) -为了让"病根"不停留在判断,下面把现状逐条落到代码位置上。这些都是已验证事实,不是推断: +下面把"门曾经怎么关、现在怎么开"逐条落到代码位置上。这些都是已验证事实,不是推断(行内同时给出**改前**与**改后落地**): -| 环节 | 现状 | 出处 | -|---|---|---| -| 创作页提交条件 | "能否提交 = 选了模板 且 输入非空";提交时先建必须带模板 ID 的草稿,再带着模板 ID 去生成 | `game-studio/src/views/create/Create.vue:53,104-116` | -| W-CLEAN 空窗 | 模板列表接口返回空 → 创作页落到"升级中"空态、没有模板可选 → 提交按钮禁用(代码诚实地区分了"升级中"与"加载失败"两种空态) | `Create.vue:162-169` | -| 契约约束 | `/aigc/generate` 要求"输入非空 且 模板 ID 存在";生成请求体 `AigcGenerateReqVO` = 输入 + 模板 ID;建项目请求体 `ProjectCreateReqVO` 把 标题、模板 ID 列为必填 | `contracts/api-schemas/aigc.yaml:38` | -| 后端通用生成路 | 通用路 / SAA 路**本就不依赖模板**(由模型直接写码,是 W-CLEAN 之后的主线),且已 R3 真库验(一句话 → 执行轨迹与就绪度落库) | R3 verdict | -| 进度与发布 | 进度页轮询已接好;生成完发布进信息流走管理员审核台(这条链路已验过) | `aigc.yaml:55` | +| 环节 | 改前(W-CLEAN 后的空窗) | 改后(已落地) | 出处 | +|---|---|---|---| +| 创作页提交条件 | "能否提交 = 选了模板 且 输入非空";提交时先建必须带模板 ID 的草稿,再带模板 ID 去生成 | `canSubmit = prompt.trim().length > 0 && !submitting`(去掉"必须选中模板");缺省 `templateId` 传 `generic` | `Create.vue:70-72,124-144`(commit `7534bdf9`) | +| 模板选单 | W-CLEAN 后 `getTemplateList()` 返空 → 创作页落"升级中"空态(代码诚实地区分了"升级中"与"加载失败") | `getTemplateList()` 已回填 **5 品类玩法模板**(经营模拟 / 剧情互动 / 解谜闯关 / TRPG / 非遗科普);空态仅在接口异常时兜底 | `AigcTaskServiceImpl.java:87-110`(commit `046c061d`,U7 R-TPL) | +| 契约约束 | (蓝图态)`/aigc/generate` 要求"输入非空 且 模板 ID 存在";建项目把 标题、模板 ID 列为必填 | `AigcGenerateReqVO` `required:[prompt]`、`templateId` 可选缺省 `generic`;`ProjectCreateReqVO` `required:[title]`、`templateId` 同样可选 | `contracts/api-schemas/aigc.yaml:200,203` / `project.yaml:200,203` | +| 后端通用生成路 | — | 通用路 / SAA 路**本就不依赖模板**(由模型直接写码,是 W-CLEAN 之后的主线),且已 R3 真库验(一句话 → 执行轨迹与就绪度落库);缺省 `templateId` 在 `submitGenerate` 归一 `generic` | `AigcTaskServiceImpl.java:140-144` / R3 verdict | +| 进度与发布 | — | 进度页轮询已接好;生成完发布进信息流走管理员审核台(这条链路已验过) | `aigc.yaml`(task 轮询接口) | -把这张表读成一句话:**断点不在生成能力,而在创作页那道"必须先选模板"的提交门——而模板这把钥匙已经被 W-CLEAN 收走了。** 所以接下来要做的不是造新东西,是拆掉这道门。 +把这张表读成一句话:**断点从来不在生成能力,而在创作页那道"必须先选模板"的提交门;这道门已于 06-17 拆除、模板选单已于 06-18 回填 5 品类,一句话创作主链已贯通。** --- -## 4. 推荐方案:三处协同的最小接线 +## 4. 接线方案:三处协同(已落地 · commit `7534bdf9`) -接线遵循**契约先行**——先把契约改对,前后端再各自落地。三处改动如下,合起来就是开闸所需的全部工程量: +接线遵循**契约先行**——先把契约改对,前后端再各自对齐。三处改动如下,合起来就是开闸所需的全部工程量;**这三处已于 2026-06-17 同一批次落地(commit `7534bdf9`)、并随后(06-18,`046c061d`)叠加 5 品类模板回填**。 -### 4.1 契约层:模板 ID 改可选,缺省走通用路 +### 4.1 契约层:模板 ID 改可选,缺省走通用路(已改) -把生成请求体与建项目请求体里的模板 ID 都从必填改为**可选**,缺省时默认取 `generic`(通用路标识);`/aigc/generate` 的描述也从"模板 ID 存在"改成"省略则走通用一句话生成"。这一步是**向后兼容**的:老的、带模板 ID 的调用依旧能正常工作,只是新增了"不带模板 ID"这条合法路径。 +生成请求体与建项目请求体里的模板 ID 已从必填改为**可选**,缺省时默认取 `generic`(通用路标识):`AigcGenerateReqVO` 现为 `required:[prompt]`、`ProjectCreateReqVO` 现为 `required:[title]`,二者的 `templateId` 描述均已注明"可选,缺省 generic"(`aigc.yaml:200,203` / `project.yaml:200,203`)。这一步是**向后兼容**的:老的、带模板 ID 的调用依旧能正常工作,只是新增了"不带模板 ID"这条合法路径。 -### 4.2 后端:让建项目与提交生成都能接受"没有模板" +### 4.2 后端:让建项目与提交生成都能接受"没有模板"(已改) -`project.create` 与 `submitGenerate` 在收到不带模板 ID 的请求时,落到 `generic`,然后复用那条已经验过的通用 / SAA 生成路。**控制平面(D12)与合规门(GP9)不动**——它们照常在入口前把关。后端这一侧改动很小,且完全不触碰这两道保护门的逻辑。 +`project.create` 与 `submitGenerate` 在收到不带模板 ID 的请求时,落到 `generic`(`AigcTaskServiceImpl.java:140-144`:`if (!hasText(templateId)) setTemplateId("generic")`),然后复用那条已经验过的通用 / SAA 生成路。**控制平面(D12)与合规门(GP9)不动**——它们照常在入口前把关。后端这一侧改动很小,且完全不触碰这两道保护门的逻辑。 -### 4.3 前端:拆掉创作页的模板门 +### 4.3 前端:拆掉创作页的模板门(已改) -`Create.vue` 的提交条件改成"输入非空即可"(去掉模板门);原本的模板选择区,降级为**可选的品类 / 风格轻提示**(纯粹用来帮用户起步、缓解空白焦虑,不是模板,也不强制)或暂时隐藏;提交时不再强制携带模板 ID。设计体系所需的样式 token 已经就绪。 +`Create.vue` 的提交条件已改成"输入非空即可"(去掉模板门,`canSubmit = prompt.trim().length > 0 && !submitting`);模板选择区保留为**可选**——回填 5 品类后,创作者可显式选一个品类模板,也可不选直接一句话生成(缺省走 `generic`);提交时不再强制携带模板 ID(`Create.vue:124-144` 缺省传 `generic`)。设计体系所需的样式 token 已就绪。 三处的关系可以用下面这张分层图看清——契约是中间的契约层,前后端各自向它对齐: ```mermaid flowchart TB subgraph 前端["前端 · game-studio"] - FE["Create.vue
提交条件 = 输入非空
模板区降级为可选轻提示"] + FE["Create.vue
提交条件 = 输入非空
模板区 = 可选 5 品类(不选走 generic)"] end subgraph 契约["契约层 · contracts/(先行)"] CT["模板 ID 改可选
缺省 = generic
(向后兼容)"] @@ -109,22 +110,22 @@ flowchart TB ## 5. 关键权衡与待裁定项 -有四件事需要创始人拍板。它们都不是工程难点,而是产品 / 策略上的取舍: +下面四件事是产品 / 策略上的取舍,不是工程难点。**截至 2026-06-17 开闸 review,放行决策本身仍待创始人裁定**(口径见 canonical[《开闸验收门-W-G1》](../../../agent-specs/开闸验收门-W-G1.md)"开闸放行决策本身");其中 C2 / C3 的**工程缺省已随接线落地**(下文标注),开放的只剩产品姿态。如已有更新裁决,回填此处结论: -- **C1 · 发布门怎么走。** 种子创作者生成游戏后,是经**管理员审核台把关后入信息流**(当前现状,合规与质量双重兜底),还是**自助直发**?建议种子期采用**管理员把关**——GP9 已在生成前挡住违规输入,审核台再过一道人 / 质把关,放种子最稳妥;后续可以加"就绪分达标即可自助发"。 -- **C2 · 模板 ID 留还是删。** 改成**可选、默认 generic**(改动最小、向后兼容),还是彻底移除(对契约是破坏性变更)?建议**保留为可选默认**。 -- **C3 · 一句话之外要不要给提示。** 保留**可选的品类 / 风格轻提示**(不是模板,纯粹是输入增强,帮用户起步、降空白焦虑),还是只留纯粹的一句话最简形态?建议**保留可选轻提示**(不强制)。 -- **C4 · 创作者白名单口径。** submitGenerate 现有一道创作者白名单校验;种子放量时"谁能创作"的白名单口径需要明确。 +- **C1 · 发布门怎么走(仍开放)。** 种子创作者生成游戏后,是经**管理员审核台把关后入信息流**(当前现状,合规与质量双重兜底),还是**自助直发**?建议种子期采用**管理员把关**——GP9 已在生成前挡住违规输入,审核台再过一道人 / 质把关,放种子最稳妥;后续可以加"就绪分达标即可自助发"。 +- **C2 · 模板 ID 留还是删(工程已按"可选默认"落地)。** 已实现为**可选、默认 generic**(改动最小、向后兼容,commit `7534bdf9`),而非彻底移除(那对契约是破坏性变更)。剩余开放项仅是"是否将来彻底移除"的长期姿态——建议维持可选默认。 +- **C3 · 一句话之外要不要给提示(工程已按"保留可选"落地)。** 现状是**保留可选的品类模板**(U7 R-TPL 回填 5 品类,commit `046c061d`):创作者可显式选品类、也可不选直接一句话。剩余开放项仅是"模板选单的呈现形态/是否进一步简化为轻提示"的产品取舍。 +- **C4 · 创作者白名单口径(仍开放)。** submitGenerate 现有一道创作者白名单校验;种子放量时"谁能创作"的白名单口径需要明确。 --- ## 6. 爆炸半径 · 兼容性 · 风险 -这次接线的风险评估很清楚,可以放心推进: +这次接线的风险评估很清楚,且已上线、未见回退: - **契约把模板 ID 改可选 = 向后兼容**,老调用不会被破坏;通用生成路已 R3 真库验,后端改动小、不碰控制平面与合规门。 -- **前端 `Create.vue` 的改动需要前端与契约协调落地**(本文定契约,前端接线,设计体系 token 已就绪)。 -- **整体风险低**:不引入任何新的生成机制,只是"解开模板门 + 走已验过的通用路 + 契约把模板 ID 改可选"三件事的组合。回滚也简单——契约与前端各自 revert 即可。 +- **前端 `Create.vue` 的改动已与契约协调落地**(契约定义在先,前端按新契约提交,设计体系 token 已就绪)。 +- **整体风险低**:不引入任何新的生成机制,只是"解开模板门 + 走已验过的通用路 + 契约把模板 ID 改可选"三件事的组合。这三处已随 commit `7534bdf9` 落地;若需回退,契约与前端各自 revert 即可(向后兼容,回退面很小)。 --- @@ -138,4 +139,4 @@ flowchart TB --- -> **验证状态**:本文为架构策展文档,由开闸接线 review 版(2026-06-17,6c6g 出,待创始人 2 轮评审)改写而成,未改任何代码。承重硬事实——堵点 = `Create.vue` 模板门(`canSubmit = 选模板 ∧ 输入非空`,`Create.vue:53,104-116` / 空窗 `162-169`)、契约约束(`aigc.yaml:38`,模板 ID 必填 → 改可选默认 generic)、通用生成路 template-free 且 R3 真库验、进度页轮询 `/aigc/task/{id}` 已接、D12 控制平面 + GP9 合规先行两道门开闸时不动、放种子三件(接线 ∧ 2 安全洞收内网 ∧ 创作者白名单)缺一不可、四个待裁定项 C1–C4——均沿用源档结论;品牌统一为"绘境AI",无旧名残留。 +> **验证状态**:本文为架构策展文档,脱胎于开闸接线 review 版(2026-06-17,6c6g 出);承重硬事实已对照当前仓库代码复核并更新到现状——**接线三处已落地**(commit `7534bdf9`,2026-06-17):`Create.vue:70-72` 提交门改为 `canSubmit = prompt.trim().length > 0 && !submitting`(`124-144` 缺省传 `generic`)、契约 `aigc.yaml:200,203` 与 `project.yaml:200,203` 把 `templateId` 改可选缺省 generic、`AigcTaskServiceImpl.java:140-144` 缺省归一 generic;**模板选单已回填 5 品类**(commit `046c061d`,2026-06-18,`AigcTaskServiceImpl.java:87-110`);通用生成路 template-free 且 R3 真库验、进度页轮询 `/aigc/task/{id}` 已接、D12 控制平面 + GP9 合规先行两道门开闸时不动、放种子三件(接线 ∧ 2 安全洞收内网 ∧ 创作者白名单)缺一不可。待裁定项 C1–C4 截至 2026-06-17 review 仍待创始人裁定(其中 C2/C3 工程缺省已落地)。术语口径:W-CLEAN 废的是"游戏模板/填参线","玩法模板"=品类框架,未废、已回填。品牌统一为"绘境AI",无旧名残留。 diff --git a/docs/architecture/架构/生成引擎/引擎与运行时.md b/docs/architecture/架构/生成引擎/引擎与运行时.md index c5cf014d..dbc9a348 100644 --- a/docs/architecture/架构/生成引擎/引擎与运行时.md +++ b/docs/architecture/架构/生成引擎/引擎与运行时.md @@ -70,7 +70,7 @@ LittleJS(轻量级 JavaScript 游戏引擎,GitHub 开源项目)是针对 | 指标 | LittleJS | Phaser | |---|---|---| | 裸冷开时间(千元机 + 4G) | **0.54 秒** | 2.86 秒 | -| gz 包体积 | **55KB** | ≈ 500KB+ | +| gz 包体积 | **55KB** | 326.7KB(raw 1.24MB) | | 综合评分(S2 实测) | **85 分** | 82 分 | 首屏 P75(第 75 百分位用户的加载时间)目标是 **< 3 秒**,点卡可玩(从点击到可交互)目标是 **S2 常态 ≤ 2 秒**。Phaser 在千元机 + 4G 环境下的冷开时间已占去大部分预算,3G / 弱网长尾用户的出线风险显著上升,因此不适合绘境AI 的分发场景。 diff --git a/docs/architecture/架构/生成引擎/设计合理性裁决.md b/docs/architecture/架构/生成引擎/设计合理性裁决.md index 1ca391c2..0000478d 100644 --- a/docs/architecture/架构/生成引擎/设计合理性裁决.md +++ b/docs/architecture/架构/生成引擎/设计合理性裁决.md @@ -111,8 +111,8 @@ entities / components / scenes / rules 那层声明式外壳是真的,可游戏 这不是理论推测,是代码现状: - **scenes 只取 `scenes[0]`** —— 多关卡无从谈起; -- **advance(推进)是注释写明的 v0 占位空操作**(`gd-runtime.js:256`)—— 关卡推进根本没实现; -- **渲染只有 rect / circle / fill 三种形状**; +- **advance(推进)是注释写明的 v0 占位空操作**(`gd-runtime.js:265`,evalRules 内 advance 分支)—— 关卡推进根本没实现; +- **渲染只有 rect / circle / fill / sprite 四种形状**(sprite 系 U1 新增,见 §3.3)—— 而 sprite 之外仍只有三类几何色块; - **物理只有 `vx/vy + gravity` 一条单一积分路径**; - **进度只有一个全局 score 加 win/lose 二元**。 @@ -130,7 +130,9 @@ entities / components / scenes / rules 那层声明式外壳是真的,可游戏 **但九门保证的是"机制合法",中间整段"好玩"没有任何硬门或软门兜底。** 同一套九门下,一个精心设计的打砖块,和一个"摆 3 个砖块、点一下就 win"的退化品,**都能全绿**。 -"好看"那一侧更直接撞墙:**渲染器只画色块**,而源项目里那六类资产规格(`SourceProject.assets`)在整条构建链上**零消费者**——审查者 grep 过整个宿主目录,构建白名单根本不含 assets。这意味着模型即便用 mmx(绘境AI 的素材生成工具)产出了精美 sprite,当前链路也会**原样丢弃**,渲出来永远是几何色块。而对大众用户来说,"好看"是游戏信息流第一屏的入场券——**色块画面会被直接划走**。 +"好看"那一侧也撞墙,但要先把现状说准——这条在审查者初稿之后已被 **U1 资产渲染工作**(commits 73d33916+db14845d+81c1b2cf,2026-06-19)推进过一截:**资产消费端的地基已打通**——runtime 多了第四种形状 `sprite`(`gd-runtime.js:368` 走 `drawSprite`→真 `drawImage`,见 `:387`),构建链也从源项目顶层 `sp.assets` 把那六类资产规格(`assetSpec`)抽进运行时 `GameDefinition.assets` 供 `drawSprite` 消费(`build-from-source.mjs:160`),`d.ts` 与单测均已对齐。所以"渲染器只画色块 / assets 零消费者 / 白名单根本不含 assets"这三句**在现行代码里已不成立**。 + +**但"好看"的方向性结论仍未翻盘**,缺口只是从"链路根本不存在"下移成了"链路打通、宿主预载未端到端 wire":真实 sprite 显示依赖宿主 `boot.assets` 预先载入图源,而这一步当前尚未端到端接上,所以 `drawSprite` 在没有图源时会**降级成类目色占位 rect**——**当前实测产出仍以几何色块为主**。这意味着模型即便用 mmx(绘境AI 的素材生成工具)产出了精美 sprite,在宿主预载 wire 落地前,渲出来基本还是占位色块。而对大众用户来说,"好看"是游戏信息流第一屏的入场券——**占位色块画面会被直接划走**。 叠加上记忆里 `SaaFullGraphE2eTest`(端到端测试)实测**便宜模型成功率只有 60%**、连"机制稳定产出"都未达 **80% 这道门**——把"大众想玩"这个愿景级目标,押在一个"机制都还没稳、好玩好看零下限保护"的单点上,是当前架构**最大的产品风险**。 @@ -181,7 +183,7 @@ flowchart LR **改动二(高优先 · 把逻辑层往结构化拽回来):把高频 idiom 沉淀成声明式 behavior kind,让 code 字符串退场到长尾兜底。** 当前四个原型其实都能用五六个内置 behavior kind(移动 / 积分 / 碰撞 lose / 计时 spawn / clickable 那样)表达。把这些做成可组合的声明式原语库——类似成熟范式里那种"可选可配"的 PlatformerMovement / ChaseAI 件——让便宜模型从"写任意 JS"降级成"选 + 配组合",才真正吃到约束式的可靠性红利;任意 JS 逃逸口只留给少数高阶场景。这一步同时缓解**裂缝一**(逻辑可契约化了)、**裂缝四**(逃逸面缩小)和"模型成功率 60%"(选配比手写错误率低得多)。 -**改动三(高优先 · 让 assetSpec 从孤儿契约转成有消费端):** 这是打通"好看"的**唯一路径**,且它是一整条链、不是一个分支——① 渲染器加 sprite 分支(render 组件增 `spriteRef` → 引擎 `drawTile`);② 构建白名单纳入 assets,并在 rt 暴露资产解析;③ **同步把 D 门从"非白屏"升级成"非纯色块/有结构"的视觉判据**(颜色直方图复杂度 / 边缘密度),否则接了 sprite,门也测不出视觉退化,等于白接。在这条链打通前,**路线图必须明确标注"当前产出 = 色块原型,非可发行视觉品质"**,杜绝把"机制门全绿"误读成"产品就绪"。 +**改动三(高优先 · 让 assetSpec 从孤儿契约转成有消费端):** 这是打通"好看"的**关键路径**,且它是一整条链、不是一个分支。其中 ①②的地基已由 **U1**(commits 73d33916+db14845d+81c1b2cf,2026-06-19)落地——① 渲染器已加 `sprite` 分支(render 组件 `shape:'sprite'` 引 `asset` → 引擎 `drawImage`);② 构建链已从源项目顶层抽 `assets` 并入运行时 `GameDefinition.assets`、`d.ts` 与单测对齐。**剩余两块尚未兑现**:一是 **宿主 `boot.assets` 预载尚未端到端 wire**(未 wire 时 `drawSprite` 降级类目色占位,故当前实测仍多为色块);二是 ③ **D 门视觉判据仍停在"非白屏"、未升级成"非纯色块/有结构"**(颜色直方图复杂度 / 边缘密度),否则接了真图,门也测不出视觉退化,等于白接。在这两块补齐前,**路线图必须明确标注"当前产出 = 色块原型,非可发行视觉品质"**,杜绝把"机制门全绿"误读成"产品就绪"。 **改动四(中优先 · 给"好玩"立独立质量轴):** 别让九门兼任"好玩"判官。补一道便宜的启发式门——动作类看 driver 真玩时分数增长曲线是否非平非爆、失败是否可达且非秒败——给 **0–100 分而非 pass/fail**,作为信息流排序与 repair 修复的信号。把"好玩"明确从九门责任里剥离: @@ -216,9 +218,9 @@ flowchart LR | 指控 | 代码证据 | |---|---| | 逻辑核未进契约 | `source-project.schema.json`:behavior 仅声明 `id`/`trigger` + `additionalProperties: true`;运行时另接受未文档化 `js` 别名 | -| 渲染/物理/场景焊死 | `gd-runtime.js`:渲染器仅 circle/rect/fill;advance 为 v0 空操作(`:256`);单场景 `scenes[0]`;单一物理积分;裸 `new Function` | -| assets 被丢弃 + 安全靠正则 | `build-from-source.mjs`:`GAMEDEF_KEYS` 五项白名单丢弃 assets;安全靠 `LOGIC_BANS`/`CONDITION_BANS` 正则黑名单 | -| 视觉链零消费端 | host 全目录对 `sprite`/`assets`/`drawTile` 零消费者(grep 全目录) | +| 渲染/物理/场景焊死 | `gd-runtime.js`:渲染器仅 rect/circle/fill + sprite(U1 新增,sprite 之外仍三类几何);advance 为 v0 空操作(`:265`,evalRules 内 advance 分支);单场景 `scenes[0]`;单一物理积分;裸 `new Function` | +| 安全靠正则 | `build-from-source.mjs`:安全靠 `LOGIC_BANS`/`CONDITION_BANS` 正则黑名单(注:assets 已不再被丢弃——U1 后从顶层 `sp.assets` 单独抽入 `cleaned.assets`,误入 `GAMEDEF_KEYS` 才会丢) | +| 视觉链(U1 后)| host 目录对 `sprite`/`assets` **非零消费者**(`gd-runtime.js` `drawSprite`、`runtime-api-2d.d.ts`、两份单测均消费;`drawTile` 路已改 `drawImage`);剩余缺口=宿主 `boot.assets` 预载未端到端 wire,故实测仍多为占位色块 | | 机制成功率未达门 | `SaaFullGraphE2eTest` 实测便宜模型成功率约 60%,未达 80% 门 | > 总架构师对四视角分歧的拍板:**这些不是四个孤立缺陷,而是"压低输出空间换不专训"这一个范式张力的多张脸——该坚持地基、对齐名实、显式分层,而非推倒重来。** diff --git a/docs/architecture/架构/生成引擎/验收门-W-G1.md b/docs/architecture/架构/生成引擎/验收门-W-G1.md index 10e485b4..4032966c 100644 --- a/docs/architecture/架构/生成引擎/验收门-W-G1.md +++ b/docs/architecture/架构/生成引擎/验收门-W-G1.md @@ -130,7 +130,7 @@ flowchart TD P["用户 prompt"] --> CHK["SafetyCheckClient
调 safety.prompt-check
超时 8s + 至多 1 重试"] CHK -->|"safe=false"| REJ["同步拒绝
抛 UNSAFE_PROMPT
不入队"] CHK -->|"safe=true"| PASS["放行,继续生成"] - CHK -->|"超时 / 调用失败"| FC["fail-closed
抛中性 LLM_ERROR
(安全检查暂不可用)"] + CHK -->|"超时 / 调用失败"| FC["fail-closed
抛中性 AIGC_LLM_SAFETY_ERROR
(失败归类仍记 llm_error)"] style REJ fill:#f5b7b1 style FC fill:#f9e79f @@ -138,11 +138,11 @@ flowchart TD ``` - 检查结果 `safe=false`(判定违规):同步拒绝,抛 `UNSAFE_PROMPT`,不入队。 -- 检查超时或调用失败:**fail-closed**,抛一个**中性**的 `LLM_ERROR`(提示"安全检查暂不可用")。这里有两处刻意的设计——一是合规判不出来就放过,等于让违规内容在窗口期直入信息流,风险不可逆,所以宁可从严挡掉;二是用中性提示而非复用 `UNSAFE_PROMPT`,是为了避免 new-api 网关偶尔抖动时,把一个正常用户误标成"发了违规内容"。这里**不新增错误码枚举**,直接复用既有的 `LLM_ERROR`。 +- 检查超时或调用失败:**fail-closed**,抛一个**中性**的业务码 `AIGC_LLM_SAFETY_ERROR`(提示"安全检查暂不可用,请稍后重试")。这里有两处刻意的设计——一是合规判不出来就放过,等于让违规内容在窗口期直入信息流,风险不可逆,所以宁可从严挡掉;二是用中性提示而非复用 `UNSAFE_PROMPT`,是为了避免 new-api 网关偶尔抖动时,把一个正常用户误标成"发了违规内容"。注意这里的"不新增枚举"指的是**失败归类**——它复用既有的 `FailureReasonEnum.LLM_ERROR`(归因 tag 仍记 `llm_error`),不在那个跨契约共享枚举上单边加值;但 ErrorCode 这一侧确实新增了 `AIGC_LLM_SAFETY_ERROR` 这个可抛业务码,因为"提交侧同步拒绝"必须有一个独立的数值码、且文案要中性。 ### 2.3 组A 的错误码、回滚与契约 -- **错误码**:在 aigc 模块的错误码里新增了 001 子段,放三个控制平面相关的码——`QUOTA_EXCEEDED`(超配额)、`BACKPRESSURE_REJECTED`(背压拒绝)、`GENERATE_PAUSED`(已暂停)。它们都是**业务码、走 HTTP 200**——验收时要断言返回的是业务码,而**不是** HTTP 429 / 503 这种协议层状态码。 +- **错误码**:在 aigc 模块的错误码里新增了 001 子段(`1-101-001-***`),共五个码——其中 D12 三个控制平面码 `AIGC_QUOTA_EXCEEDED`(超配额)、`AIGC_BACKPRESSURE_REJECTED`(背压拒绝)、`AIGC_GENERATE_PAUSED`(已暂停),再加上 GP9 的两个合规码 `AIGC_UNSAFE_PROMPT`(真违规同步拒绝,004)与上一节那个 fail-closed 的 `AIGC_LLM_SAFETY_ERROR`(安全检查暂不可用,005)。这五个都是**业务码、走 HTTP 200**——验收时要断言返回的是业务码,而**不是** HTTP 429 / 503 这种协议层状态码。 - **回滚**:整个控制平面挂在 `aigc.control-plane.enabled` 这个功能开关(feature-flag)后面,**默认关闭 = 现行逻辑逐字不变**(全部门加 GP9 都旁路)。 - **契约与数据迁移**:合规负例语料放在契约目录 `contracts/prompts/eval/safety.prompt-check/{inputs,labels}.jsonl`,共 **10 条负例,覆盖 10 类合规红线类目**;数据库迁移 `V15.0.0__aigc_task_add_level.sql` 给任务表加 `level` 列,只增不改(additive)、默认值 1,存量数据回填为 L1。 @@ -280,4 +280,4 @@ G1 验的是 GP9 这道合规门在真环境里到底挡不挡得住。结论很 --- -> **验证状态**:本文档为架构策展文档,由开闸验收门 W-G1 canonical 活档改写而成,未改任何代码。承重硬事实——D12 四门门序、GP9 短超时 8s + 1 重试 + fail-closed、10 负例 100% 阻断、错误码 001 子段(QUOTA_EXCEEDED/BACKPRESSURE_REJECTED/GENERATE_PAUSED 走 HTTP200)、Flyway V15/V16 迁移、9d trace 必填七项、D11 权重(0.5/0.25/0.15/0.1)、首局门 3 断言(≤2s / 即时 / 60s)、G0 白名单 `["generic"]`、G1 真验 `MiniMax-M2.7` 100% safe=false / 0 落库、split-brain 修复 `703e462c` 与 firstPlay 修复 `5f6cdd0c`——均沿用源档已抽查属实的结论;品牌统一为"绘境AI",无旧名残留。 +> **验证状态**:本文档为架构策展文档,由开闸验收门 W-G1 canonical 活档改写而成,未改任何代码。承重硬事实——D12 四门门序、GP9 短超时 8s + 1 重试 + fail-closed、10 负例 100% 阻断、错误码 001 子段五码走 HTTP200(D12 三控制码 QUOTA_EXCEEDED/BACKPRESSURE_REJECTED/GENERATE_PAUSED + GP9 两合规码 AIGC_UNSAFE_PROMPT/AIGC_LLM_SAFETY_ERROR)、Flyway V15/V16 迁移、9d trace 必填七项、D11 权重(0.5/0.25/0.15/0.1)、首局门 3 断言(≤2s / 即时 / 60s)、G0 白名单 `["generic"]`、G1 真验 `MiniMax-M2.7` 100% safe=false / 0 落库、split-brain 修复 `703e462c` 与 firstPlay 修复 `5f6cdd0c`——均沿用源档已抽查属实的结论;品牌统一为"绘境AI",无旧名残留。 diff --git a/docs/architecture/运维/README.md b/docs/architecture/运维/README.md index 74c17526..39b0d018 100644 --- a/docs/architecture/运维/README.md +++ b/docs/architecture/运维/README.md @@ -17,7 +17,7 @@ - **lili-mac(创作者本地工作站)**:跑开发主会话、本地全栈 dev、快速构建迭代。它会休眠合盖,所以**不进 Tailscale 调度**,也不承担任何"门"。一条关键边界:Mac 是 ARM 架构,产出的 JAR 与前端产物架构中立可用,但 **Docker 镜像与冒烟门必须在 x86 的 mini-desktop 出**,否则镜像架构与生产不同构,等于半假的门。 - **mini-desktop(100.64.0.7)**:**权威验收机**——staging 全栈、重型构建、浏览器端到端测试都在这里,且与生产同构。它跑着 huijing 后端单体(`:48080`)、产品端 game-studio(`:4173`)、管理后台 game-admin(`:4174`),外加一套**隔离的** MySQL / Redis 容器(只供 staging 用,不与共享基建混)。 -- **mini-infra(100.64.0.8)**:**共享基建**——Gitea(自建 Git 仓)、MySQL、Redis、MinIO(对象存储)、new-api(模型网关,生成主线经它直连便宜大模型)都在这台。它**绝不跑项目 app 或重型构建**,只做底座。 +- **mini-infra(100.64.0.8)**:**共享基建**——Gitea(自建 Git 仓)、PostgreSQL、Redis、MinIO(对象存储)、new-api(模型网关,生成主线经它直连便宜大模型)都在这台。它**绝不跑项目 app 或重型构建**,只做底座。(注意:这台跑的关系型库是 PostgreSQL,与 §1.1 上一条 mini-desktop 上**隔离的** staging MySQL 不是一回事;端点口径以凭据 SoT《内网凭据与端点.md》为准。) - **6c6g**:**常驻无人值守机**——常开的 agent 编排、定时任务、后台批跑、git 操作落在这里(因为 Mac 会休眠,常驻活只能交给它)。它**禁跑重活**(重型前端构建会 OOM)。 > **注(三个名词):** "单体"指后端 13 个业务模块编译进**一个** Spring Boot 进程一起启动(不是微服务那样各自独立部署);"staging"指上线前的预演环境,与生产同构、供验收;"生产同构"指机器的 OS / JDK / 浏览器版本与正式环境一致,这样验收结果才可信。 @@ -27,6 +27,7 @@ flowchart TB subgraph dev["开发侧(不进调度)"] MAC["lili-mac · ARM
主会话 / 本地 dev / 快构建
(会休眠 · 不出镜像与门)"] end + AGIT["Aliyun Gitea · 101.200.34.71
:2222 SSH push(默认远程)
:3000 HTTP 匿名读"] subgraph tnet["Tailscale 内网"] direction TB subgraph desk["mini-desktop · 100.64.0.7 · x86(权威验收 · 与生产同构)"] @@ -36,16 +37,16 @@ flowchart TB DBL["隔离 MySQL / Redis
(仅 staging)"] end subgraph infra["mini-infra · 100.64.0.8(共享基建 · 不跑 app)"] - GIT["Gitea 代码仓"] - SQL["MySQL / Redis"] + GIT["Gitea 代码仓
(自建底座 · 非默认 push 目标)"] + SQL["PostgreSQL / Redis"] OSS["MinIO 对象存储"] NAPI["new-api 模型网关"] end SIX["6c6g(常驻无人值守)
编排 / cron / 批跑 / git
(禁跑重活)"] end - MAC -- "git push" --> GIT - GIT -- "HTTP 匿名 clone/pull" --> desk + MAC -- "git push(默认远程)" --> AGIT + AGIT -- "HTTP :3000 匿名 clone/pull" --> desk BE -- "出网调模型" --> NAPI BE --> SQL BE --> OSS @@ -56,7 +57,7 @@ flowchart TB 内网阶段**没有 docker-compose、也没有自建 CI 流水线**——开发团队版文档里那套"push 触发 CI、自动构建镜像、滚动更新"是目标态蓝图,与现实已系统性脱节(那份文档顶部自带审计横幅说明这点)。现行的部署是**人工经标准序在 mini-desktop 上完成**的,核心三步: -1. **同步代码**:代码经 `git push` 推到 mini-infra 上的 Gitea,mini-desktop 再以匿名 HTTP `clone / pull` 拉取(注意是 HTTP 只读端口,不是 SSH)。这里有两条已踩过的坑:直接 `scp / rsync` 源码树会被分类器拦下,所以必须走 Gitea 中转;大资产 push 在途时再发 push 会撞 Gitea 的 ref 锁,所以**同仓 push 要串行**,等上一笔落地再发下一笔。 +1. **同步代码**:代码经 `git push` 推到 **Aliyun Gitea**(`101.200.34.71`,默认远程,SSH `:2222`),mini-desktop 再从同一 Aliyun Gitea 以匿名 HTTP `:3000` `clone / pull` 拉取(注意是 HTTP 只读端口,不是 SSH)。mini-infra 上另有一份自建 Gitea 作底座,但**不是**默认推送 / 拉取目标——端点口径以凭据 SoT《内网凭据与端点.md》与 staging-ops playbook 为准。这里有两条已踩过的坑:直接 `scp / rsync` 源码树会被分类器拦下,所以必须走 Gitea 中转;大资产 push 在途时再发 push 会撞 Gitea 的 ref 锁,所以**同仓 push 要串行**,等上一笔落地再发下一笔。 2. **重建**:在 mini-desktop 上 `git reset --hard` 到目标分支,再 `mvn clean install` 出新的 fat JAR。收口前**以字节码实证**新 JAR 确实含本次改动(曾因"构建源 ≠ 运行的 JAR"翻过车)。高风险或整机变更走**隔离验证安全变体**:先用新 JAR 在隔离端口(如 `:48090`)起一个实例验全,**live 的 `:48080` 全程不动**,验全过才切;任一步失败就用 `/tmp` 里的备份 JAR 把 `:48080` 恢复回去。 3. **验门**:重启后先验后端 `health` 返回 200、四个游戏模板就绪、Flyway(数据库迁移工具)已 up-to-date,再跑冒烟门(下一节)。 @@ -64,7 +65,7 @@ flowchart TB 每次 staging 部署之后,跑一遍 `deploy/smoke-test.sh`——这是"部署后是否健康"的**就绪检查**(秒级,以读为主、可反复跑),**不是**深度端到端测试(深度 e2e 由 agent-loop 编排器批跑,职责不重叠)。它逐项 PASS / FAIL,末尾给总判与退出码(0 = 全过,1 = 有 FAIL),因此可以直接挂到部署脚本里当卡口: -- **默认只读 12 项**:覆盖基础设施 + 鉴权,以及五条端到端闭环链路的关键 API——①创作→生成→预览、②发布→审核→游戏流、③试玩→互动→分享、④广告→收益→钱包、⑤数据回路(遥测→质量分→feed 重排)。它验的是这五条链的关键 API 在岗、鉴权 / CORS(跨域放行)/ 质量分回灌的结构正常。 +- **默认以读为主 12 项**(唯一一笔写=建一条无副作用草稿 `POST /app-api/studio/draft`,status 0、不发布、无下游副作用,用于验创作入口 + 鉴权 + gameId 分配在岗):覆盖基础设施 + 鉴权,以及五条端到端闭环链路的关键 API——①创作→生成→预览、②发布→审核→游戏流、③试玩→互动→分享、④广告→收益→钱包、⑤数据回路(遥测→质量分→feed 重排)。它验的是这五条链的关键 API 在岗、鉴权 / CORS(跨域放行)/ 质量分回灌的结构正常。 - **`--deep` 加 1 项(共 13)**:走真实写路径,触发一次生成入队 + 遥测事件落库,按需开启。 - 一个反复出现的坑被写进了脚本注释:feed 列表项的 `packageUrl` 字段**恒为 null**,真实取游戏包要走 `GET /app-api/runtime/package/{versionId}`——别拿 `packageUrl` 当取包入口。 - 还有一条红线:**API 全绿 ≠ UI 通**。编排器旁路会掩盖 UI 缺陷,所以用户可见的波次收口前,必须另做一次真 UI 走查。 diff --git a/docs/architecture/运营/变现与单位经济.md b/docs/architecture/运营/变现与单位经济.md index 7a1fb64d..6c64e4fa 100644 --- a/docs/architecture/运营/变现与单位经济.md +++ b/docs/architecture/运营/变现与单位经济.md @@ -92,14 +92,14 @@ flowchart LR 绘境AI 的整套技术哲学是**用开源生态组合而非烧钱自研**(详见[投资人版概要设计](../系统概要设计-投资人版.md)),把钱省下来花在竞品做不了的事上——游戏流分发和变现闭环。这一节回答"那生成一款游戏到底花多少钱"。 -结论先行:**文本生成根本不是成本瓶颈。** 实测一款游戏的生成成本约 **¥0.031**(merge-prod-20 这一批 20 个创意、57 次调用、19 个被采纳的实测口径),单次 LLM 调用约 ¥0.0103。即便单价翻 10 倍也不到 1 元一款。真正可能咬人的成本是图片/音乐这类素材生成的 GPU 开销(目前 ComfyUI 未部署,零数据)和人工审核兜底,这两项列为后续单位经济埋点(内部代号 **W4**,即按游戏粒度的成本/收益数据回路)的测量项。 +结论先行:**文本生成根本不是成本瓶颈。** ¥0.031 是**旧填参路径(LLM 填参)的文本 token 下界**实测值(merge-prod-20 这一批 20 个创意、57 次调用、19 个被采纳的实测口径,单次 LLM 调用约 ¥0.0103)。注意 2026-06-12 创始人拍板「模板=引擎能力插件、每款游戏=agent 写码、填参主线作废」后,当前主线单款成本改按分档工程预算 **L1-agentic P75≤¥0.15/款【假设·待 W-G1 实测】**(约旧值 4.8 倍),不要把 ¥0.031 误读为当前主线现价。即便按 ¥0.15 的新口径,单款也远不到 1 元。真正可能咬人的成本是图片/音乐这类素材生成的 GPU 开销(目前 ComfyUI 未部署,零数据)和人工审核兜底,这两项列为后续单位经济埋点(内部代号 **W4**,即按游戏粒度的成本/收益数据回路)的测量项。 成本来源与口径有几条硬规定: -- **谁是权威源。** 成本数据**直读 new-api 的 PostgreSQL 日志表 `logs.quota`**,因为里面含每个模型的真实计费倍率(new-api 的计费引擎已经算好)。客户端用 token 数自己估算的那套(`llm_client.py`)**降级为 fallback 和交叉校验**,不再作为权威。读取工具是 `orchestrator/newapi_cost.py`。 +- **谁是权威源。** 成本数据**直读 new-api 的 PostgreSQL 日志表 `logs.quota`**,因为里面含每个模型的真实计费倍率(new-api 的计费引擎已经算好)。客户端用 token 数自己估算的那套(`llm_client.py`)**降级为 fallback 和交叉校验**,不再作为权威。读取工具是 `docs/agent-specs/2026-06-09-agent-loop-v1/orchestrator/newapi_cost.py`。 - **换算口径。** new-api 内部用一个抽象单位记额度,换算关系是 `QuotaPerUnit = 500000/USD`(这是 new-api 编译时的默认值,数据库里查不到这个 key),再乘 USD→¥ 的汇率假设 7.2。 - **new-api 能力的真实边界**(2026-06-11 实查):`users / tokens / logs / channels` 这四张表已被 917 条日志的真实流量验证过,是可信的;但 `redemptions / top_ups / subscription_*`(兑换码/充值/订阅)这些表**schema 在、却从未跑过一行数据**(这个 fork 没验证过这些功能,不要当成就绪能力)。 -- **🔴 P0 级安全红线(开通任何创作者账户前必修)。** new-api 的 3000 端口当前绑在 `0.0.0.0` 且防火墙 ufw 未启用,等于 admin API 和登录页公网可达;而 `channels` 表里存着上游厂商的 API key——一旦泄露就是直接被盗刷上游账单。**必须把 3000 端口收进内网**(用 Tailscale 内网或防火墙只放行 game-cloud 访问);另外,给每个创作者发的 per-creator token 本质是支付工具,**绝不能明文落进 `game_player` 表**。 +- **🔴 P0 级安全红线(开通任何创作者账户前必修)。** new-api 网关当前运行于 Tailscale 内网(`100.64.0.8:3000`,100.64.x.x 为 Tailscale CGNAT 段),拓扑已是「3000 收到内网」;但**开通公网 / 创作者账户前仍须确认** 3000 未直接绑 `0.0.0.0`、ufw 已对非内网封禁——因为 `channels` 表里存着上游厂商的 API key,一旦公网可达且泄露就是直接被盗刷上游账单(此项在 2026-06-16 任务普查里登记为「上线前必修」)。另外,给每个创作者发的 per-creator token 本质是支付工具,**绝不能明文落进 `game_player` 表**。 --- @@ -160,7 +160,8 @@ eCPM 取三档做敏感性扫描:**悲观 15 / 基准 30 / 乐观 60 元/千次* - **按游戏粒度的成本/收益埋点(W4 ③④,未落)。** 广告产值侧走只读聚合 `group by game_id`(`game_ad_revenue` 已有 `game_id` 列和索引,零建表);创作者应得侧要补 `game_trade_income.game_id` 打通四步链(契约 `ad.yaml` 加字段 + DTO 加 `gameId` + 数据库 ALTER 加列 + `recordIncome` 透传,缺一即断)。**这里有一条防重计数的硬约束**:所有写入和透传只能发生在"首次真实入账"分支(`firstRecord/firstBilling`),命中幂等键的回查分支绝不能累加,否则同一来源重放会把统计虚高;验收必须包含 staging 重放后按游戏汇总不变(不能只靠单测 mock)。**这里有一条架构裁决**:否决了"往 telemetry 的统计表加 ad/income 列"的做法——那条路径实为新建跨模块写接缝(telemetry 没有对应写 API、签名已冻结、trade 也不依赖 telemetry),还会把"恰好一次"的保证从 ad/trade 错位到 telemetry,得不偿失。 - **per-creator 计量 + 支付→配额同步 + 订阅/充值 + UI 购买流(推迟)。** 被支付通道真实化阻塞(ICP 备案 7-20 工作日 + 微信进件 1-3 周,3-5 周内无法端到端;订阅定价也未定)。还有一个可行性硬阻塞:new-api 的 admin API **无法替他人铸 token**(`AddToken` 硬编码成调用者自己的 UserId),得重新设计一套"凭证引导"流程;而且支付→配额**不是本地事务**,真实机制是三方对账(微信交易号 ↔ 平台订单 ↔ new-api 充值记录,后者的 `trade_no` 是 UNIQUE 幂等锚)。 -- **消费侧钱包最小闭环(新增范围,待创始人 go/no-go)。** pay 模块尚未接入单体;好在 admin 手动加余额的能力是现成的(底层框架自带 `PUT /pay/wallet/update-balance`,审计已实测接入后启动干净、零冲突)。最小闭环 = 接入 pay + admin 加余额 + 1 条内购扣款。**裁断:属 v2.0,非 MVP 必需**(MVP 关键路径仍是日历闸门 + IAA 广告闭环)。会员订阅同样未建。 +- **消费侧钱包最小闭环(新增范围,待创始人 go/no-go)。** pay 模块尚未接入单体;好在 admin 手动加余额的能力已落地(U2 R-ECON,commit `ca53a0db`:trade 侧 `game_trade_grant` 流水表 + admin 赋余额接口,审计已实测接入后启动干净、零冲突;底层框架另自带 `PUT /pay/wallet/update-balance`)。最小闭环 = 接入 pay + 复用现成的 admin 加余额 + 1 条内购扣款。**裁断:属 v2.0,非 MVP 必需**(MVP 关键路径仍是日历闸门 + IAA 广告闭环)。 +- **会员订阅(已建后端,自助购买待支付通道)。** 后端订阅域已端到端建成(U2 R-ECON,commit `ca53a0db`,迁移 V21):`game_trade_subscription`(套餐 + 到期 + 状态)+ `game_trade_subscription_grant`(每笔赋订阅一行 + `uk_biz_no` 幂等账本,经 Codex 评审修订幂等 P0)三表,admin 侧 `/subscription/grant` 赋订阅、C 端 `/subscription/mine` 查订阅态(active/plan/expire),契约 `trade.yaml` 已扩。**仍缺 = 自助购买订阅**(接 pay 下单回调开通,被日历闸门阻塞;订阅定价也未定)——本轮订阅由 admin 手动赋(运营/B 端开通)。 - **真实广告联盟(csj/gdt)+ 真实打款渠道(微信企业付款)(被合规日历闸门阻塞)。** 代码侧切真**零改业务码**:广告侧注入 `CsjAdProvider`/`GdtAdProvider` 并改配置;打款侧在 Nacos 把 `trade.payout-channel` 设为 `wxpay` 并填商户密钥即可。 --- @@ -218,8 +219,8 @@ flowchart LR |---|---| | 单位经济的全部敏感性数字(各档 eCPM、回本 DAU、提现可达性、成本结构明细) | `docs/mvp/单位经济敏感性模型.md` | | 变现链路的工程落地(模块、状态机、契约) | `.agents/skills/`(`staging-ops` / `add-business-module`) | -| 契约与数据库迁移 | `contracts/api-schemas/{ad,trade}.yaml`;迁移 V6(ad)/ V7(trade)/ V14(M4 的 `transfer_ref`);**Flyway 下一个空位 = V18**(V14-V17 已被占用,给 `game_trade_income.game_id` 加列须用 V18) | -| 成本台账工具 | `orchestrator/{newapi_cost.py, report.py}` | +| 契约与数据库迁移 | `contracts/api-schemas/{ad,trade}.yaml`;迁移 V6(ad)/ V7(trade)/ V14(M4 的 `transfer_ref`)/ V21(订阅与赋余额三表);**Flyway 现行最高 = V25,新增 ALTER(如给 `game_trade_income.game_id` 加列)须用 V26**——版本号易过时,落地前以迁移目录 `game-cloud/huijing-server/src/main/resources/db/migration/` 实时核对为准 | +| 成本台账工具 | `docs/agent-specs/2026-06-09-agent-loop-v1/orchestrator/{newapi_cost.py, report.py}` | | 商业定位与竞争战略 | [商业定位](../产品/商业定位.md) | | 完整技术资本效率叙事 | [投资人版概要设计](../系统概要设计-投资人版.md) | diff --git a/docs/architecture/运营/渠道发行.md b/docs/architecture/运营/渠道发行.md index 5aff165c..360721b1 100644 --- a/docs/architecture/运营/渠道发行.md +++ b/docs/architecture/运营/渠道发行.md @@ -144,7 +144,7 @@ flowchart LR 广告这条线,接口是 `showRewarded(slotId)`(展示一支激励视频广告,`slotId` 是广告位逻辑标识),它会映射到平台原生的 `wx/tt.createRewardedVideoAd`,把逻辑广告位 `slotId` 翻译成平台的 `adUnitId`;此外增补 `showBanner / hideBanner` 管理横幅广告。这里有一条不容造假的红线:**`rewarded=true`(用户完整看完广告应得奖励)只认平台返回的"完整观看"回调**;如果走兜底发奖,必须标记 `reward_fallback=true`,绝不能把兜底奖励伪装成真实广告收益。 -遥测(telemetry,即埋点数据采集)方面,在原有的 **9g 契约**(第 9 类的 g 子项,专管遥测字段)基础上补齐渠道专属字段:`channel`、`channelAppId`、`adUnitId`、`logicalSlotId`、`packageVersion`、`configHash`、`requestId`、`ad_event_type`、`platform_callback`、`settlement_batch`。性能监测的"七锚点"在渠道版里展开为一串时序埋点:`t_launch → t_runner_boot → t_canvas_ready → t_sdk_ready → t_config_loaded → t_first_paint → t_input_bound → t_game_start`,用来精确度量从启动到游戏可玩的每一段耗时。 +遥测(telemetry,即埋点数据采集)方面,渠道专属字段作为 **9g 转正候选** 补入——与上面 §5.1 的 9c 同属"渠道线转正后才落库"的命名,现行遥测事件仍是契约 **#5**(`events.schema.json`,这些渠道字段尚未并入)。要补的字段是:`channel`、`channelAppId`、`adUnitId`、`logicalSlotId`、`packageVersion`、`configHash`、`requestId`、`ad_event_type`、`platform_callback`、`settlement_batch`。性能监测的"七锚点"在渠道版里展开为一串时序埋点:`t_launch → t_runner_boot → t_canvas_ready → t_sdk_ready → t_config_loaded → t_first_paint → t_input_bound → t_game_start`,用来精确度量从启动到游戏可玩的每一段耗时。 ---