Skip to content

Commit f20d7b7

Browse files
feat: add architecture analyzer guardrails
Move architecture boundary enforcement into a compile-time analyzer and keep host/provider composition declarative. Co-authored-by: Cursor <cursoragent@cursor.com>
1 parent 5e4bc62 commit f20d7b7

46 files changed

Lines changed: 614 additions & 802 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎ChengYuan.slnx‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@
7272
<Project Path="src/Hosts/CliHost/ChengYuan.CliHost.csproj" />
7373
</Folder>
7474
<Folder Name="/src/Analyzers/">
75-
<Project Path="src/Analyzers/ChengYuan.Architecture/ChengYuan.Architecture.csproj" />
75+
<Project Path="src/Analyzers/ChengYuan.ArchitectureAnalyzer/ChengYuan.ArchitectureAnalyzer.csproj" />
7676
</Folder>
7777
<Folder Name="/tests/">
7878
<Project Path="tests/ChengYuan.FrameworkKernel.Tests/ChengYuan.FrameworkKernel.Tests.csproj" />

‎Directory.Build.targets‎

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,14 @@
1818
<PackageReference Include="Microsoft.CodeAnalysis.PublicApiAnalyzers" PrivateAssets="all" />
1919
</ItemGroup>
2020

21+
<!-- Compile-time architecture guardrails for source projects. -->
22+
<ItemGroup Condition="'$(MSBuildProjectName)' != 'ChengYuan.ArchitectureAnalyzer' AND '$(MSBuildProjectName)' != '_build'">
23+
<ProjectReference Include="$(MSBuildThisFileDirectory)src/Analyzers/ChengYuan.ArchitectureAnalyzer/ChengYuan.ArchitectureAnalyzer.csproj"
24+
OutputItemType="Analyzer"
25+
ReferenceOutputAssembly="false"
26+
PrivateAssets="all" />
27+
</ItemGroup>
28+
2129
<!-- Populate NuGet package metadata from GitHub environment variables -->
2230
<PropertyGroup Condition="'$(GITHUB_REPOSITORY)' != '' AND '$(RepositoryUrl)' == ''">
2331
<RepositoryUrl>https://github.com/$(GITHUB_REPOSITORY)</RepositoryUrl>

‎Directory.Packages.props‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@
4545
<PackageVersion Include="OpenTelemetry.Exporter.OpenTelemetryProtocol" Version="1.15.3" />
4646
<PackageVersion Include="OpenTelemetry.Instrumentation.AspNetCore" Version="1.15.1" />
4747
<!-- Analyzers -->
48+
<PackageVersion Include="Microsoft.CodeAnalysis.Analyzers" Version="5.3.0" />
49+
<PackageVersion Include="Microsoft.CodeAnalysis.CSharp" Version="5.0.0" />
4850
<PackageVersion Include="Microsoft.CodeAnalysis.PublicApiAnalyzers" Version="5.0.0-1.25277.114" />
4951
<!-- Testing -->
5052
<PackageVersion Include="Shouldly" Version="4.3.0" />

‎docs/contributing/development.md‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@ If the current source tree and the architecture guide differ, prefer the guide a
1414
- `Framework` modules may depend only on other `Framework` modules.
1515
- `Application` modules may depend on `Framework` modules and on other `Application` modules through `Contracts` only.
1616
- Hosts compose modules; hosts do not implement business use cases.
17-
- Mirror source families in tests. Keep module tests under `tests/ChengYuan.FrameworkKernel.Tests/<Family>/<Module>/...` and architecture suites under `tests/ChengYuan.ArchitectureTests/<Suite>/...`.
18-
- Add architecture tests when you introduce a new module or a new facet profile.
17+
- Mirror source families in tests. Keep module tests under `tests/ChengYuan.FrameworkKernel.Tests/<Family>/<Module>/...`.
18+
- Update `ChengYuan.ArchitectureAnalyzer` when you introduce a new module family, facet profile, or compile-time architecture boundary.
1919

2020
## Prerequisites
2121

@@ -43,7 +43,7 @@ The default target is **Build** (Restore → Build).
4343
2. Pick the module profile or facet set.
4444
3. Add only the projects the module actually needs.
4545
4. Declare direct dependencies explicitly.
46-
5. Add or update architecture tests.
46+
5. Update `ChengYuan.ArchitectureAnalyzer` when the change introduces a new architecture boundary.
4747
6. Wire the module into Web or CLI only if a transport facet is required.
4848

4949
## NUKE Build Targets

‎docs/guide/architecture.md‎

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ When existing code and this guide differ, use this guide as the default rule for
1111
- Split reusable slices so technical systems stay separate from reusable application capabilities and optional extensions.
1212
- Allow uneven module depth. Do not force every module to expose the same layers or transports.
1313
- Keep Web and CLI as optional transport facets.
14-
- Require explicit dependencies and architecture tests.
14+
- Require explicit dependencies and compile-time architecture guardrails through `ChengYuan.ArchitectureAnalyzer`.
1515
- Preserve strong engineering guardrails: build automation, locked restore, versioning, tests, and documentation.
1616

1717
## Top-Level Structure
@@ -52,7 +52,7 @@ src/
5252

5353
The preferred path shape is `family root -> short module folder -> project`. Use `src/Applications/Identity/ChengYuan.Identity.Application/`, not `src/Applications/ChengYuan.Identity/ChengYuan.Identity.Application/`, and do not add role-only intermediate folders such as `src/Applications/Identity/Application/`.
5454

55-
Apply the same mirroring rule to tests. Keep module tests under paths such as `tests/ChengYuan.FrameworkKernel.Tests/Applications/Identity/` and architecture suites under paths such as `tests/ChengYuan.ArchitectureTests/Structure/`.
55+
Apply the same mirroring rule to tests. Keep module tests under paths such as `tests/ChengYuan.FrameworkKernel.Tests/Applications/Identity/`; architecture boundaries are enforced at compile time by `ChengYuan.ArchitectureAnalyzer`.
5656

5757
Family words such as `Framework`, `Applications`, and `Hosts` belong in directories, not in project names. Facet words such as `Application`, `Persistence`, and `Web` stay in project names when they describe the project role.
5858

@@ -232,7 +232,7 @@ The rule is simple:
232232

233233
1. Wave A: create the `ChengYuan.Core` family and move modularity ownership out of `ChengYuan.Hosting`.
234234
2. Wave B: establish the core failure model and DDD baseline with exceptions, error codes, `Result`, entities, aggregate roots, value objects, strongly typed IDs, `IClock`, and `IGuidGenerator`.
235-
3. Wave C: add `ChengYuan.Core.Json`, `ChengYuan.Core.Validation`, `ChengYuan.Core.Localization`, and `ChengYuan.Core.Data`, then enforce their dependency boundaries with architecture tests.
235+
3. Wave C: add `ChengYuan.Core.Json`, `ChengYuan.Core.Validation`, `ChengYuan.Core.Localization`, and `ChengYuan.Core.Data`, then enforce their dependency boundaries with `ChengYuan.ArchitectureAnalyzer`.
236236
4. Wave D: add `ChengYuan.Core.EntityFrameworkCore` for converters, repositories, unit of work, and data-filter implementations.
237237
5. Wave E: rebase `ExecutionContext`, `MultiTenancy`, `Caching`, `Outbox`, and later `Authorization`, `Settings`, `Features`, and `Auditing` on the new Core family.
238238
6. Wave F: split and tighten tests into core modularity, core primitives, provider, and framework-kernel suites.
@@ -329,7 +329,7 @@ It may intentionally omit modules that are irrelevant to a command-line scenario
329329
3. Do not create empty `Web`, `Cli`, or `Persistence` projects just for symmetry.
330330
4. Keep the directory shape `family root -> short module folder -> project`.
331331
5. Do not put family words in project names, but keep facet words in project names when they describe the project role.
332-
6. Add architecture tests whenever a new module or facet is introduced.
332+
6. Update `ChengYuan.ArchitectureAnalyzer` whenever a new module or facet introduces a new architecture boundary.
333333
7. Promote recurring technical concerns into `Framework`, not into shared application dumping grounds.
334334
8. Promote reusable management capabilities into `Applications`, not into hosts.
335335
9. Keep hosts thin and declarative.

‎docs/guide/introduction.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ family root -> short module folder -> project
3535

3636
For example, `src/Applications/Identity/ChengYuan.Identity.Application/` is preferred over `src/Applications/ChengYuan.Identity/ChengYuan.Identity.Application/`, and over introducing a role-only layer such as `src/Applications/Identity/Application/ChengYuan.Identity.Application/`.
3737

38-
Tests mirror the same organization. Keep module tests under `tests/ChengYuan.FrameworkKernel.Tests/<Family>/<Module>/...` and architecture suites under `tests/ChengYuan.ArchitectureTests/<Suite>/...`.
38+
Tests mirror the same organization. Keep module tests under `tests/ChengYuan.FrameworkKernel.Tests/<Family>/<Module>/...`; architecture boundaries are enforced at compile time by `ChengYuan.ArchitectureAnalyzer`.
3939

4040
## What ChengYuan Is Not
4141

‎docs/zh-cn/contributing/development.md‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
- `Framework` modules 只能依赖其他 `Framework` modules。
1515
- `Application` modules 可以依赖 `Framework` modules,也只能通过 `Contracts` 依赖其他 `Application` modules。
1616
- Hosts 只做模块组合,不承载业务用例实现。
17-
- 引入新模块或新 facet 形态时,必须补充架构测试。
17+
- 引入新模块或新 facet 形态并带来新的架构边界时,必须更新 `ChengYuan.ArchitectureAnalyzer`。
1818

1919
## 前置要求
2020

@@ -42,7 +42,7 @@ build.ps1 # Windows
4242
2. 再确定模块 profile 或 facet 组合。
4343
3. 只创建模块真正需要的项目。
4444
4. 显式声明直接依赖。
45-
5. 添加或更新架构测试。
45+
5. 如果改动引入新的架构边界,更新 `ChengYuan.ArchitectureAnalyzer`。
4646
6. 只有在需要对应传输方式时,才把模块接入 Web 或 CLI。
4747

4848
## NUKE 构建 Target

‎docs/zh-cn/guide/architecture.md‎

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
- 将可复用切面拆开,让技术系统、可复用应用能力与可选扩展各自演进。
1212
- 允许模块深度不一致,不强制所有模块都暴露相同层次或相同传输方式。
1313
- Web 和 CLI 都是可选的 transport facet。
14-
- 所有依赖必须显式声明,并通过架构测试约束。
14+
- 所有依赖必须显式声明,并通过编译期 `ChengYuan.ArchitectureAnalyzer` 约束。
1515
- 保留强工程约束:构建自动化、锁定还原、版本管理、测试和文档。
1616

1717
## 顶层结构
@@ -52,7 +52,7 @@ src/
5252

5353
推荐路径形态是 `家族根目录 -> 短模块目录 -> 项目目录`。应使用 `src/Applications/Identity/ChengYuan.Identity.Application/`,而不是 `src/Applications/ChengYuan.Identity/ChengYuan.Identity.Application/`,也不要再引入 `src/Applications/Identity/Application/` 这类只表达角色的中间目录。
5454

55-
测试目录遵循同样的镜像规则。模块测试放在 `tests/ChengYuan.FrameworkKernel.Tests/Applications/Identity/` 这类路径下,架构测试放在 `tests/ChengYuan.ArchitectureTests/Structure/` 这类按测试套件划分的路径下。
55+
测试目录遵循同样的镜像规则。模块测试放在 `tests/ChengYuan.FrameworkKernel.Tests/Applications/Identity/` 这类路径下;架构边界由编译期 `ChengYuan.ArchitectureAnalyzer` 强制执行。
5656

5757
`Framework`、`Applications`、`Hosts` 这类家族词只属于目录,不属于项目名。`Application`、`Persistence`、`Web` 这类 facet 词如果是在描述项目职责,则继续保留在项目名中。
5858

@@ -206,7 +206,7 @@ src/
206206

207207
1. Wave A:创建 `ChengYuan.Core` 家族,并把模块化所有权从 `ChengYuan.Hosting` 迁出。
208208
2. Wave B:建立 Core 的失败模型和 DDD 基线,包括异常、错误码、`Result`、实体、聚合根、值对象、强类型 Id、`IClock`、`IGuidGenerator`。
209-
3. Wave C:增加 `ChengYuan.Core.Json`、`ChengYuan.Core.Validation`、`ChengYuan.Core.Localization`、`ChengYuan.Core.Data`,并用架构测试约束依赖边界。
209+
3. Wave C:增加 `ChengYuan.Core.Json`、`ChengYuan.Core.Validation`、`ChengYuan.Core.Localization`、`ChengYuan.Core.Data`,并用 `ChengYuan.ArchitectureAnalyzer` 约束依赖边界。
210210
4. Wave D:增加 `ChengYuan.Core.EntityFrameworkCore`,承载转换器、仓储、工作单元和数据过滤器实现。
211211
5. Wave E:将 `ExecutionContext`、`MultiTenancy`、`Caching`、`Outbox`,以及后续的 `Authorization`、`Settings`、`Features`、`Auditing` 重建到新的 Core 家族之上。
212212
6. Wave F:把测试拆分并收紧为 core modularity、core primitives、provider、framework-kernel 四类。
@@ -303,7 +303,7 @@ CLI 场景可以有意省略某些与命令行无关的模块。不要把 Web tr
303303
3. 不要为了形式统一而创建空的 `Web`、`Cli` 或 `Persistence` 项目。
304304
4. 目录结构固定为 `家族根目录 -> 短模块目录 -> 项目目录`。
305305
5. 项目名中不要带家族词,但描述项目职责的 facet 词应保留。
306-
6. 每次引入新模块或新 facet,都补充架构测试。
306+
6. 每次引入新模块或新 facet 并带来新的架构边界时,都更新 `ChengYuan.ArchitectureAnalyzer`。
307307
7. 重复出现的技术能力应提升到 `Framework`,而不是塞进共享应用项目。
308308
8. 可复用管理能力应进入 `Applications`,而不是堆到 host 中。
309309
9. Hosts 必须保持薄且声明式。

‎docs/zh-cn/guide/introduction.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ docs/ # 文档
3535

3636
例如,更推荐 `src/Applications/Identity/ChengYuan.Identity.Application/`,而不是 `src/Applications/ChengYuan.Identity/ChengYuan.Identity.Application/`,也不要引入 `src/Applications/Identity/Application/ChengYuan.Identity.Application/` 这种只表达角色的中间层。
3737

38-
测试目录遵循同样的镜像规则。模块测试放在 `tests/ChengYuan.FrameworkKernel.Tests/<Family>/<Module>/...` 下,架构测试按测试套件放在 `tests/ChengYuan.ArchitectureTests/<Suite>/...` 下。
38+
测试目录遵循同样的镜像规则。模块测试放在 `tests/ChengYuan.FrameworkKernel.Tests/<Family>/<Module>/...` 下;架构边界由编译期 `ChengYuan.ArchitectureAnalyzer` 强制执行。
3939

4040
## 承渊不是什么
4141

‎src/Analyzers/ChengYuan.Architecture/ArchitectureDiagnosticRule.cs‎

Lines changed: 0 additions & 8 deletions
This file was deleted.

0 commit comments

Comments
 (0)