| name | smart-detect |
| description | Use when detecting .NET project type, architecture pattern, or solution structure. |
| metadata | {"category":"detection"} |
| when_to_use | When detecting project architecture type or analyzing .NET project structure |
Smart Detection Skill
You are analyzing a .NET project to determine its architectural type using behavioral analysis.
Input
You will receive:
- Project directory path to scan
- Up to 10 representative files from the project (you will read these yourself)
Step 1: Gather Project Context
Read the following files to build a picture of the project:
Configuration Files (read first)
Program.cs or Startup.cs — startup configuration
*.csproj — NuGet packages, target framework, SDK type
*.sln or *.slnx — solution structure
Code Samples (read up to 5)
**/Application/**/Handlers/**/*.cs or **/Features/**/*Handler.cs
**/Controllers/**/*.cs
**/Services/**/*Service.cs
**/Domain/**/Aggregate*.cs or **/Domain/**/Core/*.cs
**/Endpoints/**/*.cs or **/Modules/**/*.cs
Structural Indicators (check existence)
Features/ directory — VSA indicator
Domain/, Application/, Infrastructure/ directories — Clean Architecture indicator
BoundedContexts/ or Contexts/ directory — DDD indicator
Modules/ directory — Modular Monolith indicator
Controllers/ directory — traditional MVC/API
Listeners/ or ServiceBus/ directory — event-driven
*.razor files — Blazor UI
Step 2: Analyze Data Flow
For each handler/service file, analyze:
What comes IN?
- Commands: handler takes a command object (e.g.,
IRequestHandler<CreateOrderCommand>)
- Events: handler takes an event object (e.g.,
IRequestHandler<Event<OrderCreatedData>, bool>)
- HTTP requests: controller actions with
[HttpGet], [HttpPost], etc.
- Minimal API:
app.MapGet(), app.MapPost(), endpoint definitions
What happens INSIDE?
- Domain manipulation: loads events by aggregate ID, rebuilds aggregate, calls domain methods, commits
- Database save: calls
SaveChangesAsync, AddAsync, repository Add/Update
- Service calls: calls gRPC/HTTP clients to other services
- Message publishing: publishes to ServiceBus/queue/topic
- Feature orchestration: coordinates within a single feature slice
What goes OUT?
- Nothing (void/Task): typical command handler
- Bool acknowledgment: typical event handler
- Data (DTOs/responses): typical query handler or controller
- HTML/Blazor: UI rendering
Step 3: Classify
Microservice Mode Types
These types are for projects following a CQRS/event-sourced microservice architecture:
| Type | IN | INSIDE | OUT |
|---|
| command | Commands | Load aggregate -> domain method -> commit events | void/Task |
| query-sql | Events | Save to SQL database | bool (ack) |
| query-cosmos | Events | Save to Cosmos DB | bool (ack) |
| processor | Events | Call other gRPC services OR publish to message bus | bool (ack) |
| gateway | HTTP requests | Forward to gRPC services | HTTP responses |
| controlpanel | Browser requests | Blazor components render UI | HTML/Blazor |
| hybrid | Commands AND Events | Both domain manipulation AND DB save | Mixed |
Generic Mode Types
These types are for projects following common .NET architectural patterns outside CQRS microservices:
| Type | Key Indicators | Structure | Typical Patterns |
|---|
| vsa | Features/ directory with self-contained slices | Each feature folder contains handler, validator, model, endpoint | MediatR handlers per feature, minimal cross-feature dependencies |
| clean-arch | 3+ layers: Domain, Application, Infrastructure | Separate projects per layer, dependency inversion | Use cases in Application, entities in Domain, repos in Infrastructure |
| ddd | BoundedContexts/ or Contexts/ directory | Bounded contexts with internal layering | Aggregates, value objects, domain events, anti-corruption layers |
| modular-monolith | Modules/ directory with independent modules | Each module has its own API, domain, infrastructure | Module-to-module communication via contracts/events |
| generic | None of the above patterns match | Varies — could be simple API, console app, library | Standard .NET project without strong architectural pattern |
VSA (Vertical Slice Architecture) — Detailed Indicators
Structure signals:
Features/ or Slices/ directory at project root
- Each subdirectory under Features/ contains all layers for one feature (handler, request, response, validator)
- No separate
Application/, Domain/, Infrastructure/ top-level layers
Code signals:
- MediatR
IRequestHandler<TRequest, TResponse> per feature
IValidator<T> paired with handlers in same folder
- Endpoint classes or minimal API mappings grouped by feature
- AutoMapper/Mapster profiles per feature folder
NuGet signals:
MediatR, FluentValidation, Carter or FastEndpoints
Clean Architecture — Detailed Indicators
Structure signals:
- 3+ separate projects:
*.Domain, *.Application, *.Infrastructure, *.Api (or *.Web, *.Presentation)
- Domain project has NO references to other projects
- Application references only Domain
- Infrastructure references Application (and sometimes Domain)
- API/Web references all others
Code signals:
- Interfaces in Application (
IRepository<T>, IUnitOfWork)
- Implementations in Infrastructure
- Use case classes or command/query handlers in Application
- Entities and value objects in Domain with no framework dependencies
NuGet signals:
- Domain project: minimal packages (maybe
MediatR.Contracts only)
- Infrastructure:
EntityFrameworkCore, Dapper, provider packages
DDD (Domain-Driven Design) — Detailed Indicators
Structure signals:
BoundedContexts/ or Contexts/ directory
- Each bounded context has its own Domain, Application, Infrastructure
SharedKernel/ or BuildingBlocks/ directory for cross-cutting concerns
AntiCorruption/ or ACL/ directories
Code signals:
AggregateRoot or Entity base classes in domain
- Value objects with structural equality
- Domain events (
IDomainEvent, DomainEvent)
- Domain services with business logic
- Repository interfaces per aggregate root
NuGet signals:
- Domain event libraries, CQRS packages
Modular Monolith — Detailed Indicators
Structure signals:
Modules/ directory with independent module directories
- Each module has its own
Api/, Core/ (or Domain/), Infrastructure/
Contracts/ or IntegrationEvents/ for inter-module communication
- Shared
Infrastructure/ or Common/ at root level
Code signals:
- Module registration in Program.cs (
AddModule<OrderModule>() pattern)
- Internal module classes (not public)
- Inter-module communication via events or contracts
- Each module has its own DbContext or schema
NuGet signals:
- Module framework packages if any
Generic — When to Classify
Use generic when:
- The project is a simple Web API without clear architectural layering
- Console application or background worker
- Class library or NuGet package project
- The project structure does not match any of the above patterns
- Mixed patterns that do not clearly fit one category
Decision Process
Apply rules in order — first match wins:
- If
.razor files exist → controlpanel
- If controllers forward ALL requests to gRPC clients (no local DB) → gateway
- If REST API with reverse proxy (YARP) → gateway
- If handlers receive commands AND events, manipulate domain AND save to DB → hybrid
- If handlers receive commands, manipulate domain aggregates, commit events, NOT consuming events → command
- If handlers receive events, call other services/publish messages, NOT saving to DB → processor
- If handlers receive events and save to Cosmos DB → query-cosmos
- If handlers receive events and save to SQL/EF → query-sql
- If
Features/ directory with self-contained feature handlers → vsa
- If 3+ layers (Domain, Application, Infrastructure) with dependency inversion → clean-arch
- If
BoundedContexts/ or Contexts/ directory with aggregate roots → ddd
- If
Modules/ directory with independent module structure → modular-monolith
- Otherwise → generic
Output Format
CRITICAL: project_type is the SPECIFIC type (command, query-sql, vsa, etc.). mode is ALWAYS microservice or generic. Never swap these.
project_type: {command|query-sql|query-cosmos|processor|gateway|controlpanel|hybrid|vsa|clean-arch|ddd|modular-monolith|generic}
mode: {microservice|generic}
confidence: {high|medium|low}
dotnet_version: "{version from csproj TargetFramework}"
architecture: "{human-readable description}"
namespace_format: "{detected namespace pattern}"
evidence:
1. {most important behavioral evidence}
2. {second most important evidence}
3. {third most important evidence}
reasoning: "{1-2 sentences explaining the data flow that led to this classification}"
packages:
- {key NuGet packages detected}
solution_name: "{solution name without extension, from .sln/.slnx file}"
layers:
domain: "{Domain project name or empty}"
application: "{Application project name or empty}"
infrastructure: "{Infrastructure project name or empty}"
presentation: "{Presentation project name or empty}"
api_style: "{grpc|rest|blazor|minimal-api|none}"
patterns:
- "{architectural patterns detected, e.g. cqrs-command-side, event-sourcing, outbox-pattern}"
deployment:
containerized: {true if Dockerfile exists, else false}
orchestration: "{kubernetes if k8s manifests, docker-compose if compose file, else empty}"
test_projects:
- "{test project names from solution}"
sibling_repos:
- name: "{sibling repo directory name}"
type: "{detected type or empty}"
New field derivation
- solution_name: Read from
.sln/.slnx filename (strip extension)
- layers: Map solution projects to logical layers — look for Domain/Application/Infrastructure/Infra/Presentation/Api/Web/Grpc in project names
- api_style: Check presentation project packages —
Grpc.AspNetCore → grpc, Microsoft.AspNetCore.Mvc or controllers → rest, .razor files → blazor, app.MapGet/app.MapPost without controllers → minimal-api
- patterns: List architectural patterns found in code (cqrs-command-side, mediator, event-sourcing, outbox-pattern, clean-architecture, vertical-slice, repository-pattern, specification-pattern, etc.)
- deployment: Check for Dockerfile and kubernetes manifests or docker-compose.yml
- test_projects: Solution projects referencing xunit/nunit/mstest or named .Test/.Tests
- sibling_repos: Directories in
../ that are git repos with .NET projects — classify by quick structural scan
Important Notes
- Focus on BEHAVIOR, not naming. A class called "OrderService" tells you nothing about data flow.
- A handler that receives events AND saves to DB is a QUERY handler, even if it calls other services for enrichment.
- A handler that receives events AND forwards to other services WITHOUT saving locally is a PROCESSOR.
- Command projects may PUBLISH events to ServiceBus (outbox pattern) but do not CONSUME/LISTEN to events.
- Look at the MAJORITY of handlers, not edge cases.
- For generic mode types, focus on STRUCTURAL patterns (directory layout, project references) over code patterns.
- When confidence is low, explain what additional files would help clarify the classification.
Related rules
This skill depends on the always-on existing-projects convention rule:
- ${CLAUDE_PLUGIN_ROOT}/rules/conventions/existing-projects.md
The rule is loaded into context whenever this skill is active (FR-011 universal whitelist).