Review a topology before declaring it¶
ArchLinterNet's topology workflow separates observation from an architecture decision. Capture records what the current first-party analysis can observe. A reviewer then decides which observations belong in a bounded declared topology. Diff and verify evaluate that hand-authored declaration; they do not accept capture output or rewrite policy.
Capture observations¶
Start with a policy that describes the analysis inputs. It may omit topology when the repository
has no declaration yet:
version: 1
name: Topology capture inputs
layers: {}
analysis:
target_assemblies: [MyProduct.Server, MyProduct.Application, MyProduct.Domain]
projects:
- src/MyProduct.Server/MyProduct.Server.csproj
- src/MyProduct.Application/MyProduct.Application.csproj
- src/MyProduct.Domain/MyProduct.Domain.csproj
contracts: {}
For the first capture, use --ensure-built so ArchLinterNet builds the selected project graph
and writes the receipt that proves which artifacts it analyzed. A regular dotnet build alone
does not create that receipt. Later commands can reuse receipt-backed artifacts while their
inputs remain unchanged.
dotnet arch-linter-net topology capture \
--policy architecture/arch.yml \
--subject-kind assembly \
--ensure-built \
--format json \
--output artifacts/topology-capture.json
The supported subject kinds are type, namespace, project, and assembly. Capture is
read-only, including when the policy has no declared topology. The output is a review artifact:
it is not a YAML policy fragment, does not invent exact type selectors, and does not imply that a
candidate is approved. Keep it outside architecture/ or another directory containing the
reviewed policy, and commit it only when the repository wants a traceable observation artifact.
Review and hand-author the declaration¶
Review subjects and directed dependency witnesses together. Select a bounded scope, group
subjects under stable node IDs, and decide which edges are allowed. If a subject is intentionally
outside this declaration, record an explicit out_of_scope entry with a reason. A reviewer, not
the capture command, must author these choices in the policy.
For example, a server/library declaration can make the intended direction explicit:
topology:
mode: exhaustive
subject_kind: assembly
scope:
allow_empty: false
selectors:
- assembly: MyProduct.Server
- assembly: MyProduct.Application
- assembly: MyProduct.Domain
nodes:
- id: server
mappings:
- assembly: MyProduct.Server
- id: application
mappings:
- assembly: MyProduct.Application
- id: domain
mappings:
- assembly: MyProduct.Domain
allowed_edges:
- from: server
to: application
- from: application
to: domain
For a Unity project, use the .asmdef assembly names as assembly selectors after Unity has
exported the assemblies for analysis. .asmdef validation remains a Core capability; topology
capture does not rewrite the manifests or turn them into an approved topology.
Diff declared and observed evidence¶
Once a declaration is present, ask for a review projection:
dotnet arch-linter-net topology diff \
--policy architecture/arch.yml \
--mode strict \
--ensure-built \
--format json \
--output artifacts/topology-diff.json
Diff delegates observation and evaluation to ordinary validation. Its categories stay separate:
| Category | Meaning |
|---|---|
structural |
A mapped subject has ambiguous component ownership. |
relational |
Exactly mapped components have an observed directed edge that is not allowed; retain its dependency witness. |
unmapped |
An observed in-scope subject has no component mapping in an exhaustive declaration. |
stale |
With stale_declarations: true and complete mapping evidence, a declared node or allowed edge has no observed counterpart. |
Reviewed out-of-scope subjects remain visible evidence. They are not reclassified as unmapped or stale drift. Diff requires a declared topology and does not modify the policy, imports, baseline, or capture artifact.
Verify with normal validation semantics¶
Use verify when a focused topology result is useful to a review or CI job:
dotnet arch-linter-net topology verify \
--policy architecture/arch.yml \
--mode strict \
--ensure-built \
--format json
dotnet arch-linter-net topology verify \
--policy architecture/arch.yml \
--mode audit \
--ensure-built \
--format json
Verify invokes ordinary validation once. Strict and audit pass/fail and applicability behavior therefore match a normal validation run; verify adds no topology-specific success condition and does not create a second baseline or result envelope. A policy without declared topology is an actionable input error for diff and verify, while capture remains available.
Stable JSON contract¶
Capture JSON is versioned independently of the package version. Its top-level kind is
topology-capture and schema_version is 1. Arrays are canonically ordered, so repeating a
capture for unchanged inputs produces identical bytes. The v1 document contains:
{
"kind": "topology-capture",
"schema_version": 1,
"subject_kind": "assembly",
"subjects": [
{
"identity": "assembly|project=MyProduct.Server|assembly=MyProduct.Server|subject=MyProduct.Server",
"subject_kind": "assembly",
"subject": "MyProduct.Server",
"project": "MyProduct.Server",
"assembly": "MyProduct.Server"
}
],
"relationships": [
{
"source_identity": "...",
"target_identity": "...",
"witness": "MyProduct.Server -> MyProduct.Application"
}
],
"repository_root": "...",
"policy_import_paths": [],
"resolved_assembly_paths": [],
"discovered_project_paths": [],
"preflight_diagnostics": [],
"preflight_blocked": false
}
identity is an opaque stable key; consumers must not reconstruct it from display names. Subjects
and relationships are observations, not declaration entries. Diff JSON has the same versioned
document discipline and exposes the four categories above, while verify preserves the ordinary
validation JSON envelope and its existing exit codes (0 passed, 1 findings, 2 input/runtime
error). Consumers should key automation on kind, schema_version, category names, and typed
diagnostic fields rather than human rendering.
Neither operation writes a policy. A clean capture, diff, or verify result is evidence for review, never automatic architecture approval.