Cherry Studio 代码评审实践:gh-pr-review 技能中项目专属评审指南的设计与规则体系 📅 发布时间:2026/9/19 23:07:54 👁 浏览次数: Cherry Studio 代码评审实践gh-pr-review 技能中项目专属评审指南的设计与规则体系【免费下载链接】cherry-studio Cherry Studio 是一款支持多个 LLM 提供商的桌面客户端项目地址: https://gitcode.com/CherryHQ/cherry-studio本文深入解读 Cherry Studio 仓库内gh-pr-review自动代码评审技能的核心参考文档 cherry-review-guidance.md。读完后你将掌握该项目如何把架构优先评审落成可执行的规则体系从作用域分诊、引擎/声明式分层中的实体泄漏识别、修复建议的缺陷高度策略到 IpcApi/DataApi 边界、SWR 数据钩子与 React Hooks 的逐条检查项以及按变更区域路由权威文档的参考路由机制。一、文档定位自动化评审的项目专属镜头在 SKILL.md 定义的六阶段评审流程中本指南承担第 3 阶段Architecture-First的评审依据适用于代码、混合、架构文档和项目技能评审。它明确声明自己是项目专属评审镜头它补充而非取代 code-checklist.md 中的证据要求只报告有当前代码依据的问题不凭空推断同时定义每个变更区域应加载哪些内部文档、内部技能与外部参考——但强调按变更区域加载不要把所有外部指南粘贴进每份评审且项目文档与仓库代码优先于外部参考。这种规则文档 路由表的组织方式使评审 Agent 无需依赖记忆即可对 Cherry Studio 特有的边界DataApi、服务所有权、IpcApi、渲染进程钩子做出一致判断。二、作用域分诊先归类再找问题指南要求评审者在寻找问题之前先把被评审模块归类到下表并据此确定评审焦点区域常见文件评审焦点数据系统src/main/data/、src/shared/data/、src/renderer/data/、docs/references/data/正确的系统选型、DataApi 作用域、迁移、行/实体边界服务边界src/main/data/services/、src/main/services/属主服务、跨服务调用、事务、副作用IPC / preloadsrc/shared/ipc/、src/main/ipc/、src/preload/、src/renderer/ipc/、遗留 src/shared/IpcChannel.tsIpcApi 路由、入参校验、暴露面、兼容性、迁移完整性生命周期 / 窗口 / 路径src/main/core/、窗口服务、路径访问生命周期所有权、清理、application.getPath、WindowManager主进程架构src/main/的移动、新增、导入封闭顶层集合、落位、依赖方向、公开边界渲染进程架构src/renderer/的移动、新增、导入类型/领域落位、向下依赖、特性隔离、公开边界共享层src/shared/真实的跨进程需求、无状态表面、封闭顶层、API 契约渲染数据钩子src/renderer/data/、使用useQuery/useMutation的钩子SWR key、失效、乐观更新、外部 store 快照React UIsrc/renderer/、packages/ui/cherrystudio/ui、i18n、a11y、钩子正确性、设计体系契合网络下载包管理器配置、锁文件、安装/下载代码、模型或二进制清单全球与中国加速双源、产物一致性、来源选择、完整性校验命名 / 模块形态新增/重命名/移动的文件与目录、新类与桶文件路径大小写、导出角色命名、Service/Manager 角色、提升时机、桶边界三、架构优先引擎 声明式的结构模式指南的核心观点是评审高度与发现问题同样重要。每个被变更模块应先以架构级标准落位、所有权、依赖方向、抽象完整性对照治理文档评审然后再下探到行级细节。当两级都产出发现时架构级发现是主问题行级细节并入其中汇报——绝不允许行级吹毛求疵替代边界问题的上报。代码库在每个深度都重复同一个结构模式通用引擎搭配声明表面。指南列举了这些引擎/声明配对均可在仓库中直接验证WindowManagerwindowRegistryWindowManager.ts 是窗口生命周期引擎windowRegistry 按窗口类型声明元数据引擎通过onWindowCreated事件让领域服务注入窗口特定行为从而保持实例无感知生命周期容器 serviceRegistry 相位/依赖装饰器src/main/core/lifecycle/ 提供Injectable、ServicePhase、DependsOn等装饰器WindowManager正是用Injectable(WindowManager) ServicePhase(Phase.WhenReady) Priority(5)声明自身相位而非硬编码启动顺序JobManager/SchedulerServicejobRegistryJobManager 与 jobRegistry.ts 分离任务处理器由属主领域自行注册SeedRunnerseederRegistrySeedRunner.ts 只负责执行MigrationEnginemigrators/MigrationEngine.ts 引擎不感知单个迁移器DataApi/IpcApi 路由器 单点 schema 与 handler 注册CacheService/PreferenceService 共享 schema 注册表ai/runtime/registry 驱动工具/MCP 管线 按领域的工具单元。由此得到一条对所有被触碰模块都成立的评审判据识别该模块的引擎/声明配对然后检查变更落在哪一侧。加在引擎侧的按实例区分的行为就是实体泄漏Entity Leakage——无论跨模块features 渗入core/、data/、shared/还是模块内部模块自身的通用层。渲染进程一侧renderer.md 把同一规则表达为类型 × 领域网格 严格向下的边共享行components/、hooks/、services/、utils/、data/、ipc/、workers/定义上即领域无感知领域知识只允许存在于领域行features/domain/或提升前的pages/domain/与应用层组合windows//routes//顶层pages/。Lint 已禁止shared → features/pages、feature → feature、page → page的导入边评审要抓住的是不带导入到达的领域知识——路由字符串、缓存 key 前缀、领域 id 分支、feature-flag 属性——这些是 lint 看不见的。实体泄漏在各模块的具体形态指南给出了一张非穷举的泄漏长什么样速查表摘录关键行通用表面泄漏表现生命周期容器core/applicationApplication/BaseService按具体服务名分支为一个服务硬编码启动顺序而非用ServicePhase/DependsOn声明WindowManagercore/window引擎或共享行为代码按某一种窗口类型分支而不是在windowRegistry中按类型声明 mode/flagJob 与调度器core/job、core/schedulerJobManager/SchedulerService分支到具体任务类型某个任务的重试/并发策略在引擎里特判core/导入 feature 来执行任务而非领域注册 handler路径core/paths路径代码临时推导某 feature 目录而非声明式namespace.keyDataApi 基础设施data/api路由器或共享分页/排序/数据变更助手特判某一个端点或表CacheService/PreferenceService按 key 的行为TTL、层级、持久化、桥接写死在服务里而不是声明在 schema 注册表中迁移与种子data/migration/v2、data/db/seedingMigrationEngine/SeedRunner分支到某个迁移器/种子共享映射工具编码单一领域的转换数据库 schemadata/db/schemas一个列承载多种行类型语义、靠解析解码存在无人消费的关联列role、sourceIdIpcApi 桥shared/ipc、preload通用桥或错误模型长出只有一个路由使用的字段/分支在通用桥旁私加专用通道AI 运行时与 providerai/runtime、ai/provider共享驱动/注册表契约长出只被一个驱动消费的字段流/管线循环按具体 provider 或模型 id 分支而非注册表能力标志AI 工具/MCP/审批分发器、权限门或服务端管线特判具体xxxTool/xxxMcp名称侧表领域参数进入通用ToolHandler契约主进程services/桶能力服务文件、通知、快捷键按调用方是谁头像 vs provider logo分支而非暴露通用 API 让属主领域组合渲染共享行共享模块在不导入某领域的情况下编码该领域feature-flag 属性isAgentPage、路由路径分支pathname.startsWith(/agents)、按领域 id 切换、特判某领域的缓存 key兄弟领域features/domain/一个领域分支到另一个领域的 id/类型/状态命名为两个领域的协调者共享钩子是隐藏在同一条边packages/ui原语原语长出业务属性、领域渲染分支或数据层知识而不是 render-prop/slot 注入点src/shared/契约共享类型/枚举/工具长出只被一个进程或一个领域消费的成员跨所有模块的识别信号每条都是发现而非风格挑剔通用分发器/管线/注册表/权限检查按具体 id 分支if (name xxxTool)、对具体服务端的switch名称列表侧表KB_TOOL_NAMES [...]或字符串前缀魔法key.startsWith(CherryKb)用来分类通用集合中哪些成员获得特殊行为领域特定参数穿过大多数实现都忽略的通用契约如共享ToolHandler.run签名上只有知识领域 handler 消费的allowedIds一个原语字段承载多个不相关语义下游靠正则、顺序或约定解码而非可辨识联合基础模块导入具体 feature来做本应由 feature 拥有的决策。四、修复方向恢复所有权而非给泄漏打注释对每个实体泄漏/边界发现推荐修复必须按治理架构文档指名属主层与目标形态把关注点移入通过通用层已定义或应定义的扩展点注册的领域属主单元、引入显式领域类型、或迁移模块落位。先陈述架构级解决方案再给实现步骤。指南明确禁止、也明确不接受以下修复——它们只是把错误的所有权原样保留新增或重命名侧表/名称列表给通用契约加元数据标志或可选参数在现有特判旁边再加一个特判用 helper 把分支包一层让泄漏只是间接化。最小修复永远指最小且符合架构的修复。若该修复超出当前 PR 的规模应明确说出来并将其作为必需方向限定范围的后续项、由作者决策呈现而不是降级为保留违规的补丁——因为作者一定会采纳那个补丁。同时这一节不授权臆测性抽象只标记具体知识侵入既有通用表面的情况不要在代码本就领域局部化的地方要求新层、新注册表或新扩展点。五、修复建议策略沿缺陷所在的高度动手最小修复 vs 彻底修复是错误的坐标轴正确的坐标轴是缺陷的高度altitude修复建议必须落在缺陷实际所在的层然后成为该高度上最小的完整修复。局部缺陷用最小局部修复——把它膨胀成重构本身就是范围蔓延结构性缺陷无法用更低高度的更小改动修复——低于缺陷高度的补丁不是更小的修复而是隐藏缺陷的不修复。问题类别缺陷高度最优建议结构健全下的局部正确性 bug逻辑错误、缺失守卫/清理、off-by-one、未 await 的 Promise行/函数最小局部修正不膨胀成重构或顺手改进结构性成因的症状型 bug两个写者拥有一份状态、刷新图在多处复制、丢失更新竞态属主结构指名根因并在那里修复——症状类别随之消失。症状补丁只能作为显式标注的临时手段与主建议并列结构性修复列为必需后续项实体泄漏 / 边界违规 / 强制文档不符模块结构最小符合架构的变更。此类不存在临时补丁层保留泄漏的补丁不会停止任何伤害只是把功能实现在了错误位置。修复过大时呈现方向 限定范围的后续项对上游限制的下游绕行上游共享表面指名上游模块与要扩展的方法/契约下游随之简化为普通调用。不接受绕行 TODO作为建议重复或新 helper 遮蔽既有公开能力正规属主收敛路由到既有属主或一次性提取到正确层。绝不允许第三份拷贝也不允许让两份拷贝对齐diff 引入的臆测性抽象 / 过度设计新增结构删除。修复是移除结构推荐一个建得更好的多余层同样是错的约定 / 命名 / 模块形态违规文件或标识符文档定义的机械修复重命名、移动、改大小写。文档定义了唯一目标所以这里最小即完整性能问题实测热点路径有针对性变更 语义等价证据。不做臆测性重写不用未测量的收益换清晰度设计意图不明—向作者提问而非修复。意图确认前推荐任何修复都是过早测试覆盖缺口 / 回归风险—指名缺失用例标记之不规定实现flag-only当作者或修复者回应对本 PR 来说太大了可接受的结果只有两个现在就做或落地已陈述的方向并附被跟踪的后续项任何临时手段显式标记为临时。悄悄把建议降级为补丁永远不是可接受结果——这正是泄漏与根因在评审中存活的方式。六、反碎片化三原则在提出任何修复之前使用这三条原则防止散落的局部补丁、一次性服务 API 和臆测性抽象扩散修上游不修下游消费者因共享模块/服务/钩子/组件的限制而加绕行时先问共享上游表面是否应该被修复。当同一限制可影响其他消费者、多个消费者复制同一守卫、或补丁掩盖了上游契约 bug 时标记下游补丁。但不要求为真正孤立的兼容 shim 重写上游——改为索要边界与过期条件。先泛化清晰的服务需求再特化需求是稳定的领域操作或可能被共享的能力时优先在属主服务/钩子/组件 API 上放清晰方法而非页面专用 helper 或端点。需求必须具体不为想象中的未来调用者泛化。一次性工作流的特化实现可以接受前提是保持局部且不重复公开能力。保持简单克制没有当前证据就不加层、注册表、状态机、适配器、配置系统或扩展点没有真实重复、所有权混乱或清晰的公共服务需求就不报缺失抽象。优先选择修复边界且保持系统可理解的最小修复。严重度归类碎片化造成运行/数据/安全风险或破坏公开契约时按Blocker一次性补丁或特化 helper 使所有权不清、且更小的上游/泛化修复显而易见时按Warningdiff 需要作者确认能力应否上提、泛化或有意识保持局部时按Notice。七、网络下载来源门禁开发、构建、安装或运行时经网络获取的每个组件都必须同时具备可用的全球源和可用的中国加速源——涵盖 npm 包、运行时与工具链二进制、离线模型及其他下载资产。规则要点注册表包支持的安装路径必须在全球默认 registry 和国内镜像下都能工作依赖声明无需重复 URL模型、二进制与 URL 寻址资产两个来源必须解析到相同版本与内容且当完整性校验可用时必须使用同一校验硬编码单一来源或第二个来源没有任何受支持的代码/配置路径能选中都不满足要求。任何缺少任一可用来源的新增或变更网络下载一律按Blocker处理在补齐双源之前不批准也不建议合并。这与仓库中 scripts/linux-native/、scripts/download-binaries.js 等下载基础设施的审查直接相关。八、参考路由按变更区域加载权威文档强制基线文档以下文档成熟且权威是评审标准而非可选背景每次代码或混合评审都必须加载并对照 diff 评审文档触发条件docs/references/architecture/naming-conventions.md始终docs/references/architecture/main-process.md及其路由到的子系统参考diff 触碰src/main/docs/references/architecture/renderer.mddiff 触碰src/renderer/docs/references/architecture/shared-layer.mddiff 触碰src/shared/docs/references/data/README.md按其路由进入子系统行diff 触碰任一数据面DB schema、DataApi、Cache、Preference、BootConfig 或对应渲染钩子严重度底线对这些文档的任何不符合定义上就是重要发现——最低按Warning上报破坏契约或造成运行/数据风险时按Blocker绝不降级为 Notice、风格偏好或与附近代码一致。附近代码共享违规只是迁移残留不构成先例。按需文档生命周期、IpcApi、窗口、任务与调度器行在其区域被触碰时具有同等权威。内部仓库文档路由表节选变更区域查阅文档DataApi 契约、schema、类型或错误data-api-overview.md、api-design-guidelines.md、api-types.mdDataApi handler、服务或渲染钩子主进程侧加 contenteditable="false">【免费下载链接】cherry-studio Cherry Studio 是一款支持多个 LLM 提供商的桌面客户端项目地址: https://gitcode.com/CherryHQ/cherry-studio创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考