首页
/ PowerToys AI 贡献者指南:构建纪律、测试规范与工程边界的完整实践

PowerToys AI 贡献者指南:构建纪律、测试规范与工程边界的完整实践

2026-09-03 15:49:36作者:卓炯娓

本文以 PowerToys 仓库根目录的 AGENTS.md 为主体,系统讲解面向 AI 贡献者(以及人类开发者)的顶层工程规范:仓库区域划分、构建脚本与构建纪律、测试发现与运行规则、跨模块边界约束和提交前验证清单。读完后,你可以独立完成 PowerToys 从首次构建、失败排错到测试验证的全流程,并理解 Runner 与 Settings UI 之间 IPC 契约、src/common/ 共享库 ABI 稳定性等高风险区域的保护机制。

仓库区域总览:七大区域的职责划分

PowerToys 是面向 Windows 高级用户的生产力工具集合。AGENTS.md 开篇即用一张表划定了仓库的七个核心区域,这是理解后续所有构建、测试和边界规则的地基:

区域 位置 职责
Runner src/runner/ 主可执行文件、托盘图标、模块加载器、热键管理
Settings UI src/settings-ui/ WinUI/WPF 配置应用,通过命名管道与 Runner 通信
Modules src/modules/ 各个独立的 PowerToys 工具(每个工具一个子目录)
Common Libraries src/common/ 共享代码:日志、IPC、设置、DPI、遥测、通用工具
Build Tools tools/build/ 构建脚本与自动化
Documentation doc/devdocs/ 开发者文档
Installer installer/ 基于 WiX 的安装程序项目

从源码结构看,这个划分与实现一一对应:src/runner/main.cpp 中维护着模块 DLL 的加载列表,src/runner/powertoy_module.h 封装了模块生命周期;src/settings-ui/ 下包含 Settings.UI、Settings.UI.Library、QuickAccess.UI 等多个 WinUI/WPF 项目。更深入的架构描述(四类模块:Simple Modules、外部应用启动器、上下文菜单模块、注册表模块)可见 架构总览;每个模块必须实现的 DLL 接口定义在 powertoy_module_interface.h,其方法契约与运行时调用逻辑(powertoy_create()get_name()enable()set_config()destroy())在 模块接口文档中有完整说明——这正是 Runner 能够统一管理约二十个模块接口 DLL 的基础。

Runner 与 Settings UI 之间的通信细节(JSON over Named Pipes、设置 schema 迁移、IPC 兼容性)在 Settings 系统文档中展开,这是 AGENTS.md 边界章节重点保护的区域。

编码约定与组件级自动生效指令

AGENTS.md 将编码约定收敛为三份必读文档,并额外引入了按目录作用域自动应用的组件级指令文件:

  • 编码指南——依赖管理、测试要求、PR 管理流程
  • 编码风格——格式化工具(XAML 用 XamlStyler、C++ 用 .clang-format)、C++/C#/XAML 风格规则
  • 日志规范——C++ 侧 spdlog 与 C# 侧 Logger 的用法

组件级指令文件(instruction files)会在 AI 工具处理对应目录的文件时自动生效,其作用域声明在各文件头部的 frontmatter 中:

  • Runner & Settings UI 指令,作用域 src/runner/**, src/settings-ui/**——核心规则包括:IPC/JSON 契约变更必须同步镜像到两侧代码;保持 src/runner/main.cpp 中的模块发现列表与新增/移除模块同步;设置 schema 变更必须附带迁移逻辑;UI 绑定操作需回 UI 线程
  • Common Libraries 指令,作用域 src/common/**——核心规则包括:避免破坏公共头文件/API,修改公共接口必须全库搜索调用方;ABI 影响的 struct/class 布局变更需保持二进制兼容;热路径(hooks、定时器、序列化)警惕性能回退;新增第三方依赖须 MIT 许可或经 PM 团队批准,并登记到 NOTICE.md

这种"全局指南 + 目录作用域指令"的分层设计,使得约束在离代码最近的位置生效,是 AGENTS.md 整体工程哲学的体现:规则要具体、要可自动执行。

构建:前置条件与构建命令

前置条件

在开始构建前,AGENTS.md 明确了三个硬性前提:

  • Visual Studio 2022 17.4 及以上版本,或 Visual Studio 2026
  • Windows 10 1803(2018 年 4 月更新)或更新的系统
  • 只需执行一次子模块初始化:
git submodule update --init --recursive

子模块初始化是必要的:C++ 侧日志库 spdlog 以 git submodule 形式置于 deps/ 目录,各 vcxproj 通过 spdlog.props 引入其头文件与库链接;src/common/ 下的共享工具(如 json.htwo_way_pipe_message_ipc.h)也依赖子模块内的第三方代码。

构建命令

AGENTS.md 给出的三条核心命令对应三种典型场景:

任务 命令
首次构建 / NuGet 恢复 tools\build\build-essentials.cmd
构建当前文件夹 tools\build\build.cmd
带选项构建 build.ps1 -Platform x64 -Configuration Release

构建脚本指南 对这三个入口有更细的语义,值得在实操前理解:

  • build-essentials.ps1:对 PowerToys.slnx 执行 NuGet 恢复,并构建"必需品"(runner 与 settings)。自动检测平台(x64/arm64)并初始化 VS 开发者环境。示例:./tools/build/build-essentials.ps1 -Platform arm64 -Configuration Release
  • build.ps1:构建当前目录下的任意 .sln/.csproj/.vcxproj,接受额外 MSBuild 参数转发(如 ./tools/build/build.ps1 '/p:CIBuild=true'),也支持仅恢复依赖的 -RestoreOnly 开关
  • build-installer.ps1(需谨慎使用):完整本地打包管线(restore、build、MSIX 签名、WiX v5 MSI/bootstrapper),关键选项 -PerUser true|false-InstallerSuffix wix5|vnext

两个 CMD 包装器 build.cmdbuild-essentials.cmd 会将全部参数原样转发给对应的 PowerShell 脚本。脚本初始化 VS 环境的策略是:优先走 DevShell(Microsoft.VisualStudio.DevShell.dll / Enter-VsDevShell),失败后回退到 VsDevCmd.bat;若找不到 VS 安装,应从 "Developer PowerShell for VS 2022" 中运行,或确保 vswhere.exe 存在于 Program Files (x86)\Microsoft Visual Studio\Installer 下。

构建纪律:七条不可协商的规则

AGENTS.md 的 "Build discipline" 一节是全文最值得逐条遵守的部分,它定义了构建操作的纪律性流程:

  1. 一次操作一个终端(build → test 依次进行),中途不得切换或新开终端
  2. 修改代码后,先 cd 到发生变化的项目目录(即包含改动文件对应 .csproj/.vcxproj 的目录)
  3. 一律通过 tools/build/build.ps1tools/build/build.cmd 构建,不要直接调 msbuild
  4. 首次构建或缺少 NuGet 包时,必须先跑 build-essentials.cmd
  5. 退出码 0 = 成功;非零 = 失败——这条要当成绝对事实对待
  6. 构建失败时,阅读错误日志 build.<config>.<platform>.errors.log
  7. 构建未成功之前,不要开始跑测试,也不要启动 Runner

构建日志的排错顺序

日志位于被构建的 solution/project 旁侧,AGENTS.md 与构建脚本指南共同定义了排错时的查阅顺序:

  • build.<configuration>.<platform>.errors.log —— 仅错误(先看这个
  • build.<configuration>.<platform>.all.log —— 完整日志
  • build.<configuration>.<platform>.trace.binlog —— 用 MSBuild Structured Log Viewer 打开

BUILD-GUIDELINES.md 看,实际上还存在一个仅告警日志 build.<configuration>.<platform>.warnings.log,当 errors 为空但构建行为可疑时值得检查。

测试:发现、运行与三类测试

测试项目的发现方式

AGENTS.md 给出了一种不依赖记忆清单的测试项目定位法:

  • 按产品代码前缀查找测试项目(例如 FancyZonesAdvancedPaste
  • 在源码目录的同级或上 1–2 级目录中,查找命名为 <Product>*UnitTests<Product>*UITests 的文件夹

从仓库实际结构可以印证这一命名惯例,例如 src/modules/MouseUtils/ 下同时存在 MouseJump.Common.UnitTestsMouseJump.HotKeys.UnitTestsMouseJump.Models.UnitTestsMouseUtils.UITests 等项目;src/settings-ui/ 下则设有 Settings.UI.UnitTests

运行测试的三条规则

  1. 先构建测试项目,等到退出码为 0
  2. 通过 Visual Studio Test Explorer(Ctrl+E, T)或 vstest.console.exe 加过滤器运行
  3. 本仓库中避免使用 dotnet test——应使用 VS Test Explorer 或 vstest.console.exe

第 3 条是一个容易踩坑的仓库特定约束:PowerToys 的 C++/C# 混合工程依赖 VS 工具链生成的环境(含 WinAppSDK、WinRT 投影等),dotnet test 无法正确还原该环境。

三类测试及其环境要求

类型 要求 环境准备
单元测试 标准开发环境 无需额外准备
UI 测试 WinAppDriver v1.2.1、Windows Developer Mode 安装对应版本的 WinAppDriver 并启用开发者模式
Fuzz 测试 OneFuzz、.NET 10 Fuzzing Tests 文档

关于 UI 测试,UI Tests 文档 补充了一个 AGENTS.md 未展开的重要现状:新测试应使用 Microsoft.PowerToys.UITest.Next 框架,它通过 winappcli 驱动 Windows UI Automation,并以 Microsoft.Testing.Platform 可执行文件的形式运行;而基于 WinAppDriver/Selenium 的旧版 Microsoft.PowerToys.UITest 框架保留用于既有套件与迁移基线。这意味着 AGENTS.md 中"安装 WinAppDriver v1.2.1"的要求主要适用于存量旧版 UI 测试;新增或迁移测试时还需要安装锁定版本的 winappcli 运行时(或设置 WINAPP_CLI_PATH),且 UI 测试必须运行在真实的交互式桌面上(session 0 中 UIA、前台输入与渲染均不可用)。

测试纪律与特殊硬件要求

AGENTS.md 对"改代码"与"写测试"的绑定关系提出了明确纪律:

  1. 变更行为时,添加或调整相应测试
  2. 若测试被跳过,必须说明理由(例如仅注释变更、仅字符串改名)
  3. 处理文件 I/O 或用户输入的新模块必须实现 fuzzing 测试——这一要求与 编码指南 中"安全团队要求处理文件 I/O 或用户输入的模块做 fuzzing"的表述一致,且 C# 与 C++ 模块的 fuzzing 实现方式不同(集成 Microsoft OneFuzz 服务)

两类模块还有额外的硬件前提:

  • Mouse Without Borders:需要 2 台以上物理计算机(虚拟机不可行,因为宿主机与来宾机的鼠标输入会互相混淆)
  • 多显示器工具:至少 2 个显示器,且其中一个应支持不同的 DPI 设置

边界:何时必须澄清、哪些区域重点保护

AGENTS.md 的 "Boundaries" 章节定义了贡献过程中的风险分级,这部分对保证跨模块变更质量尤为关键。

需要先澄清再继续的场景

  • 扫描了相关文档后规格仍然含糊
  • 跨模块影响(共享 enum/struct)不明确
  • 涉及安全、提权或安装程序的变更
  • 需要修改 GPO 或策略处理逻辑

重点保护区域

区域 风险点 参考
src/common/ ABI 破坏 Common Libraries 指令
src/runner/src/settings-ui/ IPC 契约、settings schema Runner & Settings UI 指令
安装程序文件(installer/ 影响发布 需要仔细评审
提权/GPO 逻辑 安全 确认策略处理无回归

四条红线(What not to do)

  • 不要将未完成的特性合入 main(使用 feature 分支)
  • 不要在不更新 runner 和 settings-ui 两侧的情况下破坏 IPC/JSON 契约
  • 不要在热路径中加高噪声日志
  • 不要在未获 PM 批准、且未更新 NOTICE.md 的情况下引入第三方依赖

其中 IPC 契约规则在 runner-settings-ui.instructions.md 中被进一步细化为四条可操作动作:同一 PR 内更新两侧、尽量保持向后兼容、为 schema 变更添加迁移逻辑、双向通信都要测试。

提交前验证清单

AGENTS.md 的 Validation Checklist 是收尾阶段的硬性门禁,交付前逐项核对:

  • [ ] 构建干净且退出码为 0
  • [ ] 测试已更新并在本地通过
  • [ ] 无计划外的 ABI 破坏或 schema 变更
  • [ ] Runner 与 settings-ui 之间的 IPC 契约一致
  • [ ] 新依赖已登记到 NOTICE.md
  • [ ] PR 是原子的(一个逻辑变更),并关联了对应 issue

结合 编码指南 的 PR 流程看,这条清单之后还有仓库层面的审批要求:PR 需 code owners 批准;涉及安装程序文件(installer/ 下的 WiX 工程,如 PowerToys.wxs、Common.wxi)的 PR 会被重点评审,因为安装程序直接决定发布产物。

文档索引:AGENTS.md 的延伸地图

AGENTS.md 末尾的 Documentation Index 是进入 PowerToys 开发文档体系的入口,按主题分为三组:

核心架构

  • 架构总览——模块接口总览、四类模块、公共资源管理
  • Runner——PowerToys.exe 的启动流程(初始化日志 → 单实例互斥 → 托盘图标 → 低级键盘钩子 → 加载模块 DLL → 消息循环)
  • Settings 系统——Settings v2 的实现、与 Runner 的 IPC、GPO 集成
  • 模块接口——PowertoyModuleIface 各方法的契约定义

开发

构建与工具

两份按目录作用域自动生效的指令文件(Runner & Settings UICommon Libraries)则构成了约束体系中最贴近代码的一层。

小结

AGENTS.md 的价值不在于介绍 PowerToys 有哪些工具,而在于把"如何在这个仓库里安全地改代码"压缩成了一套可执行的规则:用 tools/build/ 脚本构建并以退出码裁决成败、用产品前缀规律定位测试项目且规避 dotnet test、把 src/common/ 的 ABI 与 runner/settings-ui 的 IPC 契约视为最高风险区、以 NOTICE.md 登记和原子 PR 收尾。对 AI 贡献者而言,这份文档与目录作用域指令文件共同构成了一个"规则即上下文"的体系——在动手之前读懂它,能显著降低跨模块变更引入回归的概率。

登录后查看全文
热门项目推荐
相关项目推荐