Imported from eugenemalaschuk-source/arch-linter-net (
AGENTS.md). Install upstream withnpx skills add eugenemalaschuk-source/arch-linter-net. Copyright stays with the author.
Agent Instructions
Project
- ArchLinterNet — declarative architecture contracts and dependency linting for .NET.
- Stack: .NET 10 + C#. Tests use NUnit.
- Solution file:
ArchLinterNet.slnx(.slnxformat, not.sln). TreatWarningsAsErrorsenabled globally inDirectory.Build.props.
Key commands
make setup # full bootstrap: bundle + restore + venv (run once)
make restore # NuGet restore (required before any --no-restore target)
make fmt # dotnet format — auto-format all C# code
make lint # lint-code-size + lint-dotnet-format + lint-architecture
make lint-architecture # canonical read-only strict self-policy gate (CLI + --ensure-built)
make policy-check # fast policy-only validation (no project/assembly analysis)
make public-api-check # read-only reviewed public API drift check
make lint-code-size # file size lint (warn ≥500, error ≥800 lines)
make test # run all tests
make acceptance # lint + all tests
make architecture-coverage-report # full-solution coverage report (Markdown + JSON) on demand
make lint-architecture is the single authoritative definition of "the repository satisfies its own
architecture policy". It is read-only: --ensure-built prepares and verifies the analysed project
graph, but nothing under architecture/ is ever rewritten. Rewriting a reviewed public API snapshot
is an explicit, separate action (make public-api-update); lint, acceptance, and CI never do it.
SelfArchitecturePolicyTests runs the same policy through the ArchLinterNet.Testing adapter inside
make test as parity evidence, not as a second definition of success.
Reviewed public API lifecycle:
make public-api-check # read-only diff (what lint/CI rely on)
make public-api-update-preview # dry run of the rewrite
make public-api-update # explicit snapshot rewrite — the only writing command
All dotnet test/dotnet format targets use --no-restore — run restore first when adding/changing dependencies.
make acceptance is the full local repository gate, not a mandatory step before every PR. Local validation for a feature implementation is risk-based — see docs/ai/feature-implementation-workflow.md, the single source of truth for the validation lifecycle. Exhaustive, cross-platform validation is authoritative in PR CI.
Run a single test project:
dotnet test tests/ArchLinterNet.Core.Tests --no-restore
Run the CLI directly:
dotnet run --project src/ArchLinterNet.Cli -- --policy architecture/dependencies.arch.yml --mode strict
Docs workflow
make venv # create Python virtual environment (one-time)
make docs-serve # start local preview at http://127.0.0.1:8000
make docs-build # build static site to site/
make fmt-docs # auto-format markdown documentation
make lint-docs # verify MkDocs documentation structure
Windows developer setup
All make targets run natively on Windows via Git Bash — WSL is not required and is not used.
- Prerequisite: Git for Windows (already required to clone this repo), which installs Git Bash.
make/paths.mkpinsSHELLto a discoveredbash.exefrom a standard Git for Windows install location, overriding whatever GNU Make would otherwise resolve fromPATH(which can pick up the unrelated WSLbash.exeshim atC:\Windows\System32\bash.exeand fail if no WSL distro is registered).- If Git is installed in a non-default location, point at it explicitly:
make GIT_BASH="D:/Git/bin/bash.exe" fmt. - If
bash.execannot be found at all,makefails immediately with an actionable error naming the fix, instead of failing deep inside a recipe with a WSL error. - macOS/Linux targets are unaffected — this Windows-only
SHELLoverride only applies when$(OS)isWindows_NT;BUNDLE_OS/bundle-unix/theBrewfileflow are unchanged.
Release lifecycle and milestone governance
Canonical internal policy: docs/internal/release-lifecycle-governance.md. Public user-facing version meaning: docs/reference/versioning-and-releases.md.
Before planning, creating, moving, implementing, stabilizing, or preparing release-related work, agents MUST identify the current release-lifecycle phase and apply the internal policy. When release/version semantics are user-visible, agents MUST keep the public versioning contract and NuGet-visible README.md consistent with that policy.
In particular:
- a milestone is a development-wave envelope and traceability aid, not immutable release authority;
- milestone membership alone never makes an issue a blocker for
X.Y.0; - minor capability work may deliberately leave bounded, visible, ratcheted behavior-preserving refactoring for post-release stabilization;
- known correctness, security, release-integrity, false-success, or unusable documented behavior is not optional technical debt and must remain in the owning functional/release path;
- after
X.Y.0, validate the released artifact in real consumer-shaped usage and publish as many corrective patches as needed for adoption stability; - release-specific architecture cleanup precedes broader self-architecture cleanup, which precedes the authoritative whole-repository Sonar/maintainability sweep;
- patch releases form a maintenance train, not an exactly-one-patch ritual;
- next-minor backlog planning may overlap stabilization, but agents must not merge unrelated next-minor product bytes onto the only patch candidate line when that would make a truthful current-line patch impossible without an explicit maintenance-branch/ref strategy.
Use precise completion language: implementation complete, release complete, adoption stable, and milestone/engineering-health complete are different states.
Backlog governance
File: docs/internal/backlog-governance.md.
Before creating or updating GitHub issues, agents MUST apply the backlog governance rules:
- use typed titles such as
[STORY][AI] Tooling: ...and[TASK][AI] Tooling: ...; - use the controlled title verbs from the governance document;
- link issues explicitly with
Parent story: #...,Depends on: #..., andRelated: #...where applicable; - include the required sections:
Goal,Work type,Context,What to do,Manual tasks,AI-friendly tasks,Estimate,Acceptance criteria,Validation, andNon-goals; - estimate the developer's real hands-on time with AI assistance;
- keep architecture-governance and release-pipeline task rules aligned with the governance document;
- for release-related work, state its lifecycle role when useful and keep milestone meaning aligned with
docs/internal/release-lifecycle-governance.md.
Do not create isolated implementation tasks without an existing story or a newly proposed story.
Architecture governance
File: architecture/dependencies.arch.yml. Enforced via lint-architecture.
Reviewed public API snapshots: architecture/api/*.public-api.txt.
Family-by-family adopt/already-covered/N-A/defer rationale:
docs/internal/self-policy-capability-matrix.md.
Direction rules:
- CLI and Testing depend only on Core, at namespace and assembly-reference level.
- Core depends only on CEL; CEL depends on nothing first-party.
- Unity
.asmdefvalidation is a Core capability, not a separate adapter assembly. - No circular dependencies between packages.
Core.Scanninginternals are protected — only Core itself may import them.
Also self-governed: solution-driven project discovery and project coverage, reviewed
InternalsVisibleTo sets, forbidden production→test/benchmark project references, package and
FrameworkReference boundaries, the reviewed Core/Testing/CEL public API surfaces, and the
post-#451/#452/#453 checker / diagnostic-payload / policy-validator seams.
Package layout
src/
ArchLinterNet.CEL/ — host-agnostic CEL evaluation engine (no deps on other ArchLinterNet assemblies)
ArchLinterNet.Core/ — model, YAML loading, assembly resolution, asmdef validation (depends on CEL)
ArchLinterNet.Cli/ — .NET global/local tool CLI
ArchLinterNet.Testing/ — test framework adapters
tests/
ArchLinterNet.CEL.Tests/
ArchLinterNet.Core.Tests/
ArchLinterNet.Cli.Tests/
Conventions
- Private fields:
_camelCase. Types/members:PascalCase. Interfaces:IName. - No BDD/Gherkin — library project.
- File size thresholds: ≥500 lines warning, >800 lines error.
OpenSpec workflow
- Specs live in
openspec/specs/<capability>/spec.md— this is the source of truth. Each spec file MUST have a## Purposesection and a## Requirementssection; it must NOT contain a delta header (## ADDED/MODIFIED/REMOVED/RENAMED Requirements). - During proposal, new capabilities are written as delta specs (
## ADDED Requirements) under the change directory. - To finish a change, run
openspec archive <change-name>. It rebuildsopenspec/specs/<capability>/spec.mdfrom the change's delta specs for both new and existing capabilities — do not copy a delta spec file intoopenspec/specs/directly, since that leaves an invalid delta header in the main spec. - Active changes live in
openspec/changes/<name>/. Archived changes live inopenspec/changes/archive/YYYY-MM-DD-<name>/. - Run
openspec validate --allafter archiving or any manual spec edit.
GitHub feature implementation routing
When the current user message contains exactly one GitHub issue URL matching:
https://github.com/<owner>/<repository>/issues/<number>
load and follow the feature-implementation skill. Treat the URL as the workflow input and implement the issue completely.
Do not ask the user to repeat the workflow or confirm that implementation should begin. This routing rule does not apply to pull request URLs. Do not merge the resulting pull request unless explicitly requested.
Release preparation routing
When the current user asks to prepare, ready, close, or otherwise assemble repository-side content/authority for a concrete ArchLinterNet release, load and follow the release-preparation skill.
Treat an explicit version as the release target. A request for the next patch/minor/major/preview release may derive the target only through the repository's release-process rules and current release/tag facts.
Before deciding what kind of release should exist or what work belongs in the candidate, apply docs/internal/release-lifecycle-governance.md. Then use the release-preparation workflow for the concrete candidate mechanics.
This routing rule prepares release content and reviewed scope; it does not silently authorize package publication, tag/Release creation, or docs deployment. Publication remains the separate maintainer procedure in docs/reference/release-process.md.
State of the repo
- Early extraction / preview. Docs under
docs/built with MkDocs. CI in.github/workflows/.