Architecture Design
project-spec -> architecture-design -> domain-develop -> application-develop -> adapter-develop -> observability-develop -> test-develop
Prerequisites
Section titled “Prerequisites”If 00-project-spec.md generated by the project-spec skill exists, it is automatically read to confirm Aggregate candidates and use case overview. If not, the user is asked directly about the project scope.
Background
Section titled “Background”Once Aggregate candidates and business rules are defined, the next question is “Where and under what names do we place this code?” Project structure, layer separation, naming conventions, and infrastructure decisions must be agreed upon before writing code. Changing them later requires renaming paths and files everywhere.
The architecture-design skill designs the project skeleton following the Functorium framework’s layered architecture principles. It organizes solution configuration, folder tree, naming conventions, project reference direction, and persistence/observability/API infrastructure decisions into a single document.
Skill Overview
Section titled “Skill Overview”4 Phase Workflow
Section titled “4 Phase Workflow”| Phase | Activity | Deliverable |
|---|---|---|
| 1. Project Structure Decision | Project name, solution separation level, Adapter separation approach | Solution configuration draft |
| 2. Layer Composition | Domain/Application/Adapter/Host folder tree | Per-layer folder structure |
| 3. Infrastructure Decisions | Persistence, observability, HTTP API, external service strategy | Infrastructure decision specification |
| 4. Document Generation | Organize all content into a structured document | 01-architecture-design.md |
Trigger Examples
Section titled “Trigger Examples”Design the architectureSet up the project structureDesign the layersConfigure the solutionDetermine the folder structurePhase 1: Project Structure Decision
Section titled “Phase 1: Project Structure Decision”The skill determines the following through conversation.
Basic Decisions:
- Project naming (e.g.,
AiGovernance,ECommerce) - Single solution vs multi-solution
- Adapter project separation level:
- Single:
{Name}.Adapters— Suitable for small projects - Separated:
{Name}.Adapters.Infrastructure+{Name}.Adapters.Persistence+{Name}.Adapters.Presentation— Suitable for medium to large projects
- Single:
Phase 2: Layer Composition
Section titled “Phase 2: Layer Composition”Overall Solution Structure
Section titled “Overall Solution Structure”{ProjectRoot}/├── {name}.slnx # Solution file├── Directory.Build.props # FunctoriumSrcRoot + common settings├── Src/│ ├── {Name}.Domain/ # Domain Layer│ ├── {Name}.Application/ # Application Layer│ ├── {Name}.Adapters.Infrastructure/ # Mediator, OpenTelemetry, External Services│ ├── {Name}.Adapters.Persistence/ # EfCore, Dapper, InMemory│ ├── {Name}.Adapters.Presentation/ # FastEndpoints│ └── {Name}/ # Host (Program.cs)└── Tests/ ├── {Name}.Tests.Unit/ # Domain + Application + Architecture └── {Name}.Tests.Integration/ # HTTP Endpoint E2EDomain Layer Folder
Section titled “Domain Layer Folder”{Name}.Domain/├── AggregateRoots/│ └── {Aggregate}/│ ├── {Aggregate}.cs # AggregateRoot│ ├── I{Aggregate}Repository.cs # Repository Port│ ├── ValueObjects/ # VO collection│ └── Specifications/ # Query conditions└── SharedModels/ └── Services/ # Domain ServiceApplication Layer Folder
Section titled “Application Layer Folder”{Name}.Application/└── Usecases/ └── {Aggregate}/ ├── Commands/ # State-changing use cases ├── Queries/ # Read use cases ├── Events/ # Domain event handlers ├── I{Aggregate}Query.cs # Read Port (list queries) └── I{Aggregate}DetailQuery.cs # Read Port (detail queries)Adapter Layer Folder (Persistence)
Section titled “Adapter Layer Folder (Persistence)”{Name}.Adapters.Persistence/└── {Aggregate}/ ├── {Aggregate}.Model.cs # DB POCO model ├── {Aggregate}.Configuration.cs # EF Core Fluent API ├── {Aggregate}.Mapper.cs # Domain <-> Model conversion ├── Repositories/ │ ├── {Aggregate}RepositoryEfCore.cs │ └── {Aggregate}RepositoryInMemory.cs └── Queries/ ├── {Aggregate}QueryDapper.cs └── {Aggregate}QueryInMemory.cs3-Dimensional Folder Structure Principle
Section titled “3-Dimensional Folder Structure Principle”Adapter folders are organized in 3 dimensions:
| Dimension | Representation | Example |
|---|---|---|
| Aggregate (what) | Primary folder | Products/, Orders/ |
| CQRS Role (read/write) | Secondary folder | Repositories/, Queries/ |
| Technology (how) | Class suffix | EfCore, InMemory, Dapper |
Naming Conventions
Section titled “Naming Conventions”| File Type | Pattern | Example |
|---|---|---|
| Repository | {Aggregate}Repository{Variant}.cs | ProductRepositoryEfCore.cs |
| Query | {Aggregate}Query{Variant}.cs | ProductQueryDapper.cs |
| DB Model | {Aggregate}.Model.cs | Product.Model.cs |
| EF Configuration | {Aggregate}.Configuration.cs | Product.Configuration.cs |
| EF Mapper | {Aggregate}.Mapper.cs | Product.Mapper.cs |
Project Reference Direction
Section titled “Project Reference Direction”Layer dependency direction flows only inward:
Host -> Adapters.Infrastructure -> Application -> Domain -> Adapters.Persistence -> Application -> Domain -> Adapters.Presentation -> ApplicationDomain references only the Functorium framework and SourceGenerators. Application references only Domain. Adapters depend on Application or Domain, but the reverse is not allowed.
Phase 3: Infrastructure Decisions
Section titled “Phase 3: Infrastructure Decisions”Persistence Strategy
Section titled “Persistence Strategy”Switch between InMemory/Sqlite via Persistence:Provider in appsettings.json:
{ "Persistence": { "Provider": "InMemory", "ConnectionString": "Data Source=app.db" }}Branch by Provider in DI registration:
var provider = config["Persistence:Provider"];return provider switch{ "Sqlite" => services.RegisterSqliteRepositories(config), _ => services.RegisterInMemoryRepositories()};Observability Strategy
Section titled “Observability Strategy”Configure the OpenTelemetry 3-Pillar (Logging + Tracing + Metrics) pipeline:
services.RegisterOpenTelemetry(config, assembly) .ConfigurePipelines(p => p .UseMetrics() // 1. Metrics collection .UseTracing() // 2. Distributed tracing .UseCtxEnricher() // 3. Business context propagation .UseLogging() // 4. Structured logging .UseException()) // 5. Exception conversion .Build();HTTP API Strategy
Section titled “HTTP API Strategy”HTTP endpoints are configured based on FastEndpoints.
External Service Strategy
Section titled “External Service Strategy”Leverages advanced features of the IO monad:
| Pattern | Purpose | Example |
|---|---|---|
IO.Timeout + Catch | Timeout + conditional recovery | Health check API |
IO.Retry + Schedule | Exponential backoff retry | External monitoring API |
IO.Fork + Await | Parallel execution | Parallel compliance checks |
IO.Bracket | Resource acquire-use-release | Registry session management |
Phase 4: Document Generation
Section titled “Phase 4: Document Generation”All collected decisions are organized into {context}/01-architecture-design.md.
Content Included in the Output Document
Section titled “Content Included in the Output Document”- Project structure diagram (folder tree)
- Solution file (.slnx) configuration
- Project reference relationship diagram
- Per-layer naming convention table
- DI registration strategy (roles per Registration class)
- Persistence Provider switching configuration (appsettings.json)
- Observability pipeline order
- Build/test commands
Next Step Guidance
Section titled “Next Step Guidance”The architecture design is complete.
Next Steps:
- Use the
domain-developskill to design and implement each Aggregate in detail- 4-step documents from
00-business-requirements.md->03-implementation-results.mdwill be generated per Aggregate
Core Principles
Section titled “Core Principles”- Layer dependency direction: Domain <- Application <- Adapter <- Host
- Adapter folder organization: Aggregate-centric (primary) + CQRS Role (secondary) + Technology suffix
- Naming:
{Subject}{Role}{Variant}(e.g.,ProductRepositoryEfCore) - DB model/configuration files: Dot notation (e.g.,
Product.Model.cs,Product.Configuration.cs) - Persistence Provider switching: Switch InMemory/Sqlite via
Persistence:Providerin appsettings.json $(FunctoriumSrcRoot)variable: Used for framework references in csproj
References
Section titled “References”- Workflow — 7-step overall flow
- Project Spec Skill — Previous step: PRD writing
- Domain Develop Skill — Next step: Domain model implementation
- Adapter Develop Skill — Persistence/API implementation