关于 sliderule
SlideRule 是面向长期 .NET 代码库的架构检查器,将架构规则写成单一 C# 规范,并生成构建检查与编码 Agent 所需的上下文。
主要功能
- 01以 C# 规范定义架构规则
- 02在命令行、CI 和构建中检查
- 03生成 xUnit 测试与代码扫描结果
- 04输出 AGENTS.md 和目录规则卡
- 05提供 MCP 查询工具与提示词
适用场景
- 01为既有 .NET 代码库建立架构规则
- 02在 CI 中阻止违反边界的改动
- 03向编码 Agent 提供架构说明
MCP 相关
SlideRule 提供 MCP 工具 arch_check、arch_status、arch_explain、arch_context 和 arch_graph,以及 derive_spec 提示词,供编码 Agent 检查并查询架构规则。
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
我们还没有获取到这个服务的安装包或远程地址,请按项目 README 中的说明安装。
工具
本地服务需要在你的电脑上运行后才能读取工具,维护者暂未提供工具列表。
详细介绍
SlideRule
SlideRule 是一个 .NET 架构检查器,可强制执行一份 C# 规范,并将相同的规则呈现给编码 Agent。
长期维护的代码库有层级、边界和规则。这些内容只存在于少数人的头脑中,没有构建步骤会检查它们,图表也会逐渐过时。一次更改可能越过边界,而构建仍然成功。编码 Agent 可以快速且看似合理地完成这类更改,却无法看出哪些墙是结构性的。SlideRule 的解决方案是将架构作为代码。规则成为一份 C# 规范,而这份规范会生成本文提到的所有形式。
- 强制执行。 一个检查器会在命令行、CI、构建中以及作为命名的 xUnit 测试,判定规则通过或失败。Claude Code 钩子会在 Agent 的一轮操作结束时运行同一项检查。
- Agent 上下文。 规则会呈现为受管理的
AGENTS.md区块、按目录划分的规则卡,以及供编码 Agent 使用的 MCP 查询工具。
SlideRule 处于 pre-alpha 阶段。1.0 之前,小版本仍可能更改规范 API。状态介绍了目前已有的功能和版本规则。
安装工具、构建解决方案,然后进行检查:
dotnet tool install -g SlideRule.Cli
dotnet build MyApp.sln
sliderule check MyApp.sln
check 会从规范项目(即解决方案中的 C# 类库)读取规则。如果解决方案中还没有规范项目,check 会停止并报告未找到规范项目。入门指南介绍了如何使用 SlideRule 包创建规范项目;在还没有任何规则时,sliderule graph 可以调查解决方案。
一条规则就是一项声明:
arch.Rule("layering/domain-independent")
.Enforce(domain.MustNotReference(application, infrastructure, api))
.Because("The Domain holds the quote and rate model the rest of the subsystem is built on; it stays free of the layers that depend on it so it can be reasoned about and tested on its own.")
.Fix("Move the dependency out of Domain: define an interface here and implement it in the outer layer that needs it.");
这就是规则的全部内容。它包含 ID、执行方式、约束、原因和修复方法。这里的执行方式是 Enforce,而 domain 及其不得引用的三个层级,已在规范前文通过命名空间模式声明。该规则已提交在整洁架构示例中,CI 会确保 check 对其管理的代码库保持通过。规则还可以引用其原因所依据的页面,并指定一个可供复制的类型,详见编写规范。
Agent 违反规则时
上面的规则也管理着这个代码库。其中一条规则要求 CLI 不向 stdout 输出内容,因为 MCP 服务会通过该通道传输 JSON-RPC。假设某个 Agent 为 CLI 添加进度输出,并使用 Console.WriteLine。当它尝试结束这一轮操作时,hooks/ 中的 Claude Code Stop 钩子会对工作树运行 check。规则检查失败,钩子会阻止停止操作,并将以下报告输出到 Agent 的 stderr:
FAIL cli/no-stdout — The Host layer must not use `Console.Out`, `Console.Write()` or `Console.WriteLine()`.
because: Stdout is a protocol channel here — the MCP server speaks JSON-RPC over it and CLI output flows through System.CommandLine's console — so a direct Console write corrupts the wire and is invisible to the in-process tests.
citation: https://modelcontextprotocol.io/specification/2025-06-18/basic/transports#stdio
fix: Write CLI output through the command's InvocationConfiguration console; route server diagnostics to the logger or Console.Error.
subject: 196 types, 1 generated
src/SlideRule.Cli/Rendering/ProgressPrinter.cs:10 — SlideRule.Cli.Rendering.ProgressPrinter uses System.Console.WriteLine()
src/SlideRule.Cli/Rendering/ProgressPrinter.cs:15 — SlideRule.Cli.Rendering.ProgressPrinter uses System.Console.WriteLine()
报告列出了规则、原因、引用、修复方法以及每一处违规代码行。只有当规则的检查对象包含生成代码时,才会出现 subject: 行;这里检查对象是其 195 个类型中的 1 个。Agent 改为通过命令的控制台输出内容,下一次停止操作便能顺利通过。
SlideRule 自检页面还展示了本仓库自身的规范如何应用于其他形式,包括它生成的文本、代码扫描和图表。该页面还说明了如何确保这两个页面中的每段摘录都与其来源一致。
四种姿态
每条规则都属于前两种之一,每个作用域都属于后两种之一。
| 姿态 | 含义 | 失败条件 |
|---|---|---|
Enforce | 法规 | 任何违规都会失败,包括规则生效前就存在的违规 |
Migrate | 针对计数基线的棘轮机制 | 新增违规;已纳入基线的位置不会报错 |
Quarantine | 对作用域进行隔离 | 新增对该作用域的引用 |
Caution | 供新调用方使用的代码中的注意事项 | 永不失败;触及该代码的变更会发出警告 |
Migrate 适用于代码尚未遵守的规则。sliderule baseline init 会记录该规则当前的违规情况,此后任何新增违规都会导致失败。随着违规位置逐步修复,sliderule baseline accept-reductions 会缩减基线;基线清空后,status 会建议将规则提升为 Enforce。
作用域用于标记需要谨慎处理的代码。其中的注意事项会说明代码为何脆弱,以及如何调用它。render 会在作用域所在目录中生成一张说明卡片。Quarantine 还会将指向该作用域的引用记录在基线中,并禁止任何新的引用,只有通过 BoundaryOnlyVia 指定的接口才例外。使用 check --diff-base <ref> 时,两种作用域在被变更触及时都会发出警告。编写规范页面通过代码展示了每种姿态,而运行 SlideRule则介绍了从记录到提升的棘轮流程。
Enforce 之后的三种姿态,分别应对编码 Agent 在既有代码库中可能犯下的错误。Enforce 是代码已经遵守的法规,变更一旦违反法规,无论在哪运行检查都会失败。Meridian 示例通过真实输出展示了其中三种错误。
- Agent 照搬多数人的做法,也就是统计学上的先验模式。Meridian 的八个控制器中有六个会打开
SqlConnection,因此内联 SQL 看起来就像项目的惯例,Agent 也会用同样的方式编写下一个控制器。Migrate可应对此情况。渲染出的上下文会将这种模式称为技术债,并在 Agent 编写代码前向其展示。 - Agent 出于好意重构,移除了网关。模块中的公共类型会引诱人直接调用,绕过它前面的网关。
Quarantine作用域会让网关成为唯一获准的入口。 - Agent 纠正结构上的怪异之处。一张跳过某些数值的校验位表看起来像是有错误,但将其改成连续数值会导致所有真实容器编号都出错。
Quarantine或Caution作用域中的注意事项可以应对此情况。该作用域目录中的说明卡片会解释代码的用途、哪些部分是结构性设计,以及如何调用它。
一份规范能生成什么
下面每个目标都会读取同一个模型。每份违规报告都会给出规则 ID、生成的规则说明、原因和精确的 file:line。如果规则有修复方法、引用和示例,也会一并显示。
| 目标 | 说明 |
|---|---|
sliderule check | 为命令行和 CI 提供一个通过或失败的判定 |
check --sarif | 以 SARIF 2.1.0 格式呈现该判定,用于代码扫描 |
| xUnit 适配器 | 将每条规则作为一个单独命名的测试 |
| 构建分析器 | 将违反规则的位置显示为编辑器中的波浪线,并在构建时显示为编译器警告 |
sliderule render | 受管理的 AGENTS.md 区块、每个目录的规则卡片,以及作为 JSON 文件的模型 |
render --diagram | 两张 Mermaid 图:项目及其引用关系,以及规范的法则 |
sliderule mcp | arch_check、arch_status、arch_explain、arch_context 和 arch_graph,以及一个 derive_spec 提示词 |
sliderule hook | Claude Code Agent 的回合结束时运行 check;若规则检查失败,则会阻止停止 |
适配器的失败文本与 CLI 的逐字节相同。两者共用一个渲染器,并通过产品测试确保输出一致。受管理的区块和 sliderule explain 也是生成的架构文档,优先面向 Agent 编写,同时方便人类阅读。SlideRule 自检 页面展示了确保其保持最新的门禁。
编码 Agent 页面说明哪些 Agent 会读取 AGENTS.md 文件并使用各个接口。页面还介绍了对于拥有自己 CLAUDE.md 的仓库,需要为 Claude Code 补充哪些内容。
与 ArchUnitNET 和 NetArchTest 的比较
NetArchTest 和 ArchUnitNET 会在单元测试中运行架构规则,而且很擅长这件事。SlideRule 将规则从测试代码中移出,集中到一份规范中,并据此生成上述所有形式的输出。
| 工具 | 需要编写的内容 | 运行位置 |
|---|---|---|
| NetArchTest | 测试方法中的流式断言 | 你的测试运行器 |
| ArchUnitNET | 测试类中的 ArchUnit 风格规则 | 你的测试运行器 |
| SlideRule | 独立项目中的一份规范 | 上述每个目标 |
其语法借鉴了对这些先例的考察,而 GRAMMAR.md 记录了每一处差异。约束通过动词表达否定(MustNotReference),沿用 ArchUnitNET 的做法。ArchUnit 的 FreezingArchRule 接受规则当前的违规项作为基线;在这里,对应的是带计数基线的 Migrate。Quarantine 将相同的棘轮机制应用于一段代码,统计当前指向该区域的引用,并阻止任何绕过其获准入口的新引用。
Because 是必填项。缺少它的规则会导致规范无效,而 check 会在评估任何内容之前停止,并一次性报告所有规范错误。即使是谓词逃逸口 Must(condition, description:),没有描述也无法编译。每条理由都会随渲染后的上下文提供给你的 Agent。在 Interchange 示例中,12 条规则各自都有一个 Citation,指向其理由所依据的 learn.microsoft.com 页面。其中 12 条规则有 9 条来自共享规则包,这是一个普通的静态方法类库。规则包负责引用,规范则选择约束方式。该规则包是此存储库中的一个完整示例,并非已发布的包。你可以在自己的存储库中将自有规则包建成类库,无需依赖任何注册表。
从已有代码库开始
SlideRule 专为长期维护的关键业务 .NET 代码库打造。这类代码库的架构确实存在,却往往只存在于少数人的头脑中。你可以自行编写第一批规则,也可以像 入门指南中所示,通过 derive_spec 提示词让 Agent 起草规则。你需要审阅 Agent 提出的每条规则,并在提交任何内容之前决定接受、修改或舍弃。
它能处理的情况
真实解决方案很少只有一种形式。每一行对应一种情况,以及检查器对此的处理方式。变更日志记录了各项功能加入的版本。
| 情况 | 检查器的处理方式 |
|---|---|
| 链接的源文件 | 每个参与编译的项目只读取一次共享文件的引用 |
| 多目标项目 | 同一个项目,使用一个框架的成员和层级进行读取,并读取每个框架的引用 |
| 多个项目中存在同一个类型名称,或包中也存在该名称 | 遵循编译器对每个引用的绑定 |
| 生成的代码 | 按项目和规则主体分别计数 |
| 多语言解决方案 | 列出它无法读取的每个 F#、VB 或 SQL 项目 |
| 使用集中式包管理的代码库 | derive_spec 脚手架可在 Directory.Packages.props 下构建 |
| 非 SDK 风格的 .NET Framework 项目 | 通过 Framework 构建主机加载;参见 .NET Framework |
| 来自真实构建的 binlog | check --binlog 可重放它;参见 .NET Framework |
| 解决方案筛选器 | 列出筛选运行中从未检查的项目;参见命令行参考 |
| 再次检查同一解决方案 | 重用持久化缓存,只重新提取已更改的项目;声明发生变化时,也会重新提取其依赖项目 |
| 仅修改方法体 | 只重新提取已修改的项目 |
检查器无法读取其所用语言的项目会使模型变小。检查结果、状态和图表文档会列出该项目及原因,运行仍会给出答案。调查命令 sliderule graph 会指出多目标项目的共享类型所遵循的框架。它还会列出两个项目之间,或项目与包之间同时声明的所有类型名称。规则主体上的 .Authored() 会使规则避开生成的代码。
编辑后,检查只会加载重新提取的项目及其引用的项目。当 Agent 的回合结束时,hook 运行的就是这项检查,其输出与冷运行打印的内容逐字节相同。命令行参考列出了这类检查会改为加载整个解决方案的情况。
.NET Framework
该工具运行于 .NET 10。它检查的代码库不必运行于 .NET 10,约束它的规范也不必如此。
规范项目可以面向 net48,并以该框架默认的语言级别 C# 7.3 编译。它引用与其他规范相同的 netstandard2.0 SlideRule 包,而 CLI 会在隔离的加载上下文中加载生成的 DLL。只要产品类型及其所有依赖项都保持在 netstandard2.0 范围内,typeof() 引用就可正常工作。超出此范围的内容,例如没有 .NET 对应类型的 .NET Framework 类型,则通过命名空间模式指定。像 DerivedFrom 这样的筛选器也会将类型的完整名称作为字符串接收。这两种情况都不需要加载程序集。
旧式项目文件也能加载。非 SDK 风格的 Framework 项目,是指使用 2003 MSBuild XML 命名空间、包含显式 <Reference> 项,并由人工维护 AssemblyInfo.cs 的项目。它通过 Roslyn 随附的 .NET Framework 构建主机加载,并像其他项目一样报告 file:line:
FAIL data-access/no-inline-sql — Types in `Classic.*` must not reference types in `System.Data.*`.
Classic.Billing/BillingCalculator.cs:10 — Classic.Billing.BillingCalculator references System.Data.SqlClient.SqlConnection
check --binlog 会重放同一台计算机上对该解决方案进行真实构建时生成的二进制日志,以取代它自己的设计时构建。该日志可以由 .NET Framework MSBuild.exe 生成。重放日志与直接打开工作区会产生逐字节一致的输出。
加载非 SDK 风格的项目,以及重放由 .NET Framework MSBuild.exe 生成的日志,都需要 Windows,因为 Framework 构建主机和 MSBuild.exe 都来自 Windows。命令行参考说明了该工具会使用哪个 Visual Studio 或 Build Tools 安装,以及如何选择安装。net48 规范项目没有此要求,可以在任何地方构建。
示例
examples/ 中的六个完整示例围绕一家虚构的货运代理公司展开。其中四个是解决方案。CI 会构建每个解决方案,确保 check 对已提交的代码树检查通过,并运行 render --check,以验证 render 在 examples/ 下生成的所有文件都是最新的:
-
仅强制执行的整洁架构:从零构建的报价子系统。九条规则约束四层整洁架构,每条规则都会作为一个具名 xUnit 测试运行。
-
在同一代码库中展示四种模式中的三种:正在迁移的单体应用。它包含法则、三种棘轮及其消减情况,以及一个隔离范围。
-
将模块隔离作为法则:模块化单体应用。每个模块目录都有自己的渲染规则卡片,其中一个模块被隔离在其外观之后。
-
强制执行并引用 Microsoft 指南:操作手册页面。它逐条展示规范语句、规范摘录和真实违规示例。
另外两个示例以捕获的输出,展示 Meridian 单体应用中的一段流程:
-
在现有代码库中于第一天开始采用:完整的推导流程,每一步都是带有真实输出的实际命令。
-
由钩子闭合的 Agent 循环:逐个节拍演示上述循环的分镜。还包含可直接粘贴的钩子配置。
安装
CLI 是一个 .NET 全局工具,运行它的机器需要 .NET 10 SDK。入门指南中的要求涵盖了其余内容,包括在 global.json 指定了低于 10 的 SDK 的仓库中安装。
命令行参考介绍了每条命令的选项和退出代码,以及项目加载失败或解决方案筛选器缩小范围时运行会如何处理。
命令是 sliderule。一个发行版由四个版本保持同步的包组成,规范项目引用的 SlideRule 版本与 sliderule --version 输出的版本一致:
| 包 | 内容 |
|---|---|
SlideRule.Cli | sliderule 全局工具:check、render、explain、status、graph、baseline、hook,以及 MCP 服务(sliderule mcp)。 |
SlideRule | 规范契约,零依赖。它包含一个分析器,可在编写规范时将其中错误的字符串字面量报告为编译器警告,并提供命名空间和类型名称补全。 |
SlideRule.Xunit | xUnit 适配器:将每条规则作为一个单独命名的测试。 |
SlideRule.Analyzers | 构建分析器:规则出错时,会在编辑器中显示波浪线,并在 dotnet build 中发出编译器警告;分析器读取的是 render --model 写入的模型文件。 |
运行 SlideRule介绍了随着新版本发布,如何让工具和包保持同一版本。
连接 MCP 客户端
MCP 客户端通过 mcp 命令启动同一工具;服务使用 stdio 通信。.mcp.json 格式如下:
{
"mcpServers": {
"sliderule": {
"command": "sliderule",
"args": ["mcp", "MyApp.sln"]
}
}
}
由 MCP 注册表生成的配置不会传入解决方案。随后,服务会像每条命令一样查找解决方案:从已提交的 sliderule.json 中查找,或从其工作目录向上遍历查找。如果无法找到,可在安装时绑定一个解决方案。编码 Agent页面介绍了绑定、工具和 derive_spec 提示词。
文档
-
入门指南:从没有规范到检查通过的首次运行。
-
编写规范:规则的组成部分、姿态和范围,以及规则涵盖的内容。
-
编码 Agent:上下文文件、MCP 服务和钩子。
-
运行 SlideRule:CI、棘轮机制、构建分析器、升级和失败的运行。
-
命令行参考:每条命令、选项、退出代码和文档。
-
GRAMMAR.md:语言参考。
-
SlideRule 自检:此仓库自身的规范,在其自身代码上进行检查和渲染。
状态
SlideRule 0.1.0 是首个版本。本页列出的所有功能目前均已提供,四种姿态都可以进行评估。SlideRule 对自身的检查展示了这些功能如何在本仓库自己的代码上运行,CI 还会将该 check --sarif 运行结果上传到代码扫描中。构建分析器是个例外,它已在四个示例解决方案上得到验证。流畅式接口仍可能发生变化;GRAMMAR.md 是它的规范,其词汇表由已发布的 API 生成。
这些包在 0.x 语义化版本下同步发布。规范 API 的每项变更都会列在变更日志的 Breaking 一节中,且发布时不会附带兼容垫片;补丁版本则不会包含此类变更。JSON 文档包含 schemaVersion,其结构发生变化时版本号也会更新;人类可读报告则可能在任何版本中增加行。测试会锁定 SlideRule 和 SlideRule.Xunit 的公共接口,即使用者编译时依赖的两个包。该接口包括规范语言和适配器的测试基类,其背后的引擎则是内部实现。打包时还会将此接口与上一版本进行比较,因此变更不会意外混入。
构建
dotnet build SlideRule.slnx
dotnet test SlideRule.slnx
CONTRIBUTING.md 介绍了参与 SlideRule 项目开发的其他相关内容。
许可证
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。