梳理核心业务流程(跨模块全链路)
把"用户点击某个业务按钮"到"服务器确认、表现收尾"的整条跨模块链路,写成一份以步骤为纲、每步有源码证据的中文文档。
触发条件
输入来源:通常选取 unity-module-detail 产出(
AboutMe/<一级模块名>/<子模块名>.md)中的某条"核心逻辑"作为本次深挖对象,把它展开成跨模块全链路;也可由用户直接给定一个业务动作。
用户给出以下任一信号即触发本 skill(无需用户主动写"skill"名):
- 明确要"梳理 X 的核心流程 / 全链路 / 跑一遍这条流程"。
- 要"深挖"某个业务动作是如何从一处走到另一处的(点按钮 → 发协议 → 回包 → 表现)。
- 输入是一个流程名,或一段话描述"某个动作做了哪些事、用了哪些模块"。
前置:先用知识图谱定位真相
按 CLAUDE.md 铁律:任何 Grep/Glob/Read 前,先走 code-review-graph MCP 工具获取结构。探码顺序:
get_minimal_context(task="梳理 <流程名> 的全链路")拿全局线索。semantic_search_nodes_tool/query_graph_tool(callers_of/callees_of)定位入口方法、CmdConstant.*通知的发出者与消费端。- 从入口沿调用链往下追:Mediator 动作 → Proxy 发包 → 网络派发 → 回包 Proxy diff → 通知回 Mediator。逐跳用
文件:行号记证据。 - 图谱覆盖不到时再退回 Grep/Read 直接读源码。
核心原则
- 步骤概括是纲领,深挖必须与之 1:1 对应。
## 步骤概括里写几条编号步骤,## 步骤展开深挖就分几个同名小节,顺序、条数、措辞一一对齐——否则读者(包括自己下次回看)会对着"对不上"的步骤很费劲。 - 证据式写作:每条断言、每个动作归属、每段源码都带
文件:行号。措辞不许出现"推测""或类似""应该"——用读到的代码实测结论替换;无法证实的,显式标"未在源码中证实"。 - 先文案后代码:每步"深挖"先给
**处理逻辑**:的纯文字描述(不夹代码、不夹:行号,给读者心智模型),一行一个句子;文字讲完再贴一段带中文注释的代码块示意。 - 要点名主角方法:处理逻辑里凡说"它做了某件事",负责的那个方法必须在文字里点名(如
CreateCityBuilding),不能只藏在代码块注释里一带而过——"没把主角写出来"是最常见的返工点。 - 要点破工具类逻辑:步骤里出现的某个生成/转换/校验工具(如
GenServerBuildIndexID、ConvertCityObjLocalToTile),不能只写"调用它"就当讲完,要单独说明它内部是什么逻辑、为什么这样设计。宁可多两句,不给读者留黑盒。 - 归属以源码为准:写模块职责/边界前,先用图谱确认动作真正落在哪个类。常见误属:把"通知转发者"当成"逻辑执行者"、把 HUD 展示层的职责误派给核心 Mediator。
- 中文写作:标题、术语、流程描述用中文;代码标识符、协议名、
文件:行号保留英文原样。
输出文档结构(必须包含以下章节)
H1 标题 + 范围说明
- 标题:
# <流程名>(<入口 → … → 协议 → 收尾>),括号里用箭头串概括全链路。 - 标题下紧接 blockquote:一段范围说明,写清链路从哪个模块入口、经过哪些关键通知/代理、以什么结束;再补一句"本文所有关键断言均带
文件:行号证据,源码片段直接摘自当前工程"。
## 步骤概括
编号列出 3~10 步,每步一句话,把主流程压缩成一个可背下来的清单。主干动作 + 关键方法/通知名都写在这段里(后续每步深挖以它为基准展开)。
## 参与模块列表
Markdown 表格,列固定为:模块(程序集/位置) | 参与步骤 | 在流程中的职责 | 边界。
- 模块:类名 +
程序集/路径,多个同类合成一行(如GridCollideItem · GridCollideMgr)。 - 参与步骤:用 ①②③… 标注参与哪些步骤,与步骤概括条数对应。
- 职责:浓缩成短行——有几个职责就写几行字,每行一句短语,不许写成一长串连排句。
- 边界:写它刻意不做什么(如"不直发协议、不操作场景""纯数据只读""纯表现、被动接收"),一个模块1~3行。
- 表后补充依赖方向说明(如"业务逻辑单向依赖 Hotfix → Client,Client 对 Hotfix 零感知"),这是本项目最值得记的架构事实。有几句话就写几行。
## 与服务器的数据协议
只讲本流程涉及的两类报文,各搭一个结构块:
- 发送包(请求):协议名 + 协议号 +
request{字段}与response{字段}结构(tag : 类型,*类型(field)为字典数组),并写明谁在哪一步组装发送。 - 接收包(回执/服务器下推):很多"转正"不是靠 request 的 response 字段直回,而是服务器下推整份列表、客户端 diff 检出变化——务必写清这条数据通路:网络派发点 → 数据层 的 diff 方法(附判定条件)→ 发出哪个通知 → 逻辑层消费后做收尾。
- 末尾配一张
收/发关系一览表:方向 | 协议(协议号) | 结构 | 触发/消费点。
## 步骤展开深挖
对步骤概括每一条开一个小节 ### 步骤 N · 名称(主要负责模块),内部分两半:
**处理逻辑**:纯文字分步说明,一句一行。- 带注释的 csharp 代码块:首行
// 位置:<文件:行号>标明这段对应的真实调用/分支,代码内逐行加中文注释点出意图;若该步调用了一个关键方法,代码块末补一行"方法体(<文件:行号>,逻辑示意)"注释,一行注释讲一点内部逻辑。
结尾
blockquote 一行话链接回上级文档(若存在):回链到本条核心逻辑所在的模块文档(unity-module-detail 产出的 <子模块名>.md),形如 > 本流程所属核心逻辑 L#,见 [<子模块名>.md](../<子模块名>.md)。
回链的 ../ 必须保留:本文件位于 AboutMe/<一级模块名>/<子模块名>/,而清单文档位于其上一级 AboutMe/<一级模块名>/,两者不是同一目录。去掉 ../ 会指向不存在的 AboutMe/<一级模块名>/<子模块名>/<子模块名>.md。
工作流
- 定流程边界与归属:问清(或从上下文推断)流程从哪个入口到哪个收尾;形成一句"全链路"话(也就成了 H1 括号里的箭头串)。同时定出该流程所属的
<一级模块名>与<子模块名>,用于确定输出目录。判定顺序:用户指名 → 上游 detail 文档路径AboutMe/<一级模块名>/<子模块名>.md→ 用户给定的L#所属的那份清单 → 询问用户。流程跨多个子模块时,以"入口方法所属的子模块"为准;入口不明确时列出候选询问用户,不得自行猜测。 - 沿着调用链探码并记账:从入口方法一路往下,用图谱
callers_of/callees_of+ 断言源,把每一步触发者、CmdConstant.*通知、Proxy 发包方法、网络派发 case、收包 diff、回执通知、收尾表现串成一张证据表(动作 → 归属类 → 方法 → 文件:行号)。 - 先写步骤概括:把证据表压成 3~10 条编号步骤,这是之后所有章节的对齐基准。
- 写模块列表:按证据表把参与类收进表格,职责短行为主、边界写"不做什么"。
- 写数据协议:只有本流程真正收发过的协议才写;diff 型转正务必写全数据通路。
- 逐步骤深挖:每步先纯文字、再代码块,1:1 对齐步骤概括;点名主角方法、点破工具逻辑。
- 自检后定稿:对照下方清单逐项核对,再交付。
自检清单(写完后逐项打勾)
- 步骤概括与深挖小节 1:1 对应,条数与措辞一致。
- 每步深挖都是"先纯文字处理逻辑(一句一行)、再注释代码块"的顺序,文字里不夹代码。
- 每条断言、每段源码都有
文件:行号;全文无"推测/或类似/应该"措辞。 - 处理逻辑里提到的关键动作,负责方法已在文字中点名(不只出现在代码注释里)。
- 步骤里的生成/转换/校验工具都单独点破了内部逻辑。
- 模块列表的职责列是短句、边界列写"不做什么",参与步骤 ①②③ 与步骤编号对齐。
- 数据协议写清了 diff 型转正的全数据通路(派发 → Proxy diff → 通知 → Mediator 收尾)。
- 该项目数据层的类未出现"调用 GameObject/UI API"的写法(纯数据约定)。
约定
- 源码片段必须带
文件:行号:// 位置:紧跟代码块首行,或行末括注。 - 程序集标注:本项目
Hotfix= 可热更业务层,Client或其他写法 = 不可热更纯表现层;模块表里写清程序集归属,帮助读者理解职责边界。 - 不要扩张范围:只写本流程真实经过的模块与协议,不要顺手把相邻流程/协议也塞进来。
- 中文行文约定:禁止长串的句子,或把几个句子连在一行/一段。必须一句话一行;即使描述一件事用了一个长句,也要拆成多行单句。与"职责短行、不连排句"的原则一致,步骤概括、处理逻辑、模块表等所有表述均适用。
- 不新起 README:本 skill 产出的是"单条流程"文档,落于
项目根目录/AboutMe/<一级模块名>/<子模块名>/下(如AboutMe/城建/建筑/新建建筑流程.md)。文件名直接取流程名,不带NN-编号前缀。若它是从某总览拆出,把总览(AboutMe/Overview.md或AboutMe/<一级模块名>.md)对应章节替换为跳转链接,避免一份内容两处维护。 - 阅读顺序:同一子模块下的流程文档按 detail 文档"核心逻辑清单"的 L1、L2… 顺序阅读;文件名不带编号,故目录排序不代表阅读顺序。
输出契约
- 输出一份
.md,写入用户指定路径;默认落在项目根目录/AboutMe/<一级模块名>/<子模块名>/下。 - 文件名直接用流程名(如
新建建筑流程.md),不再带NN-编号前缀;若<一级模块名>/<子模块名>/目录不存在则先创建。 - 层级关系:本文件与 detail 的清单文档
AboutMe/<一级模块名>/<子模块名>.md配套——清单在AboutMe/<一级模块名>/下,本文件在其同名的<子模块名>/子目录内。不再与Overview.md、AboutMe/<一级模块名>.md平级。 - 完整结构顺序:H1+范围 → 步骤概括 → 参与模块列表 → 与服务器的数据协议 → 步骤展开深挖 → 尾部回链。
- 若该流程原属于某总览文档(如
AboutMe/<一级模块名>.md的子模块章节),顺带把总览对应小节替换为指向本文件的跳转链接,链接写相对路径(从AboutMe/<一级模块名>.md出发即./<子模块名>/<流程名>.md)。 - 同名冲突防护:写入前检查目标文件
项目根目录/AboutMe/<一级模块名>/<子模块名>/<流程名>.md是否已存在。若已存在且内容为其他流程,先向用户确认再覆盖或换名,不得静默覆盖他人文件。 - 旧路径遗留检测(必须先检测再写入):写入前扫描
项目根目录/AboutMe/整棵树,检查是否存在旧编号流程文档。- 命中特征一:文件名形如
NN-xxx.md(数字前缀 + 短横线)。 - 命中特征二:文件直接散落在某个
<目录>/一层,且 H1 形如# <流程名>(… → …)、正文含"步骤概括 / 参与模块列表"章节。 - 旧目录名可能是历史"子系统"名,未必等于当前任一一级模块名,故须全树扫描,不得只在当前一级模块下找。
- 须按内容特征排除新布局下正常的清单文档
<子模块名>.md(其正文含"功能定位 / 职责 / 功能 / 边界 / 核心逻辑清单"章节),那是 module-detail 的产出,不是旧流程文档。 - 命中时先暂停写入,向用户说明"检测到旧路径流程文档 <路径列表>",并给出选项:迁移到新路径后继续 / 保留旧文件、另写新文件 / 本次不写入。
- 用户未确认前,不得覆盖、不得删除、不得移动旧文件;迁移后遗留的旧空目录由用户自行清理。
- 命中特征一:文件名形如
- 禁止静默忽略:不得因旧文件存在就直接跳过写入,也不得在未提示用户的情况下另起新文件。