diff --git a/docs/agent-specs/2026-06-13-WG1-20经典轻游戏基准-review.md b/docs/agent-specs/_archive/2026-06-13-WG1-20经典轻游戏基准-review.md similarity index 100% rename from docs/agent-specs/2026-06-13-WG1-20经典轻游戏基准-review.md rename to docs/agent-specs/_archive/2026-06-13-WG1-20经典轻游戏基准-review.md diff --git a/docs/agent-specs/2026-06-15-SAA-能力API接入-dossier.md b/docs/agent-specs/_archive/2026-06-15-SAA-能力API接入-dossier.md similarity index 100% rename from docs/agent-specs/2026-06-15-SAA-能力API接入-dossier.md rename to docs/agent-specs/_archive/2026-06-15-SAA-能力API接入-dossier.md diff --git a/docs/agent-specs/2026-06-16-agent-specs目录治理-review.md b/docs/agent-specs/_archive/2026-06-16-agent-specs目录治理-review.md similarity index 100% rename from docs/agent-specs/2026-06-16-agent-specs目录治理-review.md rename to docs/agent-specs/_archive/2026-06-16-agent-specs目录治理-review.md diff --git a/docs/agent-specs/2026-06-16-生成引擎-并行编排.md b/docs/agent-specs/_archive/2026-06-16-生成引擎-并行编排.md similarity index 100% rename from docs/agent-specs/2026-06-16-生成引擎-并行编排.md rename to docs/agent-specs/_archive/2026-06-16-生成引擎-并行编排.md diff --git a/docs/agent-specs/2026-06-16-生成引擎主线-传承与演进-review.md b/docs/agent-specs/_archive/2026-06-16-生成引擎主线-传承与演进-review.md similarity index 100% rename from docs/agent-specs/2026-06-16-生成引擎主线-传承与演进-review.md rename to docs/agent-specs/_archive/2026-06-16-生成引擎主线-传承与演进-review.md diff --git a/docs/agent-specs/2026-06-17-agent-specs深度重构-plan.md b/docs/agent-specs/_archive/2026-06-17-agent-specs深度重构-plan.md similarity index 100% rename from docs/agent-specs/2026-06-17-agent-specs深度重构-plan.md rename to docs/agent-specs/_archive/2026-06-17-agent-specs深度重构-plan.md diff --git a/docs/agent-specs/2026-06-17-产品功能与技术模块-完成度与优先级总账.md b/docs/agent-specs/_archive/2026-06-17-产品功能与技术模块-完成度与优先级总账.md similarity index 100% rename from docs/agent-specs/2026-06-17-产品功能与技术模块-完成度与优先级总账.md rename to docs/agent-specs/_archive/2026-06-17-产品功能与技术模块-完成度与优先级总账.md diff --git a/docs/agent-specs/2026-06-17-固定游戏架构与SAA-agentic-studio-review.md b/docs/agent-specs/_archive/2026-06-17-固定游戏架构与SAA-agentic-studio-review.md similarity index 100% rename from docs/agent-specs/2026-06-17-固定游戏架构与SAA-agentic-studio-review.md rename to docs/agent-specs/_archive/2026-06-17-固定游戏架构与SAA-agentic-studio-review.md diff --git a/docs/agent-specs/2026-06-17-开闸-一句话入口接线-review.md b/docs/agent-specs/_archive/2026-06-17-开闸-一句话入口接线-review.md similarity index 100% rename from docs/agent-specs/2026-06-17-开闸-一句话入口接线-review.md rename to docs/agent-specs/_archive/2026-06-17-开闸-一句话入口接线-review.md diff --git a/docs/agent-specs/2026-06-17-文档整理-plan.md b/docs/agent-specs/_archive/2026-06-17-文档整理-plan.md similarity index 100% rename from docs/agent-specs/2026-06-17-文档整理-plan.md rename to docs/agent-specs/_archive/2026-06-17-文档整理-plan.md diff --git a/docs/agent-specs/2026-06-20-OpenGame对照分析与复刻缺口.md b/docs/agent-specs/_archive/2026-06-20-OpenGame对照分析与复刻缺口.md similarity index 100% rename from docs/agent-specs/2026-06-20-OpenGame对照分析与复刻缺口.md rename to docs/agent-specs/_archive/2026-06-20-OpenGame对照分析与复刻缺口.md diff --git a/docs/agent-specs/2026-06-20-架构错误根因复盘-report.md b/docs/agent-specs/_archive/2026-06-20-架构错误根因复盘-report.md similarity index 100% rename from docs/agent-specs/2026-06-20-架构错误根因复盘-report.md rename to docs/agent-specs/_archive/2026-06-20-架构错误根因复盘-report.md diff --git a/docs/agent-specs/2026-06-20-生成设计合理性-对抗审查裁决.md b/docs/agent-specs/_archive/2026-06-20-生成设计合理性-对抗审查裁决.md similarity index 100% rename from docs/agent-specs/2026-06-20-生成设计合理性-对抗审查裁决.md rename to docs/agent-specs/_archive/2026-06-20-生成设计合理性-对抗审查裁决.md diff --git a/docs/agent-specs/2026-06-21-planB-phase2-closeout.md b/docs/agent-specs/_archive/2026-06-21-planB-phase2-closeout.md similarity index 100% rename from docs/agent-specs/2026-06-21-planB-phase2-closeout.md rename to docs/agent-specs/_archive/2026-06-21-planB-phase2-closeout.md diff --git a/docs/agent-specs/agentic编排-SAA.md b/docs/agent-specs/_archive/agentic编排-SAA.md similarity index 100% rename from docs/agent-specs/agentic编排-SAA.md rename to docs/agent-specs/_archive/agentic编排-SAA.md diff --git a/docs/agent-specs/prompt治理体系-execution.md b/docs/agent-specs/_archive/prompt治理体系-execution.md similarity index 100% rename from docs/agent-specs/prompt治理体系-execution.md rename to docs/agent-specs/_archive/prompt治理体系-execution.md diff --git a/docs/agent-specs/开闸验收门-W-G1.md b/docs/agent-specs/_archive/开闸验收门-W-G1.md similarity index 100% rename from docs/agent-specs/开闸验收门-W-G1.md rename to docs/agent-specs/_archive/开闸验收门-W-G1.md diff --git a/docs/agent-specs/引擎与运行时.md b/docs/agent-specs/_archive/引擎与运行时.md similarity index 100% rename from docs/agent-specs/引擎与运行时.md rename to docs/agent-specs/_archive/引擎与运行时.md diff --git a/docs/architecture/00-系统总览图说.md b/docs/architecture/00-系统总览图说.md index 7e79c737..0182d975 100644 --- a/docs/architecture/00-系统总览图说.md +++ b/docs/architecture/00-系统总览图说.md @@ -1,13 +1,13 @@ --- date: 2026-06-22 -topic: 系统总览图说——绘境AI 架构图集的总图 + 目录(系统级 7 图 + 下钻各域) -status: 现行为主(系统级 7 图)· 架构图集入口 · 通用图例与按角色路径在此 +topic: 系统总览图说——绘境AI 架构图集的总图 + 目录(系统级 9 图 + 下钻各域) +status: 现行为主(系统级 9 图)· 架构图集入口 · 通用图例与按角色路径在此 --- # 00 · 系统总览图说 -> **这是什么**:绘境AI **架构图集**的**总图 + 目录**——整套图集按领域拆成 8 篇(本篇 00 系统总览 + 01–07 各域,每篇一个文档、各含该域全部图与讲解)。本篇是入口:先读下面七张**系统级跨域图**建立全局轮廓,再按目录下钻到某个领域那一篇。 -> **怎么读**:先看「系统级 7 图」(系统怎么分层、两条生成轨现行 vs 远期、数据怎么回流、钱怎么转、失败怎么兜、鉴权边界在哪),再按你的角色或任务选某领域下钻(见文末「按角色读」)。所有 SVG 仍在各子目录 `assets/` 下,各篇经相对路径引用、inline 渲染。 +> **这是什么**:绘境AI **架构图集**的**总图 + 目录**——整套图集按领域拆成 8 篇(本篇 00 系统总览 + 01–07 各域,每篇一个文档、各含该域全部图与讲解)。本篇是入口:先读下面九张**系统级跨域图**建立全局轮廓,再按目录下钻到某个领域那一篇。 +> **怎么读**:先看「系统级 9 图」(系统怎么分层、两条生成轨现行 vs 远期、数据怎么回流、钱怎么转、失败怎么兜、鉴权边界在哪、端到端全链怎么串、系统边界与外部依赖在哪),再按你的角色或任务选某领域下钻(见文末「按角色读」)。所有 SVG 仍在各子目录 `assets/` 下,各篇经相对路径引用、inline 渲染。 --- @@ -26,7 +26,7 @@ status: 现行为主(系统级 7 图)· 架构图集入口 · 通用图例与按 ## 0. 怎么读 + 全图通用图例 -**这份主档的形态,是「先定向、再下钻」。** 它分功能段:第一篇是**系统定向图集**,用七张系统级大图把整个系统的轮廓自顶向下讲清楚;第二到第八篇是**七个领域的全部图说**,把各域的每一张图与每一段讲解都搬进来 inline。建议的读法是:**先把第一篇七张图连讲解读完**(建立全局轮廓),**再按你的角色或当前任务,选某一两个领域的篇章下钻**(文末给了按角色推荐的路径)。读完第一篇,你应该能回答「这是个什么系统、分几层、两条生成轨现行 vs 远期怎么切、数据怎么回流、钱怎么转」;读完某领域那一篇,你应该知道「这块的图在哪、它的命门是哪条缝」。 +**这份主档的形态,是「先定向、再下钻」。** 它分功能段:第一篇是**系统定向图集**,用九张系统级大图把整个系统的轮廓自顶向下讲清楚;第二到第八篇是**七个领域的全部图说**,把各域的每一张图与每一段讲解都搬进来 inline。建议的读法是:**先把第一篇九张图连讲解读完**(建立全局轮廓),**再按你的角色或当前任务,选某一两个领域的篇章下钻**(文末给了按角色推荐的路径)。读完第一篇,你应该能回答「这是个什么系统、分几层、两条生成轨现行 vs 远期怎么切、数据怎么回流、钱怎么转」;读完某领域那一篇,你应该知道「这块的图在哪、它的命门是哪条缝」。 **单源纪律(本图集的硬约束)。** 这份图集要消灭的就是「同一张图存两处、改一处漏一处」的漂移面。在原来的多文件形态下,本图集靠「系统级图内联、领域图只链接」来守这条纪律。**本主档是单一全量主档,定位就是把所有图说 inline 在一篇**——所以原各域图说里那种「单源引用、不复制 README 的图,只给链接」的声明,在本文里改成**直接内联该 README 对应节的 Mermaid 块**(让它真渲染),并在图下注明图源;原「单源不复制」的声明段相应删去。系统级图与领域图仍是**互补、不重复**:领域图回答「这一块内部长什么样」,系统级图回答「这些块如何跨域串成一个整体」;本文不会把同一张图在不同篇章各画一份。 @@ -58,18 +58,18 @@ status: 现行为主(系统级 7 图)· 架构图集入口 · 通用图例与按 **状态码**(贯穿全图集):**现** = 现行已建 / 已实测 · **接** = 现行待接线(设计已出、代码未接) · **建** = 待建 · **缓** = 缓做(排在 W-G1 之后) · **F / future** = future-state(框架自带未部署 / 远期轨) · **废** = 决策史对照(被推翻的旧方案)。全文凡远期 / 待接 / 缓做 / 已废的元素一律虚线框 + 小标,绝不画成现行。 -> **各域特有的状态分布**(各篇沿用本图例,这里把各域整体状态分布先汇总一句,各篇开头再展开):**第一篇系统级**=现 ×5、现 + F ×2;**产品**=九图整体「现」(定义层,两处元素级 future-state);**架构**=现 ×10 + 现+史 ×1 + 现+废 ×1;**产物执行沙箱**=现 ×7(机制全建成,四处现状债元素级标注);**后端**=现 ×8(若干设计缝与桩元素级标注);**前端**=现 ×8 + 建 ×1(tier2 承载);**运营**=11 图整体「现」(元素级 mock / 待建 / 待律所诚实区分);**运维**=现 ×6 + 接 ×2(观测) + 缓 ×1(k3s)。 +> **各域特有的状态分布**(各篇沿用本图例,这里把各域整体状态分布先汇总一句,各篇开头再展开):**第一篇系统级**=现 ×5、现 + F ×3、现 + 接 ×1(共 9 图);**产品**=九图整体「现」(定义层,两处元素级 future-state);**架构**=现 ×10 + 现+史 ×1 + 现+废 ×1;**产物执行沙箱**=现 ×7(机制全建成,四处现状债元素级标注);**后端**=现 ×8(若干设计缝与桩元素级标注);**前端**=现 ×8 + 建 ×1(tier2 承载);**运营**=11 图整体「现」(元素级 mock / 待建 / 待律所诚实区分);**运维**=现 ×6 + 接 ×2(观测) + 缓 ×1(k3s)。 --- --- -## 第一篇 · 系统总览(7 张系统级图) +## 第一篇 · 系统总览(9 张系统级图) -下面七张图是这份主档的核心。它们都是**跨域才画得出、没有任何单个领域拥有**的系统级图。按「先看全局形状、再看两条生成轨、再看数据与钱与可靠性与边界」的顺序读下来,就能自顶向下建立对整个系统的认知。 +下面九张图是这份主档的核心。它们都是**跨域才画得出、没有任何单个领域拥有**的系统级图。按「先看全局形状、再看两条生成轨、再看数据与钱与可靠性与边界、最后把全链串起来并钉清系统边界」的顺序读下来,就能自顶向下建立对整个系统的认知。 -> 本篇内联的图 1–6 是顶层 `docs/architecture/assets/` 下的系统级 SVG(路径保持 `assets/xxx.svg`);图 7 是 Mermaid,直接内联。 +> 本篇内联的图 1–6 与图 8–9 是顶层 `docs/architecture/assets/` 下的系统级 SVG(路径保持 `assets/xxx.svg`);图 7 是 Mermaid,直接内联。 ### 图 1 · 六域生命周期全景〔SVG·架·现〕 @@ -155,7 +155,23 @@ flowchart TB 这张图最该让人看出的,是**两条跨角色的转化回路**:一条是玩家「发起同款」跳转工作坊变成创作者(P-FED-12)——它把「玩游戏的人」转化成「做游戏的人」,是网络效应护城河的产品载体;另一条是 B 端客户的询单经商务 / BD 流转成定制单据。还有一处系统级衔接:运营对内容的审核 / 降权处置会联动 feed 曝光(影响玩家看到什么),管理员对创作者的白名单置位(set-creator)决定一个 C 端用户能不能创作——这两条「B 端动作影响 C 端体验」的链路,正是图 6 那条「权限在后端强制」与图 4 那条「feed 重排」的人侧投影。这张图没有现行 / 远期的灰度,它是当前的角色与端的真相;每个角色的完整旅程(创作者旅程、玩家旅程)在产品篇,每个端的视图地图在前端篇。 -> **第一篇状态分布**:现 ×5、现 + F ×2(图 2 含 future-state 中间件与「接」可观测、图 3 含远期 tier2 轨)。系统级图与领域图**互补不重复**:本 7 图都是跨域才画得出、无单域拥有的图。**远期/已废标注**:tier2 轨(图 3,= AgentScope+Phaser)= 远期·待 spike 虚线、远期可能与左轨收敛为一条;Nacos/RocketMQ(图 2)= future-state 未部署;观测(图 2)= 接;收益回流语料(图 4)= 远期·待建;打款 mock(图 5)= 现状桩;网关双校验(图 6)= 未来态;Dify/OpenGame/玩法填参模板/15KB = 已废;gameDefinition JSON 数据壳 = 中间脚手架·正迁移成直接生成 `src/` 源项目;均不画成现行终态。 +### 图 8 · 端到端跨域全链泳道〔SVG·流·现 + F〕 + +![图 8 端到端跨域全链泳道](assets/07-端到端全链泳道.svg) + +这张图是整本图集里**最该第一个读**的一张:它把前面那些分门别类的领域图,拼成了一条从「创作者敲下一句话」一直跑到「数据回流让 feed 重排」的完整系统链。它用八条横向泳道——创作者、game-studio、aigc + SAA、compliance、project + feed、玩家、telemetry、ad + trade——各占一条道,让你能顺着一个编号(①到⑮,外加钱流的 Ⓐ 到 Ⓓ)从头走到尾,看清每一步落在哪个域、交给谁、产出什么。主链是这样跑的:创作者一句话(①)经 studio 提交(②),aigc 建任务(③)进入 SAA 十六节点编排(④),九门验收通过后 emit 出包(⑤)回写成 project 草稿(⑥);创作者提交发布(⑦)触发 compliance 锁风门裁决(⑧),只有 pass 才让游戏 PUBLISHED 入 feed(⑨);玩家在竖屏游戏流里刷到(⑩)、即点即玩并互动(⑪);这些行为经埋点上报进 telemetry 聚合(⑬)、算出 0–100 的质量分(⑭),再把 feed 重新排序(⑮),把更好的游戏推回到玩家眼前——这条绿色的回流箭头,正是把一条线性的价值链弯成飞轮的地方。下半部还叠了一条与主链并联的钱流:玩家试玩时触发游戏内广告曝光(Ⓐ),经 ad 模块计费落账(Ⓑ),由 trade 按 `source_ref` 对账分账(Ⓒ),最终结进创作者钱包(Ⓓ)。 + +新人能从这张图看出几件单看任何一张领域图都看不全的事。其一,**判断「系统有没有缝」,就是看相邻泳道的交接处对不对得上**——出包能不能落成草稿、草稿能不能提审、裁决能不能控制入流、互动能不能回流成排序,任何一处接不上,闭环就断了;这张图把所有交接点都画在了一条线上,据图就能逐个核对。其二,**合规门是整条链的上线总闸**:图上那条红线写着「pass 才入流」,游戏造得再好,过不了锁风门也进不了 feed,这是平台不碰红线的硬约束。其三,**现状必须诚实地读**,不能因为画出来了就当全是实的:图里用橙色虚线小标点出了两处现状桩——feed 的游标分页现在恒返第一页、Redis 候选集还是增长期形态,广告侧的 `provider` 还是 mock、真广告 SDK 要等渠道落地才接;提现打款那一格更标了红线,缺渠道时必须 fail-fast、绝不发假钱。其四,右上角那个紫色虚线框是 **tier2 富游戏轨**——它走的是 AgentScope 自治加 Phaser 无头的另一套范式,目前只有设计、待 0 号 spike,**不在这条现行链上**;它换的只是「游戏内容怎么造出来」,造出来之后仍旧汇进同一条上线与发行的公共件。把这些边界一眼标清,正是为了让据图做评审的人,既能顺着主链确认闭环跑得通,又不会把桩和远期误当成已经建好的现行。 + +### 图 9 · 系统上下文与外部依赖边界〔SVG·架·现 + 接〕 + +![图 9 系统上下文与外部依赖边界](assets/08-系统上下文.svg) + +这张图回答一个新人最先想问、却常常没有一张图能直接回答的问题:**绘境AI 这个系统,边界到底画到哪里、它对外又依赖谁**。它用 C4 模型最外层的「系统上下文」视角来画——正中间一个大框是绘境AI 平台本身(内网单体:game-studio 产品前端、game-admin 管理后台、game-cloud 后端十三模块,以及它自建的 MySQL / Redis),左边是站在系统边界之外、会来使用它的四类外部用户(创作者、玩家、运营 / 管理员、B 端 / IP 客户),右边则是平台要去调用、同样在边界之外的外部依赖系统。这张图刻意不画系统内部的模块怎么拆、调用怎么串(那些在架构图和泳道图里),它只回答「边界」这一件事,所以一眼就能让人建立「哪些东西是我们自己的、哪些是外面的」这个最基础的方位感。 + +这张图真正的价值,在于它给每一个外部依赖都标了**接入度三态**,而不是把它们一律画成「已经连上了」。现行真正已经联通在调用的(绿色实线框、标「已接」)只有两类:一是生成与素材这条供给线——new-api 网关后面的便宜大模型(DeepSeek / MiniMax)和 mmx-cli 的素材生成,它们是护城河运转的燃料,已经在 mini-infra 上接通;二是代码与存储的底座——Aliyun Gitea 代码仓和 MinIO 对象存储。而变现侧的几条线——广告联盟(穿山甲 CSJ / 优量汇 GDT)、微信 / 抖音小游戏渠道、支付商户、短信服务——全部是「待接」或「远期」,用橙色或紫色虚线框画出,绝不能误读成已经接好。新人看到这里应该立刻反应过来:**这恰恰是运营域那条「合规闸门是总闸」的判断,投影到依赖边界上的样子**——所有能把钱赚回来的外部线,都卡在 ICP 备案、广告资质、渠道备案锁、短信签名报备这些日历驱动的闸门后面,一秒也压不动,所以它们现在只能是桩或 mock。最后一层意思藏在边界的切法里:平台把那些「耗时但不构成差异化」的能力——后台框架、大模型、引擎、素材生成——统统用外部现成件顶上,系统边界内只留真正的护城河(生成编排、流量分发、收益闭环、数据飞轮);而且出网一律只走受控网关、上游 key 不裸暴露、游戏侧 CSP 直接禁网,这等于把「系统边界」同时当成一道「安全边界」来守。看懂这张图,你就同时知道了这个系统「大在哪、靠谁、又把哪几道门关在了外面」。 + +> **第一篇状态分布**:现 ×5、现 + F ×3、现 + 接 ×1(图 2 含 future-state 中间件与「接」可观测、图 3 含远期 tier2 轨、图 8 含桩与远期 tier2 轨、图 9 外部依赖三态)。系统级图与领域图**互补不重复**:本 9 图都是跨域才画得出、无单域拥有的图。**远期/已废标注**:tier2 轨(图 3 / 图 8,= AgentScope+Phaser)= 远期·待 spike 虚线、远期可能与左轨收敛为一条;Nacos/RocketMQ(图 2)= future-state 未部署;观测(图 2)= 接;收益回流语料(图 4)= 远期·待建;打款 mock(图 5 / 图 8 / 图 9)= 现状桩(缺渠道须 fail-fast);网关双校验(图 6)= 未来态;feed 游标分页 / 真广告 SDK(图 8)= 现状桩;广告联盟 / 微信抖音渠道 / 支付商户 / 短信(图 9 外部依赖)= 待接或远期(被 ICP / 资质 / 备案锁 / 短信报备等日历闸门阻塞)、阿里云 OSS 生产 = 远期(MinIO 内网已接);Dify/OpenGame/玩法填参模板/15KB = 已废;gameDefinition JSON 数据壳 = 中间脚手架·正迁移成直接生成 `src/` 源项目;均不画成现行终态。 --- diff --git a/docs/architecture/01-产品图说.md b/docs/architecture/01-产品图说.md index be5cdacd..b5b514c1 100644 --- a/docs/architecture/01-产品图说.md +++ b/docs/architecture/01-产品图说.md @@ -187,6 +187,40 @@ sequenceDiagram 整张图最该让人看清的是**底部那一栏的诚实切分**:护城河的四层(数据壁垒 / 网络效应 / 资产壁垒 / 合规壁垒)全部用紫色虚线框 + 「未来式」小标画出,因为它们是**要在窗口期(6-12 个月)里点燃的、而不是已经有的**——短期没有护城河,有的是上面那三样不公平起跑,融资就是点火的燃料钱。这层切分必须看清:如果把飞轮、网络效应、生态资产画成「已有的墙」,就违背了护城河话术的红线。要补充一处源档里的设计缝(图上未展开、读图时一并记住):对外话术与内部判断有一处**刻意的时间差**——护城河话术 B3 对外仍说「复杂引擎用 Cocos / 不自研引擎」,但内部已改判 tier2 富游戏自治轨走 AgentScope(Python 自治 ReAct)+ Phaser/Pixi 全无头引擎、Cocos 收窄到 3D / 复杂场景 / 渠道导出轴(仍是有效决策、非废弃);因为 tier2 还在 0 号 spike 待验,没验证的东西不对外背书,等 spike 过了再同步对外口径。这处「内外口径暂不一致」是有意为之、有据可查,不是漏洞。 +### 产品图 10 · B端客户旅程〔Mer新·时·现〕 + +这张图补上前面缺的**第三条角色旅程**。图 7 画了创作者(做游戏的人)、图 8 画了玩家(玩游戏的人),但绘境其实有**三类核心角色**——还有一类是 **B 端 / 企业客户**(品牌方、文旅景区、教育机构),他们不是来自己做游戏、也不是来刷着玩,而是**带着一笔预算来下单定制**。这条线之所以重要,是因为它在商业定位里被排成「**三线变现的现金线 · 首位**」(商业定位 §4):B 端项目收费 + 分成、版号争议最小、回款最早,是 MVP 阶段最早能把真钱赚回来的一条线。所以这张旅程不只是补全角色,它画的正是「现在就能产生现金」的那条业务主线长什么样。 + +```mermaid +sequenceDiagram + autonumber + actor B as B端客户(品牌/文旅/教育) + participant BD as 运营即商务BD(平台侧) + participant TPL as 分场景模板库 + demo(P-BIZ-02) + participant FRM as 需求表单(P-BIZ-01) + participant DSH as 定制进度看板(P-BIZ-03) + participant ACC as 交付验收(P-BIZ-04) + + B->>BD: 询单 / 留下线索(品牌营销 P-BIZ-08 · 文旅 P-BIZ-12 · 教育 P-BIZ-10) + BD-->>B: 接洽 + 引导进场景模板库 + B->>TPL: 浏览分场景模板库、看可交互 demo + Note over B,TPL: ⚠️ 现行=能浏览模板/看 demo 的最小可用面;「32 模板 / 15min 自动出案 / demo 自动生成」是愿景示意、不是产品承诺 + B->>FRM: 提交需求表单(行业/玩法/素材/交期/预算) + FRM-->>BD: 表单进入商务工作流 + BD-->>B: 平台报价(当前=人工报价,非自动出案) + alt 报价确认、立项 + B->>DSH: 通过定制进度看板跟进制作进度 + DSH-->>B: 进度状态推送(需求确认→制作→内测→交付) + B->>ACC: 试玩 / 反馈 / 确认 + ACC-->>B: 签署交付验收 → 项目收费 + 分成回款 + end + Note over B,ACC: 教育子场景另带 学生账号与防沉迷(P-BIZ-11);P-BIZ-05~07/09 等加厚服务为 P1 远期 +``` + +这张图把 B 端旅程画成「**询单 → 看模板与 demo → 提需求表单 → 平台报价 → 进度看板跟进 → 试玩验收签署**」六段,对应需求清单 BIZ 域的四条 P0 核心(P-BIZ-01 需求表单、P-BIZ-02 模板库与预览、P-BIZ-03 进度看板、P-BIZ-04 交付验收)。新人读这张图能看出三件事。其一,**这条线有两个端在协作**:左边是 B 端客户(下单方),右边那条 BD 泳道是「运营即商务BD」——也就是平台侧的商务/运营角色,他承接询单、引导进场景库、出报价、推进交付;这正好印证了图 4 里强调的「端属性」概念,B 端定制域的需求横跨「B端」与「运营」两个端,不是单端功能。其二,**子场景是分行业的**:同一套定制流程下挂着品牌营销(P-BIZ-08)、文旅景区(P-BIZ-12)、教育课程(P-BIZ-10,且教育还连着学生账号与防沉迷 P-BIZ-11)等不同垂直场景,它们共用「表单→报价→进度→验收」这条主干、只是行业内容不同。其三,它和图 7、图 8 的关系是**三条角色旅程并列又交汇**:创作者旅程和玩家旅程在「游戏进信息流」处交汇成消费闭环,而 B 端旅程是另起的一条 B2B 业务线,它不进 C 端信息流,产出的是「项目交付 + 现金回款 + 标杆案例」,反过来给整个平台供血(对应商业定位里「B 端现金线供血 → 滚成数据飞轮」的主轴)。 + +要点出的**设计缝**是这张图最该守的诚实纪律,也是它与图 9 一脉相承的地方——**愿景与现行建设度必须切开**。需求清单里 demo 那套高调呈现的「32 个分场景模板库 / 15 分钟自动出案 / 可交互 demo 自动生成」,经创始人 2026-06-22 历史回收判定明确为**愿景示意、不是产品承诺**:B 端当前真实建设度只有**轻量需求表单 + 人工报价**,离「32 模板 / 15min 自动出案」差距很大。所以图里在「看模板与 demo」和「平台报价」两处都用 Note 把现行最小可用面与那串愿景数字切开——P-BIZ-02/03/04 在产品口径上确实是 P0(B 端能选模板预览、看进度、完成验收签署这个最小面必须可用),但「32/15min 自动」那套数字不作为验收指标、不对 B 端客户承诺。读这张图时务必记住:它画的是「B 端定制这条业务线的产品形态与现金价值」,不是「自动出案能力已经做好了」;把愿景数字当成已交付,既会误导对内排期,也会在对 B 端客户做预期管理时埋雷。 + > **产品域图清单与状态表** | # | 图名 | 家族 | 形式 | 状态 | 覆盖内容 | @@ -200,8 +234,9 @@ sequenceDiagram | 7 | 创作者旅程 | 时 | Mer新(内联) | 现 | 挑素材→一句话生成→预览迭代→发布→看收益;生成迭代闭环 + 外部渠道远期标注 | | 8 | 玩家旅程 | 时 | Mer新(内联) | 现 | 刷feed→即点即玩→点赞分享→发起同款;即点即玩差异化 + 同款回路接回创作者旅程 + 广告 SDK 待接 | | 9 | 商业定位与护城河一图 | 讲 | SVG新 | 现 | 一句话定位 + 差异化闭环 + 竞争格局 + 资本效率 + 四层护城河(虚线·未来式,诚实不假装有墙)| +| 10 | B端客户旅程 | 时 | Mer新(内联) | 现 | 询单→看模板与demo→提需求表单→平台报价→进度看板→试玩验收签署;第三类核心角色(B端/企业客户)+ 现金线首位 + B端/运营双端协作 + 品牌营销/文旅/教育子场景;「32模板/15min自动出案」愿景≠承诺(诚实切分,现行=轻量表单+人工报价) | -> **状态分布**:九张图整体状态全为 **现**(产品定义层)。其中三处以**元素级虚线**标出 future-state、绝不画成现行 MVP 范围:图 2 / 图 5 的**第二条生成轨(tier2)与治理层**(待 0 号 spike·未落代码·尚无正式 P-id)、图 9 的**四层护城河**(要在窗口期点燃·未来式·非已有)。**产品定义 ≠ 建设进度**:本图说画的是「产品要提供什么」(55 P0 = 验收口径),不是「代码建到哪一步」。55 条 P0 各自的真实完成度(真端到端 / 半真 / 桩)以 `需求模块映射.md` 现状快照与 `docs/mvp/MVP进度总账.md` §2 矩阵为唯一 SoT。**防漂移门**:本文 frontmatter 记产品域五份源档的 commit hash(README @ 366a44b4、需求清单 @ 15b707fd、需求模块映射 @ 7ecd616e、商业定位 @ f4ee2310、护城河话术 @ 5cadf504),源档变更即比对。 +> **状态分布**:十张图整体状态全为 **现**(产品定义层)。其中三处以**元素级虚线**标出 future-state、绝不画成现行 MVP 范围:图 2 / 图 5 的**第二条生成轨(tier2)与治理层**(待 0 号 spike·未落代码·尚无正式 P-id)、图 9 的**四层护城河**(要在窗口期点燃·未来式·非已有)。**产品定义 ≠ 建设进度**:本图说画的是「产品要提供什么」(55 P0 = 验收口径),不是「代码建到哪一步」。55 条 P0 各自的真实完成度(真端到端 / 半真 / 桩)以 `需求模块映射.md` 现状快照与 `docs/mvp/MVP进度总账.md` §2 矩阵为唯一 SoT。**防漂移门**:本文 frontmatter 记产品域五份源档的 commit hash(README @ 366a44b4、需求清单 @ 15b707fd、需求模块映射 @ 7ecd616e、商业定位 @ f4ee2310、护城河话术 @ 5cadf504),源档变更即比对。 --- diff --git a/docs/architecture/02-架构图说.md b/docs/architecture/02-架构图说.md index 57fcde94..6eaa7e2d 100644 --- a/docs/architecture/02-架构图说.md +++ b/docs/architecture/02-架构图说.md @@ -324,6 +324,61 @@ flowchart TB 这张图最该让人看出的是「owner 模式怎么消灭灰色地带」:锁风门由 compliance 当 owner(因为它是全平台的内容安全与裁决中枢),但它**不自产**风格检测原子——原料来自 aigc 和 ip,裁决挂到 project,三方各司其职、没有谁越界。这正是图 5 模块依赖里那条 compliance ↔ ip ↔ aigc 环路的真实含义。要按状态读的设计缝有一处:**专区 Zone 在 MVP 阶段还没有独立的数据库实体,是用字段承载的**(有意简化),所以图里 Zone 实体那一格画的是「逻辑归属」、不是一张独立表——这是 project 模块已知的、有意为之的缺口,不是设计漏洞。锁风门则有一处真实的合规债(虽不在本概念图的范围内、但读图时该知道):compliance 的核心检测原子目前全是桩、恒返回 pass,意味着锁风门框架虽真、自动拦截能力还没硬化,这是放量/接广告/上渠道前必须补的。 +### 架构图 13 · 13 逻辑模块 → 单体物理打包 / 运行拓扑〔SVG新·部署·现〕 + +![架构图 13 13 逻辑模块 → 单体物理打包/运行拓扑](架构/assets/arch-13-逻辑物理拓扑.svg) + +这张图专门破除新人最常见的一个误解:**「13 个模块 = 13 个微服务」是错的**。前面图 4、图 5 给的是「逻辑视图」——13 个模块按领域边界各自独立、单向依赖;但它们物理上并不是 13 个进程。这张图把「逻辑独立」与「物理单体」并排画出来,中间用一条「jar 聚合」的漏斗把两者连起来,让人一眼看清三件事。第一,**逻辑视图**(左栏):每个模块是一个独立领域,且都拆成 `-api`(只声明 DTO + Feign 接口,跨模块只认它)和 `-server`(实现)两段式 jar,模块间只经对方的 `-api` 单向调用、零反向依赖。第二,**物理视图**(中栏):这 13 个 `-server` jar 连同 Huijing 基座 jar 全部编译进**同一个物理 JAR `game-server`**,由一个 main 启动、跑在**同一个 JVM 进程**里,共用同一份 `application.yaml` 和同一套 MySQL/Redis 连接池;模块间调用此时其实是进程内的方法调用、根本不走网络。第三,**Spring Profile 是这套单体的「开关板」**:哪些 `-server` 进 Spring 上下文由 profile 控制,其中 **pay 模块的启动器被显式注释排除**出装配——这正是图 4 散文里说的「pay 是 Huijing 原生模块、当前未接入单体启动器」在物理层面的样子。 + +这张图最该让人据图记住、也最容易被误读的两点:其一,**「逻辑独立」不等于「物理多进程」**——它们是同一个进程里逻辑上分得很清的几块,而不是各跑各的;正因为是单写、一份代码一份库,所以**不存在 split-brain**(那种「两套代码各跑各的、数据互不一致」的脑裂状态)。其二,右栏那条紫色虚线框是**远期愿景、不是现行架构**:模块间的单向依赖方向,就是未来从单体拆成微服务时的天然切割线——依赖边界即拆分边界,且因为每模块已是 `-api`/`-server` 两段、依赖单向无环、Nacos(注册发现)与 RocketMQ(异步解耦)框架又已自带,真到拆分那天几乎零返工。但务必看清:右栏画的四簇微服务只是「切割线长这样」的示意,**当前一个都没拆、也不预先实现**,现在仍然是中间那个单进程;拆几个、何时拆,要等流量和团队涨到单体压不住时再按当下情况定,不是越早拆越好。 + +### 架构图 14 · 契约族 × 跨域接缝:生产者 → 消费者流向〔Mer新·协议契约·现〕 + +图 11 已经把契约族「有哪几类、各落哪、各算第几」的静态清单画清了,但它没回答一个新人同样关心的问题:**每一类契约具体在 govern 哪一条跨域 handoff,谁产、谁消?** 这张图就补这个动态视角——把几条最关键的跨域交接拎出来,在每条交接线上标明「是被哪类契约钉死的」。读法是:方框是域/角色,**实线箭头是数据/产物的流向**,箭头上的 `[契约]` 标签就是这次交接所遵循的契约。沿着主链看:创作侧 **studio 产出草稿 →(GamePackage 契约)→ runtime 把它编译成可运行包 → 在 iframe 沙箱里预览 → 通过后发布**;生成链路里,**aigc / SAA 生成节点调模型时遵循 prompts 契约**(第 8 契约,Git Registry + 8 阶段);游戏跑起来后,**宿主 game-studio ↔ 游戏之间靠 SDK 契约的 postMessage 双向通信**(这是平台向游戏注入能力的唯一通道);**SDK 上报与前端埋点 →(events 契约)→ telemetry 摄取 → 喂给看板**;广告位则**由 ad-slot 契约 govern**,从 ad 模块经 SDK 的 `Plugin.Ad` 在游戏内呈现、再把曝光回流计费。 + +这张图最该让人看懂的,是**契约到底「钉」住了什么**:每一条跨域 handoff 都不是口头约定,而是被一份具体的 schema/接口契约锁死了双方的数据形状,所以 studio 不必知道 runtime 内部怎么编译、telemetry 不必知道事件从哪个前端来——大家只认中间那份契约。这正是「契约先行、并行解耦」能成立的根:契约就是跨端的数据边界。有两处状态要顺带读清:**Dify I/O 契约(图里标灰)是唯一已废的一类**(对应被推翻的蓝图原案,现行生成主线是 new-api,见图 2/3),它不再 govern 任何现行 handoff,画在这里只是为了让人知道「读到它别当现行接线面」;另外,GamePackage 契约链里有一条跨模块对齐的硬约束——**`package_url`/`checksum`/`bundle_size` 这些编译产物字段的权威写者是 runtime,aigc 只回填生成元数据、不写这些字段**,这条边界本图用小注标出,避免两个域抢写同一字段。 + +```mermaid +flowchart LR + STU["studio
创作编排 · 产草稿"] + RT["runtime
编译 / 沙箱 / 发布"] + PREV["iframe 沙箱预览"] + PUB["发布上线"] + AIGC["aigc / SAA 生成节点"] + LLM["便宜 LLM
(经 new-api)"] + HOST["game-studio 宿主"] + GAME["游戏(沙箱内)"] + TEL["telemetry
摄取 / 聚合"] + DASH["数据看板"] + AD["ad 模块
植入 / 计费 / 归因"] + SDKAD["游戏内广告位
(SDK Plugin.Ad)"] + + STU -->|"#4 GamePackage 契约
(package_url 权威=runtime)"| RT + RT --> PREV --> PUB + AIGC -->|"#8 prompts 契约
(registry + 8 阶段)"| LLM + LLM -.->|"#6 Dify I/O 契约 = 废
(现行走 new-api)"| AIGC + HOST <-->|"#3 SDK 契约
postMessage 双向"| GAME + GAME -->|"#5 events 契约
(SDK 上报)"| TEL + HOST -->|"#5 events 契约
(前端埋点)"| TEL + TEL --> DASH + AD -->|"#7 ad-slot 契约"| SDKAD + SDKAD -->|"曝光回流(events)"| TEL + + classDef act fill:#dcfce7,stroke:#16a34a,stroke-width:1.5px; + classDef dead fill:#fff7ed,stroke:#d97706,stroke-width:1.4px,stroke-dasharray:6 4; + class STU,RT,PREV,PUB,AIGC,LLM,HOST,GAME,TEL,DASH,AD,SDKAD act; +``` + +*(图源:架构/契约总览.md「契约全景」表 + 架构/README.md §2.1 跨模块对齐;契约编号取 contracts/README 主轴 #3–#8,Dify #6 已废)* + +### 架构图 15 · 13 模块 真 / 桩 / 未建 状态热力图〔SVG新·架·现〕 + +![架构图 15 13 模块真/桩/未建状态热力图](架构/assets/arch-14-模块状态热力.svg) + +这张图在图 4 那张「四簇 13 模块」的聚类底图上,叠加每个模块**当前真实建到了什么程度**:用颜色编码状态(绿 = ✅ 完成、真端到端可验收;黄 = 🟡 部分、有壳/半真/部分接线;灰虚线 = ◻ 特殊、seam 寄宿或未接单体;红 = 🔴 纯未建,当前为 0),并在每一块里都点明「它最大的那道缺口」——让人不必翻完整张状态表,就能一眼看出哪里能放心用、哪里是要还的债。当前分布是:**✅ 完成 5**(project / telemetry / ad / trade / community)、**🟡 部分 6**(aigc / runtime / feed / studio / compliance / biz)、**◻ 特殊 2**(ip seam 寄宿 / pay 未接单体)、🔴 纯未建 0。每块的最大缺口也直接标在图上,例如 compliance 的检测原子恒返回 pass、feed 的游标分页是桩、runtime 的真实编译引擎是桩、aigc 的 W-G1 worker 尚未接为默认产线。 + +读这张图必须守住一条口径铁律,图顶也专门画了一条:**本图的状态以 `docs/mvp/MVP进度总账.md` 为准,当结构 / 实现 / 状态三者冲突时,优先级是「状态 > 实现 > 结构」。** 这意味着颜色代表的是「实际状态」而非「结构权威」——图 4 给的是「应该怎么切」(结构),这张图给的是「现在建到哪」(状态),两者口径不同、不可混用。这张图最该让评审据图盯死的是两道债:其一,**compliance 的核心检测原子全是桩、恒返回 pass**,意味着发布链对违规内容目前零自动拦截、纯靠人工兜底,这是放量 / 接广告 / 上渠道前必须硬化的「合规死锁」;其二,**aigc 的 W-G1 worker 还没接为 staging 默认产线**,而 aigc 正是平台护城河的关键路径。还有一类「卡在闸门」的状态值得单独记:ad / trade / pay 卡的不是代码——它们的业务逻辑大多已是真的、有几十个单元测试——而是 ICP 备案 / 支付进件 / 广告审核这类**不可压缩的日历闸门**,策略是先把逻辑建好、闸门到位即接。最后提醒一句:这张图是某一次的状态快照,颜色和缺口会随开发推进而变,任何时刻都应以进度总账的真 / 桩 / 未建为最高口径,本图只承担「一眼可读的空间总览」这一职。 + > **架构域图清单与状态表** | # | 图名 | 家族 | 形式 | 状态 | 覆盖内容 | @@ -340,8 +395,11 @@ flowchart TB | 10 | 工程治理(幂等/SLO/可观测) | 讲 | SVG新 | 现 | 幂等矩阵 + 三服务 SLO/Error Budget + 四路可观测(落地态=接)+ 三关键技术风险及应对 | | 11 | 8+2 类契约族总览 | 架 | SVG新 | 现 | 三落点 + 主编号轴;诚实标出 5 缝:DB 漂移/CI 门缺位/Dify#6 废/第9契约五套相撞/agent-loop+templates 漏登 | | 12 | 专区 Zone + 锁风门 Gate | 讲 | Mer新(内联) | 现 | 两横切概念 owner 与聚合:Gate=compliance 聚合 AGC19+IP04 挂 PRJ05;Zone=project owner;Zone 无独立实体(字段承载) | +| 13 | 13 逻辑模块 → 单体物理打包/运行拓扑 | 架 | SVG新 | 现 | 逻辑独立(13 领域 + -api/-server 两段式)→ jar 聚合进单一 JAR game-server → 单进程;Spring Profile 控加载(pay 显式注释排除);无 split-brain;依赖方向=未来微服务切割线(远期·不做) | +| 14 | 契约族 × 跨域接缝 生产者→消费者流向 | 协议契约 | Mer新(内联) | 现 | 补图 11 未答的「每类契约 govern 哪条 handoff」:GamePackage(studio→runtime 编译预览发布)/prompts(生成链)/SDK(宿主↔游戏 postMessage)/events(埋点→看板)/ad-slot(广告位);Dify#6 已废不 govern 现行 | +| 15 | 13 模块 真/桩/未建 状态热力图 | 架 | SVG新 | 现 | 四簇底图叠 13模块.md §4 状态(✅5 project/telemetry/ad/trade/community · 🟡6 aigc/runtime/feed/studio/compliance/biz · ◻2 ip seam/pay 未接单体);每块标最大缺口;口径 状态>实现>结构、以 MVP进度总账.md 为准 | -> **状态分布**:现 ×10、现+史 ×1(图 2,决策史对照)、现+废 ×1(图 3,含废弃蓝图)。**注**:图 2/3 的「史/废」指其中**并列的决策史/废弃候选**部分(Dify/OpenGame/自研壳),现行选定部分仍是「现」;图 9/10/11 虽整体「现」,但各含一处必须按状态读的缝(候选集桩 / 可观测落地=接 / 5 处契约现实缝),已在散文与图内标清。**防漂移门**:本文 frontmatter 记架构域三份源档的 commit hash(README/契约总览 @ 38357c3d、13模块 @ 7ecd616e),源档变更即比对。 +> **状态分布**:现 ×13、现+史 ×1(图 2,决策史对照)、现+废 ×1(图 3,含废弃蓝图)。**注**:图 2/3 的「史/废」指其中**并列的决策史/废弃候选**部分(Dify/OpenGame/自研壳),现行选定部分仍是「现」;图 9/10/11/13/14/15 虽整体「现」,但各含一处必须按状态读的边界——候选集桩(图 9)/ 可观测落地=接(图 10)/ 5 处契约现实缝(图 11)/ 微服务切割线为远期不做(图 13,紫虚线)/ Dify#6 已废不 govern 现行 handoff(图 14,灰块)/ 状态以总账为准且仅为快照(图 15),均已在散文与图内标清。**防漂移门**:本文 frontmatter 记架构域三份源档的 commit hash(README/契约总览 @ 38357c3d、13模块 @ 7ecd616e),源档变更即比对。 --- diff --git a/docs/architecture/03-产物执行沙箱图说.md b/docs/architecture/03-产物执行沙箱图说.md index a2fcc82d..6ad09f10 100644 --- a/docs/architecture/03-产物执行沙箱图说.md +++ b/docs/architecture/03-产物执行沙箱图说.md @@ -154,6 +154,70 @@ stateDiagram-v2 这张图没有现行/远期边界,它是现行 feed 容器生命周期的真实形态;唯一的过渡口径在「终态怎么来」——`watchGameEnd` 轮询 `host.state().phase` 到 `gameover` 才 latch 一个 `game_end` 代发,是因为 ref 游戏自己没有 emit 通道,等 W-G1 落地后改由各品类标准信号产出、轮询桩可下线(与图 2 同源)。 +### 沙箱图 8 · postMessage 信封数据模型(契约#3 跨端 wire 契约)〔Mer新·数据模型·现〕 + +下面这张类图把「跨信任边界的每一条消息长什么样」从字段层面定死。前面图 2 / 图 3 讲的是消息**怎么流、怎么被校验**,这张图补的是另一个维度:消息**本身的数据结构**。它来自契约 `contracts/sdk-interface.d.ts`(第 #3 类契约 · SDK↔宿主 postMessage 协议),是宿主侧和游戏侧都必须逐字遵守的跨端 wire 契约——游戏侧组装消息、宿主侧 `validateEnvelope` 逐字段校验,两端对的就是这一份结构。把它单独画出来,是为了给安全审计一个「合法消息的字段全集」清单,也给游戏侧实现一个照着填的模板。 + +```mermaid +classDiagram + direction TB + class PostMessageEnvelope~T~ { + +channel: 'wanxiang-game-sdk' 〔必·定值〕 + +type: PostMessageType 〔必·8枚举内〕 + +direction: MessageDirection 〔必·合法值〕 + +traceId: string 〔必·贯穿链路〕 + +payload: T 〔必·须存在〕 + +requestId?: string 〔选·配对用〕 + } + class PostMessageType { + «enum» + init + lifecycle + telemetry + error + ad + pay + social + storage + } + class MessageDirection { + «enum» + game_to_host + host_to_game + } + class StorageSetPayload { + +key string + +value string_JSON + } + class StorageGetPayload { + +key string + } + class StorageResultPayload { + +key string + +value object_or_null + } + class AdPayPayload { + +req slotId_orderId_amount + +resp rewarded_shown_paid + } + + PostMessageEnvelope~T~ *-- PostMessageType : type + PostMessageEnvelope~T~ *-- MessageDirection : direction + PostMessageEnvelope~T~ <|.. StorageSetPayload : payload(type=storage·写) + PostMessageEnvelope~T~ <|.. StorageGetPayload : payload(type=storage·读请求·带requestId) + PostMessageEnvelope~T~ <|.. StorageResultPayload : payload(type=storage·读回包) + PostMessageEnvelope~T~ <|.. AdPayPayload : payload(type=ad/pay·带requestId) + + note for PostMessageEnvelope~T~ "validateEnvelope 逐字段必过项(bridge.ts):\nchannel 严格等于 'wanxiang-game-sdk' · type 在 VALID_TYPES 内\ndirection 合法 · traceId 是字符串 · payload 存在(挡 undefined)\nrequestId 若带须是字符串。校验器不抛异常、只返判定(异常本身亦攻击面)。" + note for PostMessageType "8 枚举各自方向/用途(契约注释):\ninit=host→game 初始化 · lifecycle=game→host 生命周期 · telemetry=game→host 遥测 · error=game→host 错误\nad/pay/social/storage=双向(广告/支付/分享/键值存储,iframe 外宿主侧办、按 requestId 回包)。\n⚠ 漂移:这是契约 canonical 命名(telemetry/social);运行时 bridge VALID_TYPES 实为 track/ready(见图 4)——\n命名维度契约与代码未对齐、属已知漂移,以两侧各自语义为准,别当已收口。" +``` + +这张图分三块读。**主类 `PostMessageEnvelope` 是信封本体**,六个字段里五个必填、一个可选:`channel` 是定值常量 `wanxiang-game-sdk`,宿主据它一眼滤掉非本协议的噪声或伪造消息;`type`(取 `PostMessageType` 8 枚举之一)、`direction`(取 `MessageDirection` 两值之一)、`traceId`(贯穿「生成→运行→上报」链路的字符串)、`payload`(泛型载荷、必须存在)都是必填;只有 `requestId` 是可选——它专给「请求-回包」要配对的消息(ad / pay / storage 读)用,写类的 track / lifecycle / error 是 fire-and-forget、不带它。图上每个字段都标了〔必/选〕和约束,新人对照右侧 `validateEnvelope` 那条注记,就能一眼看出「一条消息要全过哪几关才不被丢弃」。 + +**第二块是挂在信封 `payload` 下的几个 typed payload**,展示泛型 `` 在实际消息里被具化成什么。storage 这一族最完整,正好演示请求-回包的三段形状:写存档用 `StorageSetPayload{key,value}`(value 是 JSON 字符串),读请求用 `StorageGetPayload{key}`(带 requestId),读回包用 `StorageResultPayload{key,value}`——这里有个契约级的关键细节,回包的 `value` 是**宿主侧已经解析好的对象**(`Record|null`)、不是原始字符串,且契约语义明令数组按未命中处理(resolve null),这正是「runtime 侧零 JSON.parse、不引可抛路径」红线在数据结构上的落点。ad / pay 一族我用一个示意类 `AdPayPayload` 概括其请求字段(slotId / orderId / amount)与回包字段(rewarded / shown / paid),它们都靠 requestId 配对。 + +**第三块是必须诚实标出的一条设计缝**,画在 `PostMessageType` 的注记里:这张图严格按契约 `sdk-interface.d.ts` 画,所以 8 个枚举是契约的 canonical 命名(含 `telemetry` / `social`);但运行时桥 `bridge.ts` 的 `VALID_TYPES` 实际用的是 `track` / `ready` 这套命名(就是图 4 那张 8 type 表)。也就是说契约声明与代码实现在「type 命名」这一维度并未对齐——这是一条已知漂移,不是已收口,读图时以两侧各自语义为准、别把它当成铁板一块。除这条命名漂移外,信封的字段结构本身契约与代码是一致的、且已真跑通过,所以整图状态是「现」;它没有现行/远期边界,讲的是一个当前就成立的跨端数据契约。 + > **产物执行沙箱图清单与状态表** | # | 图名 | 家族 | 形式 | 状态 | 覆盖内容 | @@ -165,8 +229,9 @@ stateDiagram-v2 | 5 | 两条正交边界 | 架 | SVG新 | 现 | 沙箱边界(iframe 壳 vs 宿主,边界①)vs 受控面(游戏↔引擎,边界②)嵌套关系 + 破一条另一条仍兜 + IP/关联档/收敛三处别混 | | 6 | CSP / 同源红线 / 产物消毒 | 讲 | Mer新(内联) | 现 | connect-src 'none' + 'unsafe-eval' 纵深承接(漂移①以代码为准)+ allow-same-origin 同源红线过渡态(HJ-AUDIT-001)+ escapeBundle 消毒 + 收敛三件一起做 | | 7 | 三容器加载 / 失败 / 销毁态机 | 状 | Mer新(内联) | 现 | 当前播放 / 前一销毁 / 后一预加载 三态轮转 + dispose 防泄漏 + 加载失败降级 demo(不上抛)+ 加载超时分流 + game_end latch 过渡口径 | +| 8 | postMessage 信封数据模型 | 数据模型 | Mer新(内联) | 现 | PostMessageEnvelope<T> 字段级结构(channel 定值 / type 8枚举 / direction / traceId / payload / requestId? 配对)+ validateEnvelope 逐字段必过项 + storage 三段 payload + ad/pay 配对 + 契约枚举 vs 运行时 VALID_TYPES 命名漂移诚实标注 | -> **状态分布**:现 ×7(机制全建成、真跑通过)。本域无「待接 / 待建 / 缓做 / future」整图——但**现行机制内有四处已知债**(CSP 文档口径漂移、sandbox 属性三处不一致、sandboxAttr 半孤儿、HJ-AUDIT-001 同源红线过渡态),在图 1 / 图 6 中用橙色虚线框 + 文字小标与「现行已建实心块」区分,绝不画成「已合规收口」。**防漂移门**:本文 frontmatter 记源档 `产物执行沙箱.md @ 38357c3d`(随 7fff6518 总图说提交锚定),源档变更即比对。**单源说明**:本域所有图均为新作(SVG新 / Mer新),无「引」类;源设计档 `产物执行沙箱.md` 自身在 §1/§2/§3 内嵌了三段 Mermaid(端到端时序、三重边界、桥双校验),本图说不复制它们——图 2 是把 §1 时序升保真为 SVG、图 3 的桥流程按「桥判定流」单独框选重画、图 1/4/5 则是源档没有的新视角(全景 / 类图 / 边界嵌套)。 +> **状态分布**:现 ×8(机制全建成、真跑通过)。本域无「待接 / 待建 / 缓做 / future」整图——但**现行机制内有四处已知债**(CSP 文档口径漂移、sandbox 属性三处不一致、sandboxAttr 半孤儿、HJ-AUDIT-001 同源红线过渡态),另有**一处契约 vs 代码命名漂移**(图 8:契约 type 枚举 telemetry/social 与运行时 VALID_TYPES 的 track/ready 未对齐),均在对应图(图 1 / 图 6 / 图 8)用橙色虚线框或注记与「现行已建实心块」区分,绝不画成「已合规收口」。**防漂移门**:本文 frontmatter 记源档 `产物执行沙箱.md @ 38357c3d`(随 7fff6518 总图说提交锚定),源档变更即比对;图 8 另锚契约 `contracts/sdk-interface.d.ts`(第 #3 类契约),契约字段变更即比对本图。**单源说明**:本域所有图均为新作(SVG新 / Mer新),无「引」类;源设计档 `产物执行沙箱.md` 自身在 §1/§2/§3 内嵌了三段 Mermaid(端到端时序、三重边界、桥双校验),本图说不复制它们——图 2 是把 §1 时序升保真为 SVG、图 3 的桥流程按「桥判定流」单独框选重画、图 1/4/5 则是源档没有的新视角(全景 / 类图 / 边界嵌套);图 8 是从契约 `sdk-interface.d.ts` 提取的信封字段级数据模型,与源档 §3 的桥流程(讲消息怎么流)正交互补(讲消息长什么样),不复制 §3 的流程图。 --- diff --git a/docs/architecture/04-后端图说.md b/docs/architecture/04-后端图说.md index 695f8b6b..19166bd6 100644 --- a/docs/architecture/04-后端图说.md +++ b/docs/architecture/04-后端图说.md @@ -204,6 +204,86 @@ flowchart TB 这张图最该让人看出的,是匿名读这一档**不是「无所谓」、而是有三条必须守的纪律**(图上用橙色虚线框单独标出,出自安全规则、P-OPN-08 已实证):只暴露公开字段、把 PII 裁剪掉;公开读靠手动 `eq` 谓词隔离,**不能假定框架的 DataPermission 会自动生效**(它只注册在 AdminUserDO 等业务表上);跨租户读要显式收敛。这三条是匿名读端点最容易踩的坑——以为放了 `@PermitAll` 就完事,结果把私有数据或 PII 漏出去。一个要记住的细节是**登录端点本身免登**:C 端的 send-sms-code / sms-login / invite-register 三个带 `@PermitAll`(不然没法登录),但 `me` 走登录态;sms-login 是「已注册即登录、未注册自动注册」一体,成功后发真 OAuth2 token。这张图没有现行/远期边界,就是当前每个端点准入的真相速查表。 +### 后端图 9 · 核心对象生命周期状态机〔Mer新·状态机·现〕 + +这张图回答全平台**最核心的那个对象——一款游戏(`game_project`)——这辈子会经历哪些状态、是谁在推它走**。前面图 5 是数据的静态结构、图 6 是链路的动态调用,这张图是第三个视角:把 `game_project.status` 这条七态主链单独抽出来当状态机看。它之所以是「总闸」,是因为创作链、发布链、合规链都不直接互相调用,而是各自读写这一个 status 字段来协同——谁也绕不开它。新人记住这张图,就抓住了后端业务流转的主心骨。 + +```mermaid +stateDiagram-v2 + direction LR + [*] --> 草稿0: createDraft 建项目 + 草稿0 --> 审核中1: submitPublish 提交发布(project 驱动) + 审核中1 --> 通过2: compliance 裁决 verdict=pass 回写 + 审核中1 --> 拒绝3: compliance 裁决 verdict=block 回写 + 通过2 --> 已发布4: 统一发布编排入 feed(status=4 出流) + 拒绝3 --> 草稿0: 改源重做后再提交 + 已发布4 --> 下架5: 运营/创作者下架(offlineRank 出流) + 已发布4 --> 封禁6: compliance 处置(user_ban 落台账) + 下架5 --> 审核中1: 重新提交复审 + 封禁6 --> [*]: 终态(申诉另走 compliance_appeal) + 通过2 --> [*] + 下架5 --> [*] + + note right of 审核中1 + 谁推 / 谁回写两分: + project 只驱动状态机迁移(submit/offline); + compliance 只给结论(pass/review/block), + 经 gate_result.verdict 回写 project.status, + 自己不持有这条主链。 + end note + note left of 草稿0 + 改源不改包:源(source_project.source_json) + 与产物(version.package_url)两面解耦。 + create=首次脚手架 / modify=确定性改源 / + extend=经 base_version_id 记血缘扩展; + 任一操作都「重新 build 产新 version」、 + 而非直接动旧 package。source_hash 幂等去重, + 构建失败留孤儿源(status=2)不污染产物面。 + end note +``` + +这张图最该让人看清两件事。**其一是「谁推」与「谁回写」的两分**:status 这条主链的所有权属于 project,但驱动它前进的有两方——project 自己负责「提交发布(submitPublish)」「下架(offlineRank)」这类主动迁移,而「通过 / 拒绝 / 封禁」这三步的结论来自 compliance,compliance 不持有这条主链、只把 `gate_result.verdict` 回写进 `project.status`。这正是图 6「唯一真原子发布」和图 7「合规处置」在状态层面的落点:发布是 project 把 compliance 裁决、runtime 出包、feed 入流串成一个事务,任一步失败整体回滚、status 不留半截。**其二是状态机背后那条「改源不改包」范式**(图左侧 note):一款游戏不是一次性产物、而是长生命周期项目,`game_source_project` 存源、`game_version` 存产物,两个存储面解耦;create(首次脚手架)/ modify(确定性改源)/ extend(经 `base_version_id` 记血缘的扩展)三种操作改的都是源,然后**重新 build 出一个新 version**,而不是去动旧包——`source_hash` 做幂等去重,构建失败时留下孤儿源(`status=2`)而不污染产物面。这张图没有现行/远期的灰度,七态都是已落库、已 e2e 验证的现行真相;唯一要注意的边界是「封禁」后的申诉不在这条主链上、另走 `compliance_appeal` 台账(见图 5 合规块)。 + +### 后端图 10 · 两套身份 + 匿名→登录归因数据视图〔Mer新·数据模型·现〕(P2) + +这张图回答一个读懂全平台数据归属的前提问题:**「谁拥有这条数据」到底怎么判定**。答案分两层:第一层是平台根本就有**两套互不相干的身份体系**——C 端的玩家兼创作者用 `game_player`、B 端的运营与管理员用 `system_users`,它们在数值空间和代码路径上都分开;第二层是 `game_*` 业务表全都**没有物理外键**,归属不靠 DB 约束、而靠 Service 可信边界在查询里强制带 `eq(userId)` 谓词。这两层一起,才是图 5「两套身份」框和图 7「C 端归属隔离」范式在数据视角的完整底座。 + +```mermaid +erDiagram + game_player { + bigint id "= OAuth2 userId(MEMBER)· 不在13模块清单却被全模块引用" + varchar mobile "uk_mobile 登录主键" + tinyint creator_flag "0 玩家 / 1 创作者(A2 白名单)" + varchar first_anon_id "匿名→登录归因衔接" + } + system_users { + bigint id "= OAuth2 userId(ADMIN)· Huijing 原生" + varchar username "B 端账号" + } + game_project { + bigint id "gameId" + bigint creator_user_id "软关联 game_player.id(无物理外键)" + } + game_telemetry_event { + varchar event_id "uk_event_id 幂等真身" + bigint player_user_id "可空·登录态归属" + varchar anon_id "匿名态归属" + } + game_runtime_session { + bigint id "试玩会话" + bigint player_user_id "可空(V11 放宽)" + varchar anon_id "V11 加·匿名也能试玩" + } + + game_player ||..o{ game_project : "creator_user_id eq 谓词(软关联·零外键)" + game_player ||..o{ game_runtime_session : "player_user_id(登录后)" + game_player ||..o{ game_telemetry_event : "player_user_id(登录后)" + game_runtime_session }o..|| game_telemetry_event : "anon_id 串起匿名行为" + system_users ||..o{ game_project : "B 端 RBAC 经 AdminUserApi(另一套人)" +``` + +读这张图,新人最该看出三点。**一是两套身份的彻底分离**:`game_player` 物理上寄宿在 `huijing-module-system`、却不在 13 模块清单里——它是被全平台 `game_*` 表共同引用的归属起点,所有业务表里的 `creator_user_id` / `user_id` / `player_user_id` 数值上都等于 `game_player.id`(即 OAuth2 的 `userId`);而 B 端管理员是另一套人,走 Huijing 原生的 `system_users`,`ProjectServiceImpl` 引 `AdminUserApi` 就是这条线。两套人不共用一张表、不共享数值空间。**二是「零外键 + eq 谓词」这条归属强制机理**:图上 `game_player` 指向各业务表的连线全部用虚线(`..`)画,因为代码里一根物理外键都没有——归属隔离完全靠 Service/Mapper 在 WHERE 里钉 `eq(creatorUserId)`,这是图 7 C 端「黄金归属范式」在数据层的落点,也是为什么动跨模块查询时必须自己带归属谓词、不能指望 DB 帮你拦。**三是匿名→登录的归因衔接**:试玩会话(`game_runtime_session`)和遥测事件(`game_telemetry_event`)的 `player_user_id` 都是可空的(V11 放宽),匿名玩家靠 `anon_id` 占位先玩起来、产生行为数据,登录后再经 `game_player.first_anon_id` 把这段匿名轨迹归并到真实身份上——这条衔接是「先让人无门槛玩、再做转化归因」的数据基础。这张图没有现行/远期边界,是当前数据归属判定的真相底座;标注 (P2) 是因为它服务于 feed/试玩这条 P2 链路的归属语义。 + > **后端域图清单与状态表** | # | 图名 | 家族 | 形式 | 状态 | 覆盖内容 | @@ -216,8 +296,10 @@ flowchart TB | 6 | 五条业务链路 | 时 | SVG新 | 现 | 创作/发布/试玩/广告收益/数据回路 跨模块调用;唯一真原子发布 + 唯一双向边 + source_ref 对账锚点;游标/联盟SDK/检测原子桩照实标 | | 7 | 鉴权 OAuth2/RBAC 双模型 | 类 | SVG新 | 现 | 两类用户两套权限并存:B 端 @PreAuthorize RBAC + C 端 Service 归属隔离 + 创作白名单 + 网关双重校验=未来态纠偏 + mock 后门红线 | | 8 | 匿名/登录准入矩阵 | 讲 | Mer新 | 现 | 四档准入(匿名/登录/RBAC/归属)速查 + 匿名读三纪律 + 登录端点本身免登 | +| 9 | 核心对象生命周期状态机 | 状态机 | Mer新 | 现 | game_project.status 七态主链(草稿→审核→通过/拒绝→已发布→下架/封禁)+ 每迁移标谁推谁回写(project 驱动状态 / compliance 给结论)+ 改源不改包(create/modify/extend→重 build 产新 version 不动旧 package · source/version 两面解耦) | +| 10 | 两套身份 + 匿名→登录归因数据视图 | 数据模型 | Mer新 | 现(P2) | game_player(C 端·不在13模块清单却被全模块引用)vs system_users(B 端)两套身份数值与代码路径分开 + game_* 全表零物理外键(归属靠 Service eq 谓词)+ anon_id 匿名→登录归因衔接 | -> **状态分布**:现 ×8(后端域全部现行已建,无接/缓/建/future)。但「现行已建的结构」里照实标出了若干**设计缝与桩**——contracts DB 镜像漂移(图 5)、compliance 检测原子恒 pass / feed 游标分页桩 / 真联盟 SDK 桩(图 6)、网关双重校验是未来态而非现状(图 7)——绝不因整体为「现」就把桩画成真。**防漂移门**:本文 frontmatter 记后端域四份源档的 commit hash(README/数据模型/鉴权与权限 @ 38357c3d、13模块 @ 7ecd616e),源档变更即比对。 +> **状态分布**:现 ×10(后端域全部现行已建,无接/缓/建/future)。但「现行已建的结构」里照实标出了若干**设计缝与桩**——contracts DB 镜像漂移(图 5)、compliance 检测原子恒 pass / feed 游标分页桩 / 真联盟 SDK 桩(图 6)、网关双重校验是未来态而非现状(图 7)——绝不因整体为「现」就把桩画成真。图 9 / 图 10 是补的两张新人视角图(对象生命周期状态机 + 身份归属数据底座),都是现行真相、无远期灰度。**防漂移门**:本文 frontmatter 记后端域四份源档的 commit hash(README/数据模型/鉴权与权限 @ 38357c3d、13模块 @ 7ecd616e),源档变更即比对。 --- diff --git a/docs/architecture/05-前端图说.md b/docs/architecture/05-前端图说.md index 7f00583d..f537072a 100644 --- a/docs/architecture/05-前端图说.md +++ b/docs/architecture/05-前端图说.md @@ -179,6 +179,143 @@ flowchart TB 这张图有一条最关键的边界要看清,它决定了前端域的工作量没有想象中大:**两条装载轨共用同一套执行沙箱**——不管哪条轨出来的 bundle,都暴露 `window.__GameBundle` 全局名、都调 `bootGameHost`、都跑在同一套 iframe + CSP + 桥里(图上用深色实心块把「执行沙箱」画成公共件,两轨都虚线指向它)。tier2 换的是「游戏内容怎么造出来」,换不掉「造出来之后怎么被关进笼子跑」。所以前端域要补的只是**运行时容器的双轨分发 + 创作入口**,装载与渲染的 how 在架构域、见 **`架构/生成引擎/引擎与运行时.md`**(其 §7.3 把「tier2 第二装载分支」列为待开项)与 `架构/生成引擎/tier2实现详设.md`。这张图的设计缝就是它的状态本身:**整套是待建**,详细前端设计要等 tier2 临近过 0 号 spike 再展开,现在只钉归属、不预先设计——绝不能因为图画出来了,就误以为第二条生成轨的前端已经建好。 +### 前端图 10 · 对话式创作闭环全景〔Mer新·流·现+建〕 + +这张图回答「绘境AI 完整的产品形态到底长什么样」——前面图 1 到图 9 讲的是「界面靠什么撑起一致体验、生成的游戏怎么被玩起来」,而这张图把镜头拉到最上层,画出**创作者从一句话到一款不断打磨的游戏**的全过程。它的核心定调来自 README §7.3(创始人 2026-06-21 拍):绘境的产品形态**不是「一句话 + 选玩法模板 → 整包生成」一锤子买卖,而是一条对话式创作闭环**——多轮对话把游戏生成出来,之后还能对已经生成的游戏做**差量修改**(换套美术、改第 2 关的关卡参数),以及替换游戏里用到的素材。「一句话整包生成」只是**发起一次生成的若干启动点位之一**,不是终点。 + +```mermaid +flowchart TB + subgraph START["发起点(启动一次生成的若干入口)"] + direction LR + S1["一句话自然语言
+ 可选玩法模板/参考图"] + S2["feed「做同款」入口
(P-FED-12 · 2026-06-22 升 P0)"] + end + + ANALYZE["意图解析
系统理解创意 → 归一玩法/模板"] + CONFIRM["目标确认卡
把解析结果回给用户确认再生成"] + GEN["generate 整包生成
(SAA 全图 → 可玩产物 + 版本)"] + PLAYABLE["已生成的游戏
(进 feed 可玩 · 有版本)"] + + subgraph ITER["对已生成游戏的差量迭代(只动一处、不毁全局)"] + direction LR + MOD["modify 差量修改
换美术 / 改某关参数"] + EXT["extend 扩展
加第 2 关 / 加系统"] + end + + S1 --> ANALYZE + S2 -.->|读原作血缘 → 作为生成上下文| ANALYZE + ANALYZE --> CONFIRM --> GEN --> PLAYABLE + PLAYABLE --> ITER + ITER -.->|生成新版本 → 回到可玩| PLAYABLE + + C01["前端 C01 对话框 + 六类素材当上下文"]:::todo + C02["前端 C02 目标确认卡 UI"]:::todo + C03["前端 C03 差量修改入口"]:::todo + C04["前端 C04「改了哪·其余没动」差异展示"]:::todo + C01 -.-> S1 + C02 -.-> CONFIRM + C03 -.-> ITER + C04 -.-> ITER + + classDef todo fill:#faf5ff,stroke:#7c3aed,stroke-width:1.4px,stroke-dasharray:5 4; + classDef now fill:#dcfce7,stroke:#16a34a,stroke-width:1.5px; + class S1,S2,ANALYZE,CONFIRM,GEN,PLAYABLE,MOD,EXT now; +``` + +这张图最该让人看出的,是**「产品形态已经定调、但前端 UI 还要补」这条现行 / 待建的分界线**。图的主链路——发起点 → 意图解析 → 目标确认卡 → generate → 对已生成游戏 modify/extend——在**后端已经是现行真相**:`/studio/{create,modify,extend}` 三个端点都建好了(`AppStudioController` 的 `/modify`、`/extend` 实测在),SAA 的 modify 节点也在(它会按 `baseVersionId` 反查原作的源工程注入,做差量而非静默全量重生成)。所以这条创作链不是空想,后端跑得通。但**用户看得见的那层壳子还没做**:对话框、把六类素材传进去当生成上下文、系统解析意图后给用户的目标确认卡、差量修改的入口、以及「改了哪、其余没动」的差异展示——这五件事对应 README 里的前端 **C01–C04**,图上专门用紫色虚线把它们挂在主链路相应环节,一眼看清「哪几处是待补的前端」。这正是要分清的一条边界:对话式创作**不是被砍掉的范围(descope)**,而是产品形态已定、前端落点待补,别把它和图 4「勿误砍清单」里那些有意 MVP descope 的屏(首页门户、素材中心)混为一谈。 + +图上还有一处升级要看清:右侧的 **feed「做同款」入口**(P-FED-12)——玩家在信息流里看到一款喜欢的游戏,可以直接「做同款」发起一次属于自己的创作(它会读原作的血缘当生成上下文,见图 12 与数据飞轮域)。这条入口已由创始人 2026-06-22 拍板从 P1 **升为 P0**(它是数据飞轮网络效应的核心杠杆,Doc A 已改)。需要据图把握的口径是:产品形态定调讲的是**方向**,把对话式创作(P-CRT-05)、素材中心(P-MAT)定调为产品形态,不等于把它们的验收优先级一次性提到 P0——只有同款创作(P-FED-12)这一项真升了 P0,P-CRT-05 / P-MAT 的优先级调整仍另走评审,别据这张图擅自改动验收契约。 + +### 前端图 11 · 生成任务 UI 侧 失败/取消/重试/轮询闭环〔Mer新·状态机·现〕 + +这张图回答「创作者点了生成之后,前端这一侧怎么把一次生成的全过程(排队 → 跑 → 成 / 败 / 超时 / 取消)展示出来,失败了怎么读懂原因、怎么重试」。它是一张**前端视角**的状态机,刻意和后端的任务状态机区别开:后端的状态机讲「任务在服务端经历哪些状态」,这张图讲「`Task.vue` 这个生成进度页**在浏览器里**怎么轮询、怎么渲染每个状态、给用户哪些可操作的出口」。这是 studio 比 demo 多出来的一项真实能力——demo 那个「试玩」用 720ms 模拟一卡到底的 complete、**从不出现失败态**,而真实生成会排队、会超时、会因为各种原因失败,前端必须把这些都老实地接住、可读地呈现。 + +```mermaid +stateDiagram-v2 + direction LR + [*] --> 提交生成: 用户在 Create 发起 / 重试 + 提交生成 --> 排队中: status 0 queued + 排队中 --> 运行中: status 1 running + note right of 运行中 + UI 轮询 / SSE 监听 taskId + 进度色按 progress 粗分四阶段: + 理解创意 → 搭玩法 → 生素材 → 打包 + end note + + 运行中 --> 成功: status 2 succeeded + 运行中 --> 失败: status 3 failed + 运行中 --> 超时: status 4 timed_out + 运行中 --> 已取消: status 5 canceled(用户点取消) + 排队中 --> 已取消: 排队期也可取消 + + 成功 --> [*]: 回填 versionId → 进预览试玩 + 失败 --> 提交生成: 点「重新生成」(retryOf 指原任务) + 超时 --> 提交生成: 点「重新生成」 + 已取消 --> 提交生成: 「返回创作」再发起 + + note right of 失败 + 展开七种失败原因可读中文映射(对齐契约 aigc.yaml FailureReason): + unsafe_prompt 描述含不适宜内容请换说法 + intent_unclear 没太理解意图请写具体 + no_template_match 没匹配到玩法模板 + config_invalid 玩法配置校验未过 + llm_error AI 服务开小差 + timeout 生成超时了 + asset_gen_failed 素材生成失败 + end note +``` + +这张图最该让人看出的,是**「失败」在前端不是一个死胡同,而是一个能被读懂、能被重来的可恢复态**。它的护城河价值就在这里:后端契约 `aigc.yaml` 定了七种失败原因枚举(`unsafe_prompt` / `intent_unclear` / `no_template_match` / `config_invalid` / `llm_error` / `timeout` / `asset_gen_failed`),前端在 `Task.vue` 里把每一种都映射成一句**人话提示**(比如 `unsafe_prompt` → 「描述包含不适宜内容,请换个说法」、`intent_unclear` → 「没太理解你的意图,试试把描述写得更具体」),让创作者知道「为什么没成、下一步该怎么改」,而不是只看到一个冷冰冰的「失败」。图上把这七条原因映射直接挂在「失败」态的展开注里,因为这正是这张图区别于后端状态机的关键信息——后端只回一个枚举值,把枚举翻译成可读文案、决定展示哪个出口,是前端这一侧的活。 + +这张图还要让人看出**两个状态边界**。其一,**可取消**:不只「运行中」能点取消,「排队中」也能取消(图上两条都画了到「已取消」的边),取消后落「已取消」态、给一个「返回创作」的出口。其二,**可重试且可追溯**:失败、超时都能点「重新生成」,重试时会带上 `retryOf` 指向原任务(图上在重试边上标了),这样一次创作的多轮重试在数据上是串得起来的,不是各自孤立的新任务。需要据图把握的一处实现现状:进度的四阶段(理解创意 → 搭玩法 → 生素材 → 打包)是前端按 `progress` 百分比**粗分**出来的展示阶段(`< 30` / `< 60` / `< 90` / `>= 90`),它是给用户的进度叙事、不是后端下发的精确步骤,看图时别把它误当成后端的真实流水节点。 + +### 前端图 12 · feed 玩家消费交互模型〔Mer新·流·现〕 + +这张图回答「玩家打开游戏信息流之后,在播放器里是怎么消费、怎么互动的」——它是图 7 视图地图里「玩家消费」那条主回路的运行期放大,聚焦**玩家侧**(区别于图 8 讲的「一款游戏怎么在沙箱里跑起来」的宿主侧装载机制)。绘境的 feed 是一条**类短视频的竖屏即刷即玩流**:整屏吸附、上滑切下一款,右侧一条互动条,刷得越深越往后拉新的一批。它和短视频最大的不同是——每一屏不是一段视频,而是一款**真在跑的游戏**,所以「切换」既要丝滑、又要让下一款游戏提前就绪。 + +```mermaid +flowchart TB + ENTER["玩家进入 Feed
(匿名 anonId 可达 · 无需登录)"]:::now + + subgraph SWIPE["整屏吸附上滑切换(scroll-snap y mandatory)"] + direction LR + PREV["上一屏
(已销毁/可回滑)"]:::dim + CUR["当前屏
一款真在跑的游戏"]:::now + NEXT["下一屏 N+1
三容器预取就绪"]:::now + end + + subgraph BAR["右侧互动条 · 四动作(贴 feed.yaml action 枚举)"] + direction LR + A1["赞 action=1"]:::now + A2["藏 action=2"]:::now + A3["分享 action=3
→ 跳 /share 落地页"]:::now + A4["举报 action=4
→ 弹原因"]:::now + end + + PREFETCH["manifest 首帧 + 容器预取
(随 feed 清单先行下发 · 先画主题底色/标题)"]:::now + IMPRESS["曝光埋点 game_impression
(去重 · 滚到底续拉下一批)"]:::now + LOGINGATE["触发互动才弹登录
(isRealLogin 前置 · 跳 /login 带回跳)"]:::gate + + ENTER --> SWIPE + CUR --> BAR + CUR -.->|切换前预热| PREFETCH + PREFETCH -.-> NEXT + CUR -->|整屏进入| IMPRESS + IMPRESS -.->|滚到底| ENTER + A1 -.->|未真实登录| LOGINGATE + A2 -.->|未真实登录| LOGINGATE + A4 -.->|未真实登录| LOGINGATE + A3 -->|分享落地页公开| OUT["/share 落地页
(OG 元数据 · utm 归因)"]:::now + + classDef now fill:#dcfce7,stroke:#16a34a,stroke-width:1.5px; + classDef dim fill:#f1f5f9,stroke:#94a3b8,stroke-width:1.2px,stroke-dasharray:4 3; + classDef gate fill:#fee2e2,stroke:#dc2626,stroke-width:1.5px; +``` + +这张图最该让人看出的,是 feed 玩家侧的两条体验支柱:**「切得快」和「玩得到」**。「切得快」靠的是**三容器调度 + scroll-snap 整屏吸附**:`Feed.vue` 用原生 `scroll-snap-type: y mandatory` 做整屏吸附,上滑就切到下一款;同时维护「上一屏 / 当前屏 / 下一屏」三个容器,在切换前就把 N+1 那款游戏预取就绪(图上把当前屏、下一屏画成已就绪的实心绿块,上一屏画成可回滑的灰态)。「玩得到」靠的是 **manifest 随 feed 清单先行下发**——前端拿到 manifest 后能在切换前先用它把游戏的主题底色、标题画出来(300ms 量级),消除「点了卡在等字节」的空白感,而不是干等游戏字节到齐才出画面。这两条共同兑现了体验 SLO(信息流首屏 P75 < 3 秒、点卡到可玩常态 ≤ 2 秒),而 feed 正是这套 SLO 的前端兑现处。 + +这张图还要让人看出**互动条的真实形状和准入边界**。右侧互动条是**四个动作**,严格贴后端 `feed.yaml` 的 `action` 枚举:**赞(1)/ 藏(2)/ 分享(3)/ 举报(4)**——这里要据代码纠一处口径:互动条的第四个动作是**举报**(`action=4`),不是评论;评论(P-SOC-01)当前在 Doc A 标 P1、且 feed 互动按钮真接 community / social 仍是「排期真接」的待办(部分按钮现仍是 mock),所以图上据 `InteractBar.vue` 现状画四动作=赞/藏/分享/举报,不臆造一个评论按钮。准入边界是这张图的安全主轴:**Feed 匿名可达**(`anonId` 衔接未登录态,玩家无需登录即可即刷即玩,图上用绿块画「进入」),但**互动是登录态动作**——点赞 / 收藏 / 举报这些动作在入口最前置 `isRealLogin()` 判定,未真实登录就**弹引导登录**(确认跳 `/login` 带回跳,取消则留在当前流继续刷),图上用红色门块把这条「触发互动才弹登录」单独标出。唯独**分享**例外:它跳的 `/share` 落地页是公开页(带 OG 元数据供社交平台抓取、带 utm 渠道归因),不挡登录门。需要据图把握的两处:**曝光埋点 `game_impression` 做了去重**(来回滑同一张不重复计数,是运营质量分的回灌信号源之一)、**滚到底触发续拉下一批**(图上画了 impression → 回到 Feed 的续拉环);这套消费 / 互动 / 埋点都是现行已建,整图状态为「现」。 + > **前端域图清单与状态表** | # | 图名 | 家族 | 形式 | 状态 | 覆盖内容 | @@ -192,8 +329,11 @@ flowchart TB | 7 | studio 视图地图 | 架 | SVG新 | 现 | 20 路由视图按五业务域布局(玩家消费/创作/平台成长/studio 专区/B 端)+ 4 tab 导航 + 匿名可达/必须登录准入边界 + 20vs19 计数口径 | | 8 | 真实试玩宿主 | 时 | Mer新(内联) | 现 | 取包→sha256 校验→srcdoc 注入→iframe sandbox→桥双校验→postMessage 回流;game_end 宿主轮询 latch 代发;同源过渡态 + 三债交叉引沙箱 §8 | | 9 | tier2 富游戏前端承载 | 架 | Mer新(内联) | **建** | feed 双轨装载分发 + studio 第二轨创作入口(归前端域·待建);两轨共用同一套沙箱(公共件);钉归属不预先设计,等 0 号 spike | +| 10 | 对话式创作闭环全景 | 架 | Mer新(内联) | 现+建 | 一句话/选模板 → 意图解析 → 目标确认卡 → generate → 对已生成游戏 modify/extend + feed「做同款」(P-FED-12 升 P0);后端 /studio/{create,modify,extend} 与 SAA modify 节点现行,前端 C01–C04 待补(虚线) | +| 11 | 失败/取消/重试/轮询闭环 | 状态机 | Mer新(内联) | 现 | UI 视角任务状态机:提交→排队→运行(进度色四阶段)→成/失/超时/取消;失败展开七种 FailureReason 可读映射;排队/运行皆可取消;重试带 retryOf 可追溯(区别于后端状态机) | +| 12 | feed 玩家消费交互模型 | 流 | Mer新(内联) | 现 | 整屏吸附上滑切换(scroll-snap·三容器预取)+ 互动条四动作(赞/藏/分享/举报·贴 feed.yaml,非评论)+ manifest 首帧预热 + 曝光去重续拉;Feed 匿名可达、触发互动才弹登录,分享落地页公开 | -> **状态分布**:现 ×8(图 1–8,设计体系已全量收口合入 `dev/2.0.0`)、建 ×1(图 9,tier2 富游戏前端承载归属已定但代码未建·整图虚线)。**防漂移门**:本文 frontmatter 记前端域三份源档的 commit hash(前端/README @ 15b707fd、产物执行沙箱 @ 38357c3d、引擎与运行时 @ 7ecd616e),源档变更即比对。 +> **状态分布**:现 ×10(图 1–8、11、12,设计体系与生成任务 UI / feed 消费均已建并合入 `dev/2.0.0`)、现+建 ×1(图 10,对话式创作产品形态已定调、后端主链路现行,前端 C01–C04 待补)、建 ×1(图 9,tier2 富游戏前端承载归属已定但代码未建·整图虚线)。**防漂移门**:本文 frontmatter 记前端域三份源档的 commit hash(前端/README @ 15b707fd、产物执行沙箱 @ 38357c3d、引擎与运行时 @ 7ecd616e),源档变更即比对。 --- diff --git a/docs/architecture/06-运营图说.md b/docs/architecture/06-运营图说.md index 439167f0..038d3e1c 100644 --- a/docs/architecture/06-运营图说.md +++ b/docs/architecture/06-运营图说.md @@ -167,6 +167,79 @@ flowchart TB 读这张图最该守的是它把**现状与待补严格分层**的诚实。现行已建(实心绿块)只有锁风门聚合那条框架:ComplianceGateApi.evaluate 按 block > review > pass 取最严裁决、落 game_compliance_gate_result 台账、在发布前检查被真注入——但**聚合进来的原子目前都是桩、恒返回 pass**,意味着今天的发布链对违规内容零自动拦截、纯靠人工兜底。其余全是本设计要补的待建(虚线框):双层机审的两层、人审队列底座、feed 自动降权接缝、创作者信用。处置联动这一栏要看清四类处置各自的现状落差——**下架**走 feed 现有的跨模块接缝 FeedApi.offlineRank(现成可用、封禁联动下架已在走它),**降权**则因为 setExposureLimit 现在只是管理端 HTTP 端点、不在跨模块 FeedApi 上,要 contract-first 新建 feed 降权 -api(创始人 2026-06-22 定放第一期、单独做);**封禁**台账已建,但封账号联动断着(不置 player.status=DISABLE、不连带下架全部内容,validateCreator 也不查 ban 表,所以今天封号拦不住本人继续创作,是本设计要补的两条断链);**创作者信用**现在一点没有、第一期建简单扣分台账(只记不连带、保守形态、防误伤)。图上还钉了两条贯穿铁律:**审核降级朝保守**(阿里云超时 / 报错降级到 review、绝不降级到 pass,与打款 fail-fast 同理),以及**审核状态唯一权威在 compliance**(project 只接回写、不双写,避免脑裂)。这张图的设计缝几乎布满全图——它如实画出了「框架在、判定空、处置半通」的真实现状,而非假装审核台已经建好。 +### 运营图 12 · 运营对象状态机合集〔SVG·状态机·现〕 + +![运营图 12 运营对象状态机合集](运营/assets/12-运营状态机合集.svg) + +这张图回答「运营域里到底有几台状态机、各自怎么转、谁已经真跑」。前面几张图里,状态机被压成钱流图或瀑布图里的一行散文标签——提现五态在图 10 里只是钱流终点的一个小框,B 端五态、订阅续期同样被一笔带过。这张图把运营域四个核心对象的状态机抽出来并排画在一处:提现、B 端询单、审核工单、订阅续期各占一格,让人一眼看清每台机的触发条件、各自的终态,以及哪些动作是幂等的。读它的正确方式不是逐格细看字段,而是先对比四台机的「成熟度差异」——它们恰好分布在「已建真跑」「整段不碰钱」「第一期待建」「半建半阻塞」四种状态上,正是运营域「整图是现、元素级布满设计缝」这条命门纪律的最集中体现。 + +四台机各有一处最该记住的设计点。**提现五态**(左上,trade,实线整片已真跑)最硬的纪律是「发起 ≠ 终态」:审核事务内只把单子从「待审 0」CAS 到「打款中 1」,绝不在审核里直接置「已打款」;真正的终态由打款回调驱动,成功走 1→2、失败走 1→4 退回冻结。它的终点是 mock 桩(图上右侧虚线红框标清)——只有 MockPayoutClient,真实微信/支付宝渠道被合规日历闸门阻塞,且这条线的降级口径是「绝不静默降级 mock」,因为打款降级 mock 就是吞真钱、必须 fail-fast,这一点和广告线「缺渠道降级 mock 可接受」正好相反。**B 端询单五态**(右上,biz,整条画成虚线红框)是四台机里唯一「完全不碰钱」的——待跟进→已报价→制作中→待验收→已交付单线推进,它的「终态」是交付而不是收款,在线签章/收款/分账整段留在 M4,现在唯一能标的只有 signed_offline 线下签兜底;把它整条画成虚线红框,正是要提醒读者:B 端虽是近期现金线,但工程钱流尚未建,真正的资金动作在提现线、不在这里。 + +下面两台机讲的是「待建」与「半建」。**审核工单**(左下,compliance,整台虚线)是第一期才建的——今天 compliance 只有「申诉」一种人工单,没有带认领/分派/SLA 的内容审核队列底座;它的状态机里「超时告警」是旁路态(介入后回到审核中)、不是终态,只有「已通过/已拒绝」是真终态,而人工 approve/reject 是最高权威、覆盖机审结论。把它整台画成虚线是诚实的:今天的发布链对违规内容零自动拦截、纯靠人工兜底。**订阅续期**(右下,trade,入账实线已真跑、收单虚线红框未接)有一处和其他三台都不同的终态语义——它没有「彻底结束」的吸收态,「过期」可以被下一次续期重新拉回「生效中」,是可逆回落,所以图上画成双向箭头;它被卡住的只是「自助购买收单」这一半(需接真实支付),admin 手动赋订阅那一半早已真跑、入创作者钱包恒等式。这张图的设计缝因此可以一句话收束:四台机里没有一台是凭空设想的,但它们各自被卡在不同的位置——读图时分清「实线方框=已真跑」与「虚线框+小标=被资质/波次阻塞」,就不会把待建的审核工单或被阻塞的打款 mock、订阅收单误当成已经建好。 + +### 运营图 13 · IP 库 · 素材授权与锁风档位来源 概念模型〔Mer新·概念·现〕 + +```mermaid +flowchart TB + subgraph IPLIB["IP 库(ip 模块 · 现以 seam 寄宿 compliance · 授权链待建)"] + direction TB + OWNER["IP 所有者 / 授权方
(迪士尼 / 王蓝莓 / 品牌方)"] -->|签授权| GRANT["IP 授权档
授权范围 + 敏感度 + 合同约束"] + GRANT --> IPENT["注册 IP 实体
(终态:lockStrength 作为授权属性挂在这)"] + end + subgraph SRC["档位源(现阶段=过渡表 · 终态=IP 实体属性)"] + POLICY["lock_strength_policy 过渡表
按 ipId / 题材关键词映射档位 · admin 可配"] + BLACK["题材黑名单兜底规则
(棋牌 / 捕鱼即便纯 UGC 也强拉人工复核)"] + end + IPENT -. 终态收敛(IP 授权模型成熟后) .-> POLICY + CONTENT["待审内容
生成时声明 ipId(无则纯 UGC)"] --> SEL["锁风三档选档器"] + POLICY -->|查 lockStrength| SEL + BLACK -->|叠一层兜底拉档| SEL + SEL -->|无 IP / 低敏| STD["标准档
机审瀑布正常跑"] + SEL -->|IP 中高敏| STRICT["严格档
降低放行阈值 · review 一律转人审"] + SEL -->|IP 最高敏 / 命中黑名单| MANUAL["人工复核档
跳过机审放行 · 直接进人审队列"] + STD --> GATE["锁风门聚合
block>review>pass 取最严 · 落 game_compliance_gate_result"] + STRICT --> GATE + MANUAL --> GATE +``` + +*(图源:审核台运营.md §3.3「锁风三档与 IP 库怎么绑」;选档器下游的机审瀑布见图 11)* + +这张图回答的是图 11 没答完的一个问题:锁风门有标准/严格/人工复核三档,**但「这条内容该走哪一档」是谁、按什么决定的**?图 11 只画了锁风门聚合的 owner 与三层瀑布,把「选档」当成一个黑盒输入;这张图把那个黑盒拆开,讲清档位的来源链——它不该让运营对每条内容手动选,而该由内容的 **IP 归属**自动推导出来。读这张图,新人能看出一条从上到下的推导链:IP 所有者签下授权时,授权档里就带了这个 IP 的敏感度与合同约束;每个注册 IP 据此带一个 `lockStrength`(标准/严格/人工复核);一条内容生成时声明了用哪个 IP,选档器就拿这个 IP 去查它的档位;没声明 IP 的纯 UGC 默认走标准档,内容类型再叠一层题材黑名单兜底(棋牌/捕鱼这类即便是纯 UGC 也强制拉到人工复核档)。三档选出来后,才进入图 11 那条机审瀑布——标准档正常跑、严格档把放行阈值压低、人工复核档直接送人审。 + +这张图最该让人看清的设计缝,是「档位源」现在和将来不是同一个东西。终态设计是把 `lockStrength` 作为 IP 的一个授权属性,直接挂在 IP 实体上,录入授权时由运营按 IP 方敏感度定下来;但现状是——**IP 库目前只是个 seam,授权链还没建,根本没有承载 `lockStrength` 的 IP 实体**。所以图上把「档位源」这一簇明确标成「现阶段=过渡表 `lock_strength_policy`、终态=IP 实体属性」,中间那条从 IP 实体指向过渡表的箭头特意画成虚线、注明「终态收敛(IP 授权模型成熟后)」:现在先用一张轻量过渡表按 ipId 或题材关键词映射档位、admin 可配,等 IP 授权模型成熟了再把档位策略收敛进 IP 实体。这样三档不被 IP 库的进度卡死,又不至于产生两套并行的策略源。这条「现在用过渡表、将来收敛进 IP 实体」的迁移,正是评审最该盯住的设计意图——别把过渡表当成终态,也别因为 IP 库还是 seam 就以为三档无从落地。 + +### 运营图 14 · 短信报备闸门 vs 邀请码旁路(C方案)切换纪律〔Mer新·时·现〕(P2) + +```mermaid +sequenceDiagram + participant U as 玩家 + participant P as 绘境AI 平台 + participant S as 短信供应商 + participant G as 合规闸门(#3 短信签名报备) + Note over G: 报备周期 1-2 周不可压缩 · 报备完成前验证码不可用 + Note over U,P: 内测期:报备未完成,但注册漏斗不能被一道审批闸门卡死 + U->>P: 用邀请码注册(C 方案旁路 · 不依赖短信验证码) + P-->>U: 注册成功(漏斗跑通,报备未完成也不影响内测) + Note over G,S: 依赖串联:部分短信供应商要求域名已备案(#2 ICP)
→ 选不强制备案的供应商先行,或等 ICP 完成,二者择一 + G->>P: 报备完成(签名通过)→ 才允许全量切验证码 + rect rgb(255,235,235) + Note over P: 切渠道硬规矩 = 配置切换 + 两项验证绑定(缺一不得只切配置) + P->>P: ① 确认 huijing.captcha.enable 对发码链路真生效 + P->>P: ② 发码 IP 日/时上限已部署(Redis 计数,防短信费用黑洞) + end + U->>P: 输入手机号 + P->>S: 请求下发验证码(两项验证均绑定后才放开) + S-->>U: 短信验证码 + U->>P: 提交验证码 + P-->>U: 登录成功(切到验证码全量) +``` + +*(图源:合规闸门.md §6「短信报备这道闸门如何不卡死漏斗」+ §4 依赖串联;鉴权切渠道两项验证出自 HJ-PASSPORT-EXEC-001 §7.2)* + +这张图回答一个很实际的运营纪律问题:有一道合规闸门(#3 短信签名报备)周期 1-2 周不可压缩、且报备完成前短信验证码根本用不了,**那内测期的玩家怎么注册**?如果硬等这道闸门,注册漏斗在内测期就被卡死了——这正是「合规闸门是日历驱动、一秒也压不动」这条铁律,撞上「产品要尽快验证」这件事时的典型冲突。图上半部分画的就是绘境AI 的解法:把「鉴权」与「短信报备」解耦,内测期玩家用**邀请码**注册(C 方案旁路),完全不依赖短信验证码,所以报备没完成也不影响内测漏斗跑通。这一旁路同时还顺带服务了另一件事——自有端按「邀请制内测、不公开注册」定性(见图 3 的双层定性),邀请码注册恰好是这个定性的落地形态。 + +这张图最该让人记住的是下半部分那条红框纪律:邀请码旁路不是永久方案,等报备完成、要切到短信验证码全量时,**不允许「只切一个配置开关就上线」**。切渠道的硬规矩是「配置切换 + 两项验证绑定,缺一不可」——既要确认 `huijing.captcha.enable` 这个开关真正对发码链路生效(配置生效是一回事),又必须先把「按 IP 的日/时发码上限」用 Redis 计数部署好(发码频率有上限是另一回事);少了后者,验证码接口会被刷爆、烧出一个短信费用黑洞。图上还钉了一条容易被忽略的依赖串联:部分短信供应商要求域名已备案(#2 ICP 回执),所以这道报备和 ICP 之间有先后约束,要么选不强制备案的供应商先行、要么等 ICP 完成,二者择一。这张图标了 (P2) ——它讲的是一个会随日历推进真实发生的切换动作的运营纪律,不是当下就要执行的开发项;在邀请码内测阶段,它是「设计已想清、待时点到了再按纪律切」的待办,评审该确认的是这条「切换前置」别被简化成「改一行配置」,而非现在就去接短信验证码。 + > **运营域图清单与状态表** | # | 图名 | 家族 | 形式 | 状态 | 覆盖内容 | @@ -182,8 +255,11 @@ flowchart TB | 9 | 一壳多游 · L1 精选整包发行 | 架 | SVG新 | 现 | 固定壳 + 远程 GameConfig(禁代码·9c 红线)+ 备案锁(待律所裁)+ 引擎竞标(P1 暂停)+ 零构建生产红利 | | 10 | 变现端到端钱流地图 | 时 | SVG新 | 现 | 三线(广告全真 / 订阅半真 / B 端仅状态机)→ 创作者钱包(恒等式)+ 提现 mock 打款;控制平面三 job + 对账锚点链 | | 11 | 审核台双层审核 | 流 | SVG新 | 现 | 快检 + 阿里云兜底 + 人审 BPM + 锁风三档 + 处置联动(下架现成 / 降权·信用·封账号联动待建);锁风门框架真·原子桩 | +| 12 | 运营对象状态机合集 | 状态机 | SVG | 现 | 四台机并排:提现五态(真跑·终点 mock)‖ B 端询单五态(不碰钱·钱留 M4)‖ 审核工单(第一期待建·超时告警为旁路态)‖ 订阅续期(入账真·收单未接·过期可逆回落);各机触发/终态/幂等键 | +| 13 | IP 库 · 锁风档位来源概念模型 | 概念 | Mer新 | 现 | 选档器 lockStrength 来源链:IP 授权档→IP 实体属性(终态)/ 现阶段过渡表 lock_strength_policy + 题材黑名单兜底;补图 11 未答的档位来源 | +| 14 | 短信报备闸门 vs 邀请码旁路(C方案) | 时 | Mer新 | 现(P2) | 合规闸门(日历)交注册漏斗:邀请码旁路内测不卡注册 / 报备完成才切验证码;切渠道硬规矩=配置+两项验证绑定;依赖 ICP 串联 | -> **状态分布**:11 张图整体状态全为「现」(讲的都是已拍板的现行设计逻辑);状态差异在**元素级**——已建真跑 / 框架真用实心块,待接线 / 待建 / mock / 钱留 M4 / 待律所 / 远期账用虚线框 + 文字小标。本域无「整图待接 / 整图缓做」的图,其纪律点是**不把现行设计里被合规日历闸门或外部资质阻塞的部分画成已建好**。**防漂移门**:本文 frontmatter 记运营域六份源档的 commit hash(README/合规闸门 @ 3e71715a、变现与单位经济 @ 7ecd616e、变现端到端 @ 38357c3d、渠道发行 @ 5cadf504、审核台运营 @ 15b707fd),源档变更即比对。 +> **状态分布**:14 张图整体状态全为「现」(讲的都是已拍板的现行设计逻辑);状态差异在**元素级**——已建真跑 / 框架真用实心块,待接线 / 待建 / mock / 钱留 M4 / 待律所 / 远期账用虚线框 + 文字小标。本域无「整图待接 / 整图缓做」的图,其纪律点是**不把现行设计里被合规日历闸门或外部资质阻塞的部分画成已建好**。**防漂移门**:本文 frontmatter 记运营域六份源档的 commit hash(README/合规闸门 @ 3e71715a、变现与单位经济 @ 7ecd616e、变现端到端 @ 38357c3d、渠道发行 @ 5cadf504、审核台运营 @ 15b707fd),源档变更即比对。 --- diff --git a/docs/architecture/07-运维图说.md b/docs/architecture/07-运维图说.md index 687a84b7..9a93ca44 100644 --- a/docs/architecture/07-运维图说.md +++ b/docs/architecture/07-运维图说.md @@ -168,6 +168,50 @@ flowchart LR 读这张图,最要让人看清的是「**买到什么、买不到什么**」那一栏:本阶段上 k8s 买到的是声明式部署 + `rollout undo` 一键回滚 + requests/limits 共存保护 + 观测栈编排;**买不到的是高可用**——单节点 k3s 一旦节点挂了,集群和所有 workload 一起没,这和今天裸 JAR 挂了没本质区别,反而多背了一整套 k8s 控制平面的复杂度。如果创始人的预期是「上了 k8s 就更稳了」,这里要先校准:高可用要等多节点,而多节点要等有第二台有内存余量的 x86 机器(现在没有)。技术细节上还有两个被图钉住的关键决定:后端走 `hostNetwork: true`(一举两得——既直占宿主 48080 让对外端口零变化,又能连只 bind 在 `127.0.0.1` 的库,`hostAliases` 和 host-gateway 都做不到);隔离期 Pod 用 `server.port=48092` 起(避开正被 live 裸 JAR 占着的 48080),这正是图 2/图 3 的隔离验证安全变体平移到了 k8s。 +### 运维图 9 · 一句话生成游戏 · 端到端 trace 贯穿〔Mer新·时序·接(待接线)〕 + +这张图回答一个最具体的问题:观测体系**做好了到底能干嘛**。前面图 6 画的是观测栈的零件怎么搭、图 5 点的是「达标线画出来了但没人在度量」,而这张图把那套栈兑现成一个看得见摸得着的能力——**一个 `trace_id` 把「一句话生成游戏」这条最值钱的链,从用户在前端点下「生成」那一刻,一路串到便宜模型返回、九门放行、产物编译完成**,中途经过的每一跳都挂在同一棵 trace 树上。这正是源档《观测体系.md》§5.1 列的**头号验收判据**:发起一次生成,在 Grafana 里用同一个 trace_id 就能查到「网关入口 → SAA 各节点 → new-api 调用」的完整链路,而且**这个 trace_id 恰好等于响应头回写的那个 `trace-id`**——前端报错时把响应头里的 `trace-id` 抄下来,运营贴进 Grafana 就能直接定位这次生成卡在哪个节点、哪道门、调模型报了什么。 + +整张图的状态是**接**(待接线):它画的是观测做好之后的目标能力,而不是今天已经能做到的事。所以图上用一条贯穿的虚线把「这条 trace 链」整体标成待接线,中途凡是要新建埋点才有数据的节点(自动 span、九门指标、终态指标、成本/积压)一律虚线框 + 「待接」小标;**唯一一个实心绿块**是 SAA 各节点的 observation——它是后端目前唯一一段依赖已就位、已在以 Micrometer 标准产出的观测信号(详见图 6 正下方那条高亮),其余全靠这条链补齐才能点亮。 + +```mermaid +flowchart LR + U["前端点击「生成游戏」
game-studio"]:::todo + U -->|"注入 traceparent(W3C)"| GW + + subgraph BE["huijing 后端单体(同一棵 trace 树)"] + direction LR + GW["网关入口 · TraceFilter
起 root span
响应头回写 trace-id"]:::todo + AIGC["aigc 服务
建 game_aigc_task"]:::todo + subgraph SAA["SAA 裸图编排 · 每节点一条 observation span"] + direction LR + NB["node: brief
需求拆解"]:::done + NG["node: gen_source
调 new-api(出网 span)"]:::done + NN["node: nine_gates
九门校验"]:::done + NBD["node: build
build-from-source"]:::done + end + GW --> AIGC --> SAA + NB --> NG --> NN --> NBD + end + + NG -->|"OTel agent 自动 span"| NAPI["new-api 网关
→ 便宜 LLM(M3/DS-V4)"]:::todo + + AIGC -. "终态回填 status
gen_task_total{status}" .-> M + NN -. "gen_gate_fail_total{gate}" .-> M + SAA -. "gen_duration_seconds / gen_queue_depth / llm_cost" .-> M + M[("指标平面
成功率 / 耗时 / 积压 / 成本")]:::metric + + GW -. "同一 trace_id 关联" .-> M + M -. "trace ↔ metrics 同 id" .-> T[("trace 平面
= 响应头 trace-id")]:::tracehl + + classDef done fill:#dcfce7,stroke:#16a34a,stroke-width:2px; + classDef todo fill:#fff7ed,stroke:#d97706,stroke-width:1.5px,stroke-dasharray:5 4; + classDef metric fill:#1e293b,color:#fff,stroke:#475569,stroke-width:1.5px; + classDef tracehl fill:#0c4a6e,color:#fff,stroke:#0ea5e9,stroke-width:2px; +``` + +读这张图要抓住三层意思。其一,**实线链是「trace 怎么连成一根」,虚线指向是「metrics 怎么和这根 trace 同 id 挂钩」**:一次生成在 trace 平面是一条完整时间轴(每个 SAA 节点一个 span、调 new-api 那一跳由 OTel agent 自动补 span),同时几个关键节点把业务指标(终态算成功率、九门算 `gen_gate_fail`、耗时/积压/成本)打到指标平面,两个平面经同一个 trace_id 对得上——所以既能看「这一次生成卡哪了」(trace 下钻),又能看「最近一千次生成的成功率趋势」(metrics 看板),这是图 6 那套栈接好后最直接的回报。其二,**绿块与虚线框的对比就是本图的状态纪律**:别因为这张图画得顺就以为链路已经通了——除了 SAA 节点 observation 这一段地基真在,前端 traceparent 注入、网关 root span 与 trace-id 对齐、自动 span、那几个业务指标的埋点,在代码里全是待新建(图 6 散文已逐件点过,五个生成指标当前零命中)。其三,这张图同时钉死了一条**最该据图 review 的设计缝**:响应头那个 `trace-id` 现在取自 SkyWalking 的 `TracerUtils`,而 OTel agent 走的是 W3C `traceparent` 自成一套——两者不打通,前端抄回来的 `trace-id` 就和 Grafana 里 OTel trace 的 id 对不上号、查不到链路。源档《观测体系.md》§6 把「trace context 头怎么对齐成一根」列为**第一期落地就要先打通的头号待核**,这张图把那条缝画在「网关 root span ↔ 响应头 trace-id ↔ 指标/ trace 同 id」这条线上;它一旦没对齐,整张图承诺的「一个 id 贯穿到底」就断在前后端边界,所以它既是观测体系的头号验收判据,也是落地时第一个要验的点。 + > **运维域图清单与状态表** | # | 图名 | 家族 | 形式 | 状态 | 覆盖内容 | @@ -180,8 +224,9 @@ flowchart LR | 6 | 观测体系 OTel→Grafana/夜莺 | 架 | SVG新 | **接** | 采集→管道→存储→看板/告警全链;唯一已就位=SAA 节点 observation,其余待接线;Collector 居中/双看板分工/旁路铁律 | | 7 | admin 观测入口 | 流 | Mer新(内联) | **接** | 控制台一键进盘链路 + SSO 免登 + 嵌入方式/SSO 两处待核;现状=零、整套新建 | | 8 | k3s 单节点迁移 | 架 | SVG新 | **缓** | 单节点 k3s + staging 应用 + 观测栈,库不进集群;四阶段迁移路;裸 JAR 兜底全程保留;买到/买不到边界 | +| 9 | 一句话生成游戏 · 端到端 trace 贯穿 | 时 | Mer新(内联) | **接** | 一个 trace_id 串前端点击→网关→aigc→SAA 各节点 observation→new-api→九门→build;trace 与 metrics 同 id 关联、= 响应头 trace-id;唯一已就位=SAA 节点 observation,余待接线;= 观测体系头号验收判据 | -> **状态分布**:现 ×6、接 ×2(图 6/7,观测体系待接线)、缓 ×1(图 8,k3s 收窄缓做)。**防漂移门**:本文 frontmatter 记运维域三份源档的 commit hash(README/k8s迁移 @ 15b707fd、观测体系 @ 3e71715a),源档变更即比对。 +> **状态分布**:现 ×6、接 ×3(图 6/7/9,观测体系待接线)、缓 ×1(图 8,k3s 收窄缓做)。**防漂移门**:本文 frontmatter 记运维域三份源档的 commit hash(README/k8s迁移 @ 15b707fd、观测体系 @ 3e71715a),源档变更即比对。 --- diff --git a/docs/architecture/assets/07-端到端全链泳道.svg b/docs/architecture/assets/07-端到端全链泳道.svg new file mode 100644 index 00000000..12b3ef28 --- /dev/null +++ b/docs/architecture/assets/07-端到端全链泳道.svg @@ -0,0 +1,228 @@ + + + + + + + + + + + 图 8 · 端到端跨域全链泳道 + 一句话 → 出包 → 上线 → 被玩 → 数据回流 → feed 重排,八条泳道串成一条完整系统链。下半叠一条并联钱流(广告曝光 → 计费 → 分账 → 钱包)。把碎片拼成整条系统,这是最该先读的一张。 + + + + 状态约定: + 实线步骤 = 现行已建(机制实测);橙虚线小标 = 现状桩(feed 游标分页恒返第一页 / 真广告 SDK 仍 mock);紫虚线 = tier2 富游戏轨(远期·待 spike,不入现行链)。整链主路 = 现 + 桩,绝不读成全实。 + + + + + + + + + + + + + + + + 创作者C 端 + game-studio前端宿主 + aigc + SAA生成层 + compliance合规审核 + project+ feed + 玩家C 端 + telemetry遥测回路 + ad + trade钱流并联 + + + + ① 一句话 + 选风格 + 零门槛创意输入 + 素材 + + + + ② 提交生成请求 + POST /app-api/aigc/generate + + + ⑫ iframe 沙箱试玩 + CSP + sandbox · SDK 注入受控面 + + + + ③ 建生成任务 + 202 + taskId · Dispatcher 派发 + + + ④ SAA 裸图 16 节点编排 + render→classify→design→generate→… + → new-api → 便宜 LLM → 九门兜底 + + + ⑤ 九门过 → emit 出包 + done 由确定性门定,非 LLM 自评 + + + + ⑥ 回写 project 草稿 + game_version status=0 草稿 + + + ⑦ submitPublish 提审 + project 编排发布 · 落锁风门 + + + + ⑧ 锁风门裁决 + pass / review / block 取 max + + + + ⑨ PUBLISHED → 入 feed + status=4 · game_feed_rank 排序 + + + + ⑩ 竖屏 feed 刷到 + 即点即玩 · anon_id 匿名可达 + + + ⑪ 试玩 · 互动 + 点赞 / 收藏 / 分享 / 跳过 / 举报 + + + + ⑬ 埋点上报 + 聚合 + uk_event_id 幂等 · 日聚合 + + + ⑭ 算质量分 0–100 + error_rate 硬降权:跑不动沉底 + + + + ⑮ feed 重排 + sort_score 降序 = quality + boost − 限曝光 + + + + Ⓐ 游戏内广告曝光 + SDK Plugin.Ad · 激励 / 插屏 + + + Ⓑ ad 计费台账 + game_ad_revenue · 以分计 · uk_trace 防重 + + + Ⓒ trade 分账入账 + source_ref 对账 · net = gross × rate + + + Ⓓ 创作者钱包 + 恒等式 balance+frozen+提现=收入 + + + + + + + + + + + + + + + + + + + pass 才入流 + + + + + + + + + + + + + + + + + + 回流闭环:更优游戏流回到玩家眼前 + + + + + 游戏内广告 + + + + + + + + 出包即可预览试玩 + + + + + 桩:feed 游标分页恒返第一页,Redis 候选集=增长期形态 + + + 桩:provider=mock,真广告 SDK 待接渠道 + + + 提现打款桩:缺渠道须 fail-fast,绝不发假钱 + + + + tier2 富游戏轨(远期·待 spike,不入现行链) + AgentScope 自治 ReAct + Phaser 无头 → 真 src 源工程 + 换的是"内容怎么造",出包后仍走同一条上线 / 发行公共件 + + + + 图例: + 现行主路(一句话→出包→上线→被玩) + 数据回流(把链弯成飞轮) + 合规总闸(pass 才入流) + 远期 tier2 轨(不入现行链) + + 现状桩(feed 游标 / 真广告 SDK / 打款) + 旁路(出包即可预览) + 安全 + 数据 + 可靠 + 沙箱/打款=安全 · 回流=数据 · 幂等对账=可靠 + + + + 新人一眼看出: + ① 没有任何一环跨域接缝是断的——相邻泳道交接处对得上,系统才闭环;② 合规门是上线总闸(⑧),不 pass 进不了 feed;③ 数据回流(⑬⑭⑮)把线性链弯成飞轮,是"越用越聪明"的来源; + ④ 钱流(ⒶⒷⒸⒹ)与主链并联、经 source_ref 串起对账;⑤ 现状要诚实读:feed 分页 / 真广告 SDK / 打款都还是桩,tier2 富游戏轨是远期、不在这条现行链上。 + + 映射:产品/README §1 闭环 + 架构/README §5 + 后端/README §3 五条业务链 + 后端/数据模型 §2 + 运营/变现与单位经济 + 运维/smoke §1.3 | 状态:现 + F(桩与远期已标)| 设计变动须同步本图 + diff --git a/docs/architecture/assets/08-系统上下文.svg b/docs/architecture/assets/08-系统上下文.svg new file mode 100644 index 00000000..1151fb00 --- /dev/null +++ b/docs/architecture/assets/08-系统上下文.svg @@ -0,0 +1,179 @@ + + + + + + + + + 图 9 · 系统上下文与外部依赖边界 + C4 L1 系统上下文:中心是绘境AI 平台(单体),左边外部用户、右边外部依赖系统。一眼看清"系统边界到哪、对外依赖谁、各依赖现接还是远期"。 + + + + 状态约定: + 外部依赖按接入度标三态——实线框 + 绿「已接」= 现行已联通调用;橙虚线框 + 「待接」= 设计已定、被日历闸门 / 进件阻塞;紫虚线框 + 「远期」= 排期更后或竞标未决。绝不把待接 / 远期画成已接。 + + + + 绘境AI 平台(内网单体 · 系统边界内) + monorepo 先行 · 13 业务模块 jar 聚合进一个进程 + + + + game-studio + Vue3 + Vant · 创作者 + 玩家 + C 端产品前端 · 试玩宿主 + + + game-admin + Vue3 + Element Plus + B 端运营 + 管理员后台 + + + + Spring Cloud Gateway · MVP 软转发(身份可信化) + + + + game-cloud 后端单体(Huijing fork · Java 17) + 13 模块:studio · aigc · runtime · project · feed · telemetry +      trade · ad · compliance · community · biz(+ ip seam · pay 原生) + + AI 生成层:SAA 裸图编排 → 经 new-api 出网调便宜 LLM + + 中间件(系统边界内,自建):MySQL 8.0 · Redis 7 + 权限只在后端可信边界强制 · 上游 API key 不裸暴露 + + + + 平台对外姿态: + 出网只经受控网关(生成走 new-api / 素材走 mmx),不让游戏自行联网(CSP connect-src 'none')。 + 所有外部依赖均可换 mock ↔ 真实现零改业务码切换;打款例外:缺渠道 fail-fast 不发假钱。 + 安全 + 成本 + 伸缩 + 数据 + + + 外部用户(系统边界外 · actor) + + 创作者 + 一句话生成 / 发布 / 看收益 + studio · C 端 + + + 玩家 + 刷 feed 即点即玩 / 互动 + studio · C 端 · anon_id 匿名可达 + + + 运营 / 管理员 + 审核 / 精选 / 封禁 / 看板 + admin · B 端 · system_users + + + B 端 / IP 客户 + 提需求 / 看 demo / 验收 + 现金线首位 · biz 单据流 + + + + + + + 浏览器 HTTPS + + + 外部依赖系统(系统边界外 · 各标接入度) + + + + new-api 网关 → 便宜 LLM(DeepSeek / MiniMax) + 已接 + 生成主线:SAA 经 OpenAI 兼容接口调模型 · 单 key 入计费台账 + 部署在 mini-infra · 多通道兜底(二厂系全废已实战) + + + + mmx-cli / MiniMax(图 / 音 / 封面素材生成) + 已接 + agent 造游戏直接 CLI 调 · 免 GPU 免训练 · 成本入同一台账 + + + + 对象存储 / CDN(MinIO 内网 · 阿里云 OSS 生产) + MinIO 已接 · OSS 远期 + 游戏包 / 素材 / 封面;MVP 整包内嵌 DB,无 OSS 也可跑 + + + + Gitea 代码仓(Aliyun · 101.200.34.71) + 已接 + 代码同步中转:push :2222 / 匿名 clone :3000 → mini-desktop 重建 + + + + 广告联盟(穿山甲 CSJ / 优量汇 GDT) + 待接 + 现 provider=mock;真 SDK 接入待广告资质 + 渠道落地 + + + + 微信 / 抖音小游戏渠道 + 远期 + 一壳多游 L1 精选整包 · 备案锁约束 · 引擎竞标未决 + + + + 支付商户(微信支付 / 提现打款通道) + 待接 + pay 模块未接入单体 · 进件待 ICP;缺渠道打款 fail-fast + + + + 短信服务(验证码 / 通知下发) + 待接 + 登录验证码 / 关键通知 · 待短信签名报备闸门 + + + + + + + + + + + + + + + + 图例: + 已接(现行已联通调用) + 待接(设计已定 · 闸门 / 进件阻塞) + 远期(排期更后 / 竞标未决) + 系统边界内(绘境AI 平台单体) + + + + 新人一眼看出: + ① 系统边界 = 绘境AI 单体(含自建 MySQL / Redis);MySQL / Redis 是边界内自建组件、不是外部依赖,所以不画在右侧。 + ② 对外只有两类联通是"现行已接":生成 / 素材(new-api · mmx)与代码 / 存储底座(Gitea · MinIO);变现侧的广告、渠道、支付、短信全是待接 / 远期。 + ③ 这正是运营域那条"合规闸门是总闸"在依赖边界上的投影——能赚钱的几条外部线,都卡在 ICP / 资质 / 备案这些日历闸门后面,绝不能读成已接。 + + 为什么这样切边界: + 平台把"不差异化但耗时"的能力(后台框架 Huijing、大模型、引擎、素材)全用外部现成件,边界内只留真正的护城河(生成编排 / 流量分发 / 收益闭环 / 数据飞轮)——这就是"5 人 + ¥4,300/月"能跑起来的取舍。 + 出网只走受控网关、key 不裸暴露、游戏侧 CSP 禁网,是把"系统边界"同时当成安全边界来守:不可信的游戏代码与不可信的外部头,都在边界上被换成可信形态。 + + 映射:架构/README §1·§2 + 运维/README §1.1 四机 + 运营/README §2 合规闸门 + 内网凭据与端点 | 状态:现 + 接(外部依赖三态已标)| 设计变动须同步本图 + diff --git a/docs/architecture/架构/assets/arch-13-逻辑物理拓扑.svg b/docs/architecture/架构/assets/arch-13-逻辑物理拓扑.svg new file mode 100644 index 00000000..fa3c35a8 --- /dev/null +++ b/docs/architecture/架构/assets/arch-13-逻辑物理拓扑.svg @@ -0,0 +1,179 @@ + + + + + + + + 图 13 · 13 逻辑模块 → 单体物理打包 / 运行拓扑 + 破除「13 模块 = 13 微服务」的误解:13 个逻辑模块按领域各自独立,物理上聚合进同一个 JAR、跑成单一进程;依赖方向就是未来微服务的天然切割线。 + + + + 读图约定: + 实线绿/蓝块 = 现行已建并打进单体;橙虚线 = 当前未接入单体启动器(pay);紫虚线 + 「远期」= 未来微服务拆分形态,当前不做。本图整体状态 = 现,仅右栏拆分愿景为远期。 + + + + 逻辑视图 · 13 个领域模块(各自独立) + 按领域边界切分;每个模块 = 一个独立领域 + -api / -server 两段式 jar + + + + 两段式 jar: + -api 包 = 只声明 DTO + Feign 接口(跨模块只认它) + -server 包 = 实现;模块间只经对方 -api 单向调用,零反向依赖 + + + + 创作链路 + + studio创作编排STU + + aigc生成原子AGC + + runtime编译沙箱RT + + project项目生命周期PRJ + + + 分发与数据 + + feed · FED + + telemetry · TEL + + + 变现链路 + + pay · PAY未接单体 ↓huijing 原生 + + trade · TRD分账结算 + + ad · AD广告计费 + + + 平台与合规 + + community社交通知CMU + + ip · IPseam 寄宿于 compliance + + compliance安全裁决CMP + + biz · BIZB/G 定制 + + 这 13 个是逻辑划分:对内一件完整的事,对外只露窄接口。它们各自独立, + 但物理上不是 13 个进程 —— 右侧看它们怎么聚成一个。 + 注:ip 不独立建模块、以 seam 寄宿 compliance(D5 裁定);pay 是 huijing 原生模块、 + 当前在启动器里被显式注释排除。两者状态以 13模块.md §4 为准。 + + + + 物理视图 · 聚合进一个 JAR、跑成一个进程 + MVP = 单体启动:所有模块编译进同一个 JAR,用 Spring Profile 控加载 + + + + + + + jar 聚合 + + + + 单一物理 JAR:game-server + 13 个 -server jar + huijing 基座 jar 全部编译进它,一个 main 启动 + + 同一 JVM 进程 · 同一份 application.yaml · 同一套 MySQL/Redis 连接池 + 模块间调用 = 进程内方法调用(不走网络),逻辑独立但物理共址 + 不存在 split-brain:全仓单写、一份代码一份库,不会两套各跑各的 + + Spring Profile 控各模块加载 / 排除: + @ComponentScan / starter 装配按 profile 决定哪些 -server 进上下文; + pay 的 server 启动器里被显式「注释排除」出装配 —— 故未接入单体 + + + + 运行拓扑:单进程 + 共享中间件 + + game-server单进程 + + + MySQL 8.0单库多表 + + Redis 7缓存/幂等键 + Nginx → Gateway → game-server 单进程;Nacos/RocketMQ 框架自带但 MVP + 未启 broker/registry,故无服务注册发现、无 MQ —— 进程内调用即可。 + + 为什么先单体:复用 Huijing 60% 后台、一个进程一套部署,团队小、成本低。 + 逻辑边界已按领域切清,等流量与团队涨上来,再沿边界平滑拆出去(见右)。 + 证据:单体真启动、Flyway V1–V25 全绿、12 份契约 yaml 锁定、project 真原子跨表发布。 + (运行实测见 docs/mvp/MVP进度总账.md;本图只画拓扑形状。) + + + + 远期 · 沿依赖方向拆 N 个微服务 + 登记为演进路径 · 当前不做、不预先实现 + + 关键洞见:模块间的 + 单向依赖方向 + 就是未来 + 微服务拆分的天然切割线 —— 依赖边界 = 拆分边界。 + + + 沿边界切 + + + 创作生成服务studio + aigc + runtime + + 分发数据服务feed + telemetry + + 资金变现服务pay + trade + ad + + 合规社区服务compliance + ip + community + biz + + + 拆分时几乎零返工,因为已经备好: + · 每模块已是 -api / -server 两段,-api 现成可变 Feign 远程契约 + · 依赖单向、零反向引用,按簇切不会切出环 + · Nacos(注册发现)+ RocketMQ(异步解耦)框架已自带,届时启用即可 + · 进程内方法调用 → 网络调用,调用方代码基本不动 + 触发时机:流量 / 团队涨上来、单体压不住时;不是越早拆越好。 + + 这四簇只是「切割线长这样」的示意分组, + 真正拆几个、怎么拆,到那时按当下负载与组织再定。 + ⚠ 这一栏整体是远期愿景,不是现行架构 —— 现在仍是中间那个单进程。 + + + + + 逻辑独立 + jar 聚合 → + 物理单体(现行) + 沿边界 → + 微服务(远期) + + + 图例: + 现行已建 · 打进单体 + 未接单体启动器(pay) + seam 寄宿(ip) + 远期微服务形态(不做) + 现行聚合/依赖 + 远期拆分 + + + 成本 + 伸缩 + 单体 = 团队小 / 部署省 / 复用 Huijing(成本);逻辑边界即切割线 = 平滑长成微服务(伸缩)。 + + 映射:架构/README.md §3(jar 聚合单体 / Spring Profile / pay 排除)+ 架构/13模块.md §1(逻辑独立 · 物理单体 · 无 split-brain · 状态总表) | 状态:现(右栏微服务拆分为远期) | 设计变动须同步本图 + diff --git a/docs/architecture/架构/assets/arch-14-模块状态热力.svg b/docs/architecture/架构/assets/arch-14-模块状态热力.svg new file mode 100644 index 00000000..1673f503 --- /dev/null +++ b/docs/architecture/架构/assets/arch-14-模块状态热力.svg @@ -0,0 +1,175 @@ + + + + + + 图 14 · 13 模块 真 / 桩 / 未建 状态热力图 + 在四簇聚类底图上按颜色叠加每个模块的真实建设状态,并在每块标出它「最大的那道缺口」—— 一眼看出哪里能用、哪里是债。 + + + + 口径铁律: + 本图状态以 docs/mvp/MVP进度总账.md 为准(实时最高口径);结构 / 实现 / 状态三者冲突时,优先级 = + 状态 > 实现 > 结构 + 。颜色 = 状态,不是结构权威。 + + + + 颜色解码: + ✅ 完成 ×5真端到端、可验收 + 🟡 部分 ×6有壳 / 半真 / 部分接线 + ◻ 特殊 ×2seam 寄宿 / 未接单体 + 🔴 纯未建 ×0(当前为 0) + + + + 创作链路 · 把游戏做出来 + + + + + project · 项目生命周期 ✅ 完成 + 全仓最成熟:状态机 + 唯一真原子跨表发布编排 + 审核队列真查库 + 最大缺口: + Zone 无独立实体(字段承载,MVP 有意简化) + PRJ · 创作链路的状态收口与原子发布脊柱 + + + + + aigc · 无状态生成原子 🟡 部分 + 执行器主链真(M2 e2e:一句话 18–27s 可玩,约 80% 成功) + 最大缺口: + W-G1 worker 尚未接为 staging 默认产线 + SAA 控制平面「建成未默认生产」;玩法模板注册未建(护城河关键路径) + + + + + runtime · 编译 / 沙箱 / 发布 🟡 部分 + 存包 / 取包、engineBundle 内嵌、沙箱桥接都是真的 + 最大缺口: + 真实编译引擎目前是桩 + 微信 / 抖音 / 快手 / TapTap 渠道转换未建;OSS 存取也是桩 + + + + + studio · 创作编排 / 编辑器域 🟡 部分 + 创作编排委托层真(草稿装配 + aigc 接缝 + 血缘追溯) + 最大缺口: + 「7 步生成链」其实在 aigc SAA 图、不在 studio + 六类资产 / 角色 rig / 对白树 / 可视化编排目前全是桩 + + + + 分发与数据 · 让游戏被玩到、被看清 + + + + + feed · 游戏流推荐 / 互动 / 分享 🟡 部分 + 互动信号、getZones、quality 排序都是真的(B2 已 e2e 实证「互动回灌翻转排序」) + 最大缺口: + 游标分页是桩(永远返回第一页) + 候选集纯查 MySQL、无 Redis;举报转 compliance 也是桩 + + + + + telemetry · 事件聚合 / 质量评分 ✅ 完成 + 唯一真端到端数据底座:事件落库 + quality 真算分 + 日聚合 upsert + 创作者 stats 全打通 + 最大缺口: + MQ 异步聚合 = 桩(有意);广告营收字段占位 + TEL · 平台「越用越聪明」的数据回路源头 + + + + 变现链路 · 把钱赚回来 + + + + + pay · 支付收单 ◻ 未接单体 + yudao 原生模块,server 启动器里被显式注释排除 + 最大缺口: + 真实支付收单全未接入 + 卡在「支付进件」这类不可压缩的日历闸门(须等监管 / 渠道审批) + + + + + trade · 分账 / 结算 / 对账 ✅ 完成 + 资金状态机真(逐笔入账 + 冻结 CAS + 对账补偿),41 单测;打款 fail-fast 防假钱 + 最大缺口: + 真 pay 对接 = 桩,受支付进件闸门 mock-gated + 逻辑已真、卡闸门 —— 闸门到位即接 + + + + + ad · 广告联盟 / 植入 / 曝光计费 / 归因 ✅ 完成 + 计费全链真(合规 → 幂等 → 归因 → 台账)+ 验签 fail-fast,24 单测 + 最大缺口: + 真联盟 SDK(穿山甲 / 优量汇)= 桩,受广告审核闸门 mock-gated + AD · 与 trade 一样「逻辑已真、卡在日历闸门」 + + + + 平台与合规 · 让生态转得起来、守得住 + + + + + community · 社交 / 通知底座 ✅ 完成 + 通知底座 + 等级引擎真,3 上游 notify 全通;又补评论/关注/排行 ZSET/弹幕 WS(57 单测) + 最大缺口: + 成就引擎仍未建(MVP 裁剪);弹幕多实例 / 多通道未建 + CMU · 完成度按 MVP 裁剪后的范围计 + + + + + compliance · 内容安全 / 锁风门 🟡 部分 + 锁风门框架 + 真注入发布链 + RBAC 都是真的 + 最大缺口: + 核心检测原子全桩、恒返回 pass + 发布链对违规内容零自动拦截、纯人工兜底 → 放量前必须硬化的合规死锁 + + + + + ip · 素材安全 / 授权 / 风格原子 ◻ seam + 有意不独立建,以 seam 寄宿在 compliance 里(D5 裁定) + 最大缺口: + 风格原子桩;素材安全 / 授权链 / 盗用监测全未建(远期) + 注:面向用户的素材浏览/选用/上传最小后端在 studio 域、非 ip(plan002 U6) + + + + + biz · B/G 端定制工程底座 🟡 部分 + lead 状态机 + 报价落库真,13 单测 + 最大缺口: + 模板硬编码 4 个(非 32 套) + 报价引擎 / 签章 / CRM 纯未建 + + + + 合计 13 模块:✅ 完成 5(project / telemetry / ad / trade / community)· 🟡 部分 6(aigc / runtime / feed / studio / compliance / biz)· ◻ 特殊 2(ip / pay)· 🔴 纯未建 0。 + 三类「卡在闸门」值得单记:ad / trade / pay 卡的不是代码、是 ICP 备案 / 支付进件 / 广告审核这类不可压缩的日历闸门 —— 逻辑先建好,闸门到位即接。 + 最该据图盯的两道债:compliance 检测原子恒 pass(放量前必硬化的合规死锁)、aigc 的 W-G1 worker 未接默认产线(护城河关键路径)。 + 本图是某次快照;颜色与缺口随开发推进会变,任何时刻以 docs/mvp/MVP进度总账.md 的真 / 桩 / 未建为准,本图只给一眼可读的空间总览。 + + + 质量 + 安全 + 真端到端 5 块 = 可验收质量底座(质量);compliance 检测原子恒 pass = 放量前真实合规风险(安全)。 + + 映射:架构/13模块.md §4 状态总表(与 docs/mvp/MVP进度总账.md 同口径) | 状态:现(快照 · 实时以 MVP进度总账.md 为准,口径 状态>实现>结构) | 设计变动须同步本图 + diff --git a/docs/architecture/运营/assets/12-运营状态机合集.svg b/docs/architecture/运营/assets/12-运营状态机合集.svg new file mode 100644 index 00000000..f19ae3f1 --- /dev/null +++ b/docs/architecture/运营/assets/12-运营状态机合集.svg @@ -0,0 +1,227 @@ + + + + + + + + + 图 12 · 运营对象状态机合集(提现 ‖ B 端询单 ‖ 审核工单 ‖ 订阅续期) + 运营域里四个对象各有一台状态机,分散在三条变现线、审核台、订阅会员里。把它们并排画出来,看清每台机各自的触发条件、终态、哪些动作幂等,以及谁已真跑、谁的某段被外部资质卡住。 + + + + 状态约定: + 实线方框 = 该状态/迁移已落地真跑;虚线框 + 小标 = 该段被合规日历闸门或外部资质阻塞(mock / 钱留 M4 / 收单未接)。绿色双框 = 终态。本图整体状态 = 现。 + + + + ① 提现五态(trade · game_trade_withdraw · 已建真跑,终点 mock) + 触发:创作者点提现 applyWithdraw;幂等键 uk_biz_no;金额单位「分」。最硬纪律 = 发起 ≠ 终态。 + + + + 待审 0 + freeze 余额→冻结 + + + 打款中 1 + CAS 0→1(审核内只到此) + + + + 已打款 2 ✓终 + 回调 settlePaid + + + + 驳回 3 ✓终 + refundFrozen 退冻结 + + + + 打款失败 4 ✓终 + CAS 1→4 退冻结 + + + 审核通过 + + 回调成功 + + 审核驳回 + + 回调失败 + + + 打款执行 = mock 桩(待真渠道) + 仅 MockPayoutClient;真 wxpay/alipay + 被合规闸门阻塞,找不到实现 fail-fast + 幂等:申请 uk_biz_no 防重;审核 / 打款终态全走 CAS(已翻走的单二次驱动 CAS 失败、不二次发钱)。 + 卡单兜底:WithdrawPayoutCompensateJob 扫 status=1 超 15min,按单子血统渠道补驱动终态——正常路回调、异常路补偿,两路都过 CAS。 + 降级口径:打款渠道缺失绝不静默降级 mock(那是吞真钱),必须 fail-fast——与广告线「缺渠道降级 mock 可接受」正好相反。 + + + + ② B 端询单五态(biz · game_biz_lead · 单线推进,完全不碰钱) + 触发:客户提单 → 单线性五态;本波只走业务状态机,收款 / 在线签章 / 分账整段留 M4。 + + + + 待跟进 0 + 客户提单 / 线索 + + 已报价 1 + 报价(只展示) + + 制作中 2 + 接单 · 进度工单 + + 待验收 3 + 提交验收 + + + 已交付 4 + ✓终 + + + + 接单 + + + 确认 + + + + 四表:lead 询单主单 · quote 报价(只展示不收款)· progress 进度时间线 · acceptance 验收(带 signed_offline 线下签兜底) + 状态机合法迁移由 BizLeadServiceImpl 写前校验;admin 推进 advance / 报价 quotes / 线下签 sign-offline,app 提单 / 反馈 / 确认。 + + 钱留 M4 + 报价 ≠ 可支付订单:在线签章 / 收款(T-BIZ-08)/ 分账整段留 M4 + 现唯一能标的是 signed_offline——线下签了合同打个兜底标记。B 端是近期现金线,但工程钱流尚未建。 + 前端 game-admin 暂无 biz/lead 视图(待建);状态机本身已真跑,被卡的只是「钱」这一段。 + 幂等:状态机以「待跟进→已报价→制作中→待验收→已交付」单线推进,非法跳转写前即拒;重复推进同一态不产生副作用。 + 整条线虚线红框 = 唯一不碰钱的状态机:它的「终态」是交付,不是收款;真正的资金动作在 ① 提现线、不在这里。 + + + + ③ 审核工单(compliance · game_compliance_review_task · 第一期待建) + 触发:机审瀑布判 review / 锁风人工档 / 举报率超阈值事中召回;MVP 轻量状态机起步,Flowable 留远期。 + + + + 待认领 + 机审 review / 建单 + + + 审核中 + 认领 CAS 抢占 + + + 已升级 + 拿不准 → 复审/主管 + + + 超时告警 + 超 SLA → 介入处理 + + + + 已通过 ✓终 + approve → 推进发布 + + + + 已拒绝 ✓终 + reject → 触发处置 + + + 认领 + + + 上级接手 + + + + approve + + reject + + + 超 SLA 未认领 + + + + 现状(诚实分层): + 这台机第一期才建——今天 + compliance 只有「申诉」一种 + 人工单,没有带认领/分派/ + SLA 的内容审核队列底座。 + 人审终裁 = 最高权威, + 覆盖机审结论。审核状态 + 唯一权威在 compliance。 + 幂等:认领用 CAS 抢占防双审;事中召回以 gameId+窗口为幂等键,同一内容一个窗口只召回一次、不每轮重复建单。 + 为什么走 BPM 而非裸 status:认领 / 分派 / 升级 / 超时 / SLA 统计用裸字段会越写越乱,声明成流程图由引擎驱动。 + 两条人工流并存——审核工单(compliance:review:handle 新增)与申诉单(compliance:appeal:handle 已建)共用同一套将建的队列 UI 框架。 + 权威:人工 approve/reject 覆盖机审;终裁回写驱动后续(放行推进发布 / 拦截触发 §3.5 处置联动)。 + 整台机虚线 = 第一期待建(队列底座 + 状态机 + admin 审核台);今天发布链对违规内容零自动拦截、纯靠人工兜底。 + 超时告警 = 旁路态(不是终态),介入后回到审核中;只有「已通过 / 已拒绝」是真终态。 + + + + ④ 订阅续期(trade · game_trade_subscription · 入账已建 / 收单未建) + 触发:admin 赋订阅 grant;有效性以 expire_time 为权威、无 cron 物化;自助购买那一半被支付通道阻塞。 + + + + 无订阅 / 已过期 + expire_time ≤ now + + + 生效中 active + expire_time > now + + + 赋订阅 + + + 续期 newExpire=max(now,旧)+时长 + + + 到期未续(实时回算,无 job) + + + + 三表:grant 赋余额流水(uk_biz_no)· subscription 一用户一行(uk_user · plan 1月/2季/3年)· subscription_grant 幂等账本(uk_biz_no) + subscription_grant 是 P0 修复加的独立账本——主行 last_grant_biz_no 只挡上一次,独立账本才挡任意历史 bizNo 重放。 + 续期算法 newExpire=max(now,旧expire)+时长,没用完的时长叠加不丢;renewByCas 防并发 lost-update。 + + 收单待支付 + 自助购买未接:现只能 admin 手动赋(source=admin_grant),自助购买需接真实支付收单 + 回调驱动 grantSubscription + 替代 admin 手动赋——这一半被日历闸门(支付进件)阻塞,抽象已留好接缝,补真实现即切。 + 幂等:每笔赋订阅落账本一行 uk_biz_no,挡任意历史 bizNo 重放;续期 renewByCas 防并发。 + 终态语义特殊:订阅没有「彻底结束」的吸收态——「过期」可被下一次续期重新拉回「生效中」,是可逆回落,故图上画双向。 + C 端查态 mine:effectiveStatus 按 expire_time > now 实时回算,不跑 cron 物化过期——少维护一个定时任务,代价是查时算一下。 + 入账已建(admin 赋真跑、入创作者钱包恒等式);被卡的只是「自助收单」这一半,不是整条订阅线。 + 这台机与 ① 提现共用 trade 钱包:admin 赋订阅入账 game_trade_account(已真),与广告分账汇合在同一恒等式上。 + 边界:自助购买订阅 = 日历闸门约束(支付收单)的事,MVP 非必需;当前订阅只能 admin 手动赋。 + 分层纪律:实线方框(生效中 / 赋订阅 / 续期)已真跑,仅虚线红框「收单」一段未接。 + + + 图例: + 已真跑状态 + 终态(双框) + 待建状态(虚线) + 被资质阻塞段(mock/钱留 M4/收单待接) + 已落地迁移 + 待建 / 可逆回落 + 可靠 + 幂等键 + CAS + 发起≠终态 + 终态可追 + + 映射:变现端到端.md §2.4/§3/§4 + 审核台运营.md §3.4(dev/2.0.0) | 状态:现(提现真跑·终点 mock ‖ B 端不碰钱·钱留 M4 ‖ 审核工单第一期待建 ‖ 订阅入账真·收单未接) | 设计变动须同步本图 +