Concrete examples of what Architests does, and who each one is for.
Developer
The whole rule set from a policy file and one derived class
You want your layering enforced by the build, but you do not want to hand-write the same dependency-direction and forbidden-reference tests in every repository.
// .config/architecture-policy.json declares the responsibilities.
// This is the entire test suite.
[InheritsTests]
public sealed class ArchitectureTests : PurviewArchitectureTests;
What you get: One policy file plus one derived test class is the whole suite. Each rule is a separate test, so a failure names the rule rather than collapsing the set into one assertion.
The base class ships twelve rule ids as separate [Test]s — graph discovery, naming, discouraged name, dependency matrix, assembly matrix, sibling independence, composition boundary, forbidden package, forbidden framework, cycle, test reference and waiver integrity — plus a schema-validation test that runs first. [InheritsTests] is required: without it TUnit discovers nothing, the run is green and nothing is enforced, which TUnit's own analyzer reports as TUnit0030.
Read the guide →
Developer
Catch a type-level dependency a ProjectReference never shows
A project file only shows declared ProjectReferences. A type that arrives transitively through another project, or through a package, is invisible to a project-level check.
"assemblyRules": {
"enabled": true,
"assemblyRoots": [],
"assemblyGlobs": ["*.dll"]
}
What you get: The same mayDependOn/mustNotDependOn matrix is applied to the types each compiled assembly actually references. An empty assemblyRoots scans the test output directory, which already holds every project the test project references.
The reader opens each assembly with System.Reflection.Metadata and walks the TypeReference table — nothing is loaded, executed, or resolved through a probing path, so a type initialiser never runs. Enabling the rule with no production assemblies found is a failure, not a silent pass.
Read the guide →
Architect
A dependency the policy is silent about is a violation, not permission
Your layering is agreed and documented, and you want a reference that points the wrong way to fail the build rather than erode the design one reasonable-looking reference at a time.
{
"version": 2,
"sourceRoots": ["src"],
"responsibilities": [
{
"name": "Domain",
"category": "domain",
"purpose": "The domain model, its invariants and its rules.",
"mayDependOn": [],
"mustNotDependOn": ["Application", "Persistence", "Composition"]
}
]
}
What you get: The matrix is applied three ways: the same responsibility is always allowed, mustNotDependOn is a violation, and a reference the matrix neither permits nor forbids is also a violation — so a gap in the policy is surfaced instead of passing.
A project name is classified by its first segment only, so Persistence.SqlServer and Persistence follow the same rules and qualification is a naming choice rather than a different set of rules.
Read the guide →
Team lead
A reviewed waiver instead of switching a rule off
One project legitimately departs from the architecture policy, and you do not want to answer that by disabling the rule for the whole repository.
{
"waivers": [
{
"project": "Persistence.Legacy",
"mapsTo": "Persistence",
"rules": ["forbiddenPackage"],
"reason": "The legacy EF6 store is being replaced and still needs EntityFramework.",
"reviewedOn": "2026-10-16"
}
]
}
What you get: The departure is per project, carries a reason and a review date, keeps every other rule in force, and is itself checked. SkipRule opts a whole repository out with no record, so a waiver is the narrower choice.
Any rule id may be waived, including siblingIndependence and assemblyDependencyMatrix, but an unknown id is a waiverIntegrity failure — a typo cannot silently excuse nothing — and only graphDiscovery and waiverIntegrity are not waivable.
Read the guide →
Contributor
Add a bespoke rule to the same reporting and waiver model
You need a repository-specific check — a banned API, a required convention — and do not want a second architecture framework to maintain alongside the standard set.
[InheritsTests]
public sealed class ArchitectureTests : PurviewArchitectureTests
{
protected override IReadOnlyList<IArchitectureRule> AdditionalRules => [new NoConsoleLoggingRule()];
sealed class NoConsoleLoggingRule : IArchitectureRule
{
public string Rule => "noConsoleLogging";
public IReadOnlyList<ArchitectureViolation> Evaluate(ArchitectureContext context) =>
context.Projects.Values
.Where(project => !project.IsTestProject)
.Select(project => new ArchitectureViolation(Rule, project.Name, "Console logging is banned here."))
.ToArray();
}
}
What you get: An additional rule runs as its own test, honours SkipRule by its rule id, and is excused by a matching waiver without any extra plumbing — the same reporting the built-in rules use.
The evaluator takes the parsed policy, the project graph and the assemblies as constructor arguments, so a rule is testable as a small in-memory fixture rather than a repository on disk — which is how the package's own rules are tested.
Read the guide →