agentsclimarketplace

Evolutionary architecture

Skill kinhluan/skills/.agent-skills/evolutionary-architecture

Design and maintain architectures that support guided, incremental change. Use this skill for fitness functions, architecture testing, strangler fig patterns, and protecting architectural characteristics as systems evolve.From its SKILL.md

Install
npx -y skills add kinhluan/skills --skill evolutionary-architecture

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

One thing to look at

  • 2 stars2 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

SKILL.md

16.2 KB, ~3.5k tokens by cl100k_base, as published. Nobody here has run it

Evolutionary Architecture

"An evolutionary architecture supports guided, incremental change as a first principle across multiple dimensions." β€” Neal Ford, Rebecca Parsons, Pat Kua

Traditional architecture tries to predict the future. Evolutionary architecture accepts that change is inevitable and builds mechanisms to guide it safely.


🎯 Core Concepts

The Three Pillars

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚              EVOLUTIONARY ARCHITECTURE                       β”‚
β”‚                                                              β”‚
β”‚   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”       β”‚
β”‚   β”‚  Incremental β”‚  β”‚   Fitness   β”‚  β”‚ Appropriate β”‚       β”‚
β”‚   β”‚    Change    β”‚  β”‚  Functions  β”‚  β”‚   Coupling  β”‚       β”‚
β”‚   β”‚              β”‚  β”‚             β”‚  β”‚             β”‚       β”‚
β”‚   β”‚ Deployment   β”‚  β”‚ Automated   β”‚  β”‚ Quantum     β”‚       β”‚
β”‚   β”‚ pipelines    β”‚  β”‚ tests that  β”‚  β”‚ boundaries  β”‚       β”‚
β”‚   β”‚ Feature      β”‚  β”‚ verify      β”‚  β”‚ Team        β”‚       β”‚
β”‚   β”‚ toggles      β”‚  β”‚ architectureβ”‚  β”‚ alignment   β”‚       β”‚
β”‚   β”‚              β”‚  β”‚ goals       β”‚  β”‚             β”‚       β”‚
β”‚   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜       β”‚
β”‚                                                              β”‚
β”‚   Change without guidance = chaos                            β”‚
β”‚   Fitness without change = stagnation                        β”‚
β”‚   Coupling without fitness = fragile                         β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

1️⃣ Fitness Functions

Definition: Automated tests that verify architectural goals and constraints. Like unit tests for architecture.

Types of Fitness Functions

TypeScopeWhen It RunsExample
AtomicSingle componentUnit test phase"No package has >20 classes"
HolisticWhole systemIntegration test"API response time < 200ms"
TriggeredOn specific eventPre-commit/PR"No new circular dependencies"
ContinuousOngoingProduction"Error rate < 0.1%"

Fitness Function Examples

Example 1: Dependency Direction (Atomic)

Goal: Domain layer must not import infrastructure layer (Clean Architecture).

Go (using import-linter):

# .importlinter
[importlinter:contract:clean-architecture]
name = Domain does not depend on Infrastructure
type = forbidden
source_modules =
    myproject.domain
forbidden_modules =
    myproject.infrastructure
    myproject.adapter

Python (using import-linter):

[importlinter:contract:domain-independence]
name = Domain layer is independent
type = forbidden
source_modules =
    myproject.domain
forbidden_modules =
    myproject.infrastructure
    myproject.adapters

Example 2: API Latency (Holistic)

Goal: 95th percentile API response time < 200ms.

# test/fitness/test_api_latency.py
import pytest
from locust import HttpUser, task, between

class APILatencyFitness:
    def test_p95_latency(self):
        """95th percentile API latency must be < 200ms"""
        result = run_load_test(
            endpoint="/api/v1/orders",
            duration="5m",
            users=100
        )
        assert result.p95_latency_ms < 200, \
            f"P95 latency {result.p95_latency_ms}ms exceeds 200ms threshold"

    def test_error_rate(self):
        """Error rate must be < 0.1%"""
        assert result.error_rate < 0.001, \
            f"Error rate {result.error_rate} exceeds 0.1% threshold"

Example 3: No Circular Dependencies (Triggered)

Go:

# .github/workflows/fitness.yml
- name: Check circular dependencies
  run: |
    go install github.com/fzipp/gocyclo@latest
    gocyclo -over 15 ./... || exit 1

- name: Check architecture boundaries
  run: |
    pip install import-linter
    lint-imports

JavaScript/TypeScript:

# package.json
{
  "scripts": {
    "fitness:deps": "madge --circular src/",
    "fitness:coverage": "jest --coverage --coverageThreshold='{\"global\":{\"branches\":80}}'"
  }
}

Example 4: Database Migration Safety (Triggered)

# test/fitness/test_migrations.py
class MigrationFitness:
    def test_no_destructive_migrations(self):
        """Migrations must not drop columns without deprecation period"""
        for migration in get_pending_migrations():
            assert not migration.has_drop_column(), \
                f"Migration {migration.name} drops column. Use deprecation first."

    def test_migration_runtime(self):
        """Migrations must complete in < 5 seconds"""
        for migration in get_pending_migrations():
            runtime = estimate_migration_runtime(migration)
            assert runtime < 5, \
                f"Migration {migration.name} estimated at {runtime}s. Break into smaller migrations."

2️⃣ Architecture Testing

Testing Architectural Characteristics ("-ilities")

CharacteristicFitness FunctionTool
PerformanceResponse time < X ms under Y loadk6, Locust, Artillery
ScalabilityThroughput scales linearly to N nodesCustom load tests
SecurityNo secrets in code, dependencies scannedgit-secrets, Snyk, Trivy
MaintainabilityCyclomatic complexity < 15 per functiongocyclo, radon, eslint
TestabilityCode coverage > 80%pytest, jest, go test
ObservabilityAll services expose /health and /metricsCustom validators
CouplingNo circular dependencies between modulesmadge, import-linter
ModularityPackage cohesion score > thresholdjdepend, structure101

CI/CD Integration

# .github/workflows/architecture-fitness.yml
name: Architecture Fitness

on: [pull_request]

jobs:
  fitness:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      # 1. Dependency direction
      - name: Check Clean Architecture boundaries
        run: |
          pip install import-linter
          lint-imports

      # 2. Cyclomatic complexity
      - name: Check complexity
        run: |
          go install github.com/fzipp/gocyclo@latest
          gocyclo -over 15 ./...

      # 3. No secrets
      - name: Scan for secrets
        uses: trufflesecurity/trufflehog@main
        with:
          path: ./
          base: main

      # 4. API latency (if changes touch API)
      - name: Performance regression test
        if: contains(github.event.pull_request.changed_files, 'api/')
        run: |
          docker-compose up -d
          k6 run --summary-trend-stats="avg,min,med,max,p(95),p(99)" tests/performance/api.js

      # 5. Coverage gate
      - name: Test coverage
        run: |
          go test -coverprofile=coverage.out ./...
          go tool cover -func=coverage.out | grep total | awk '{print $3}' | sed 's/%//' | awk '{if ($1 < 80) exit 1}'

3️⃣ Strangler Fig Pattern

Definition: Gradually replace a legacy system by building new functionality around it, routing traffic incrementally, until the old system is "strangled" and can be removed.

Why Strangler Fig?

ApproachRiskTime
Big Bang RewriteVery HighLong
Strangler FigLowGradual

Implementation Strategy

Phase 1: ROUTE          Phase 2: EXTRACT        Phase 3: STRANGLE
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”        β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”        β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚   Client    β”‚        β”‚   Client    β”‚        β”‚   Client    β”‚
β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”˜        β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”˜        β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”˜
       β”‚                      β”‚                      β”‚
       β–Ό                      β–Ό                      β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”        β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”        β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  Facade/    β”‚        β”‚  Facade/    β”‚        β”‚   New       β”‚
β”‚  Router     β”‚        β”‚  Router     β”‚        β”‚   Service   β”‚
β”‚  (new)      β”‚        β”‚  (new)      β”‚        β”‚  (full)     β”‚
β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”˜        β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”˜        β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
       β”‚                      β”‚
       β–Ό                      β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”        β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚   Legacy    β”‚        β”‚   Legacy    β”‚
β”‚   System    β”‚        β”‚   System    β”‚
β”‚  (monolith) β”‚        β”‚  (partial)  β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜        β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”˜
                              β”‚
                              β–Ό
                        β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                        β”‚   New       β”‚
                        β”‚   Service   β”‚
                        β”‚  (extracted)β”‚
                        β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Routing Strategies

StrategyWhen to UseImplementation
URL-basedDifferent endpoints/api/v2/orders β†’ new, /api/v1/orders β†’ legacy
Feature flagSame endpoint, new featureLaunchDarkly, Unleash: if (flag.enabled) new() else legacy()
CanaryGradual traffic shiftRoute 5% β†’ new, 95% β†’ legacy, increase over time
Data-basedDifferent user segmentsNew users β†’ new system, old users β†’ legacy

Example: Feature Flag Router

type OrderRouter struct {
    legacyService *LegacyOrderService
    newService    *NewOrderService
    flags         FeatureFlagClient
}

func (r *OrderRouter) GetOrder(ctx context.Context, id uuid.UUID) (*Order, error) {
    // Check if this user should use new service
    if r.flags.IsEnabled(ctx, "new-order-service", getUserID(ctx)) {
        return r.newService.GetOrder(ctx, id)
    }
    return r.legacyService.GetOrder(ctx, id)
}

func (r *OrderRouter) CreateOrder(ctx context.Context, cmd CreateOrderCommand) (*Order, error) {
    // All new orders go to new service
    return r.newService.CreateOrder(ctx, cmd)
}

4️⃣ Architectural Dimensions

Identify which dimensions of your architecture need to evolve:

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                    ARCHITECTURAL DIMENSIONS                  β”‚
β”‚                                                              β”‚
β”‚  Technical          Business           Operational          β”‚
β”‚  ─────────          ────────           ───────────          β”‚
β”‚  β€’ Tech stack       β€’ Features         β€’ Scalability        β”‚
β”‚  β€’ Data storage     β€’ Domain model     β€’ Performance        β”‚
β”‚  β€’ Communication    β€’ Business rules   β€’ Security           β”‚
β”‚  β€’ Integration      β€’ Regulations      β€’ Observability      β”‚
β”‚                                                              β”‚
β”‚  Each dimension needs:                                       β”‚
β”‚  1. Current state measurement                                β”‚
β”‚  2. Target state definition                                  β”‚
β”‚  3. Fitness function to guard it                             β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Dimension Example: Scalability

MetricCurrentTargetFitness Function
Orders/second1001000Load test: sustain 1000 orders/sec for 5 min
Database connections50200Monitor: alert at 150 connections
Cache hit rate60%85%Monitor: alert if < 80% for 1 hour

5️⃣ Conway's Law & Team Alignment

"Organizations which design systems are constrained to produce designs which are copies of the communication structures of these organizations." β€” Melvin Conway

Implications

Team StructureArchitecture Result
One big teamMonolith (natural)
Frontend + Backend teamsFrontend/Backend split
Feature teams (cross-functional)Vertical slices, microservices
Platform + Product teamsPlatform + product services

Team Topologies Mapping

Team TypeOwnsArchitecture
Stream-alignedOne business capabilityOne Bounded Context / Service
PlatformInternal tools, infrastructurePlatform services, shared libraries
Complicated SubsystemComplex domain (ML, security)Specialized service
EnablingTemporary expertise injectionNo permanent ownership

🚫 Evolutionary Anti-Patterns

Anti-PatternSymptomFix
Fitness Function TheaterTests exist but never failMake them fail intentionally to verify they work
Ignoring FailuresFitness fails, but PR merges anywayBlock merge on fitness failure
Too Many Dimensions50 fitness functions, team overwhelmedStart with 3-5 most critical
Static ArchitectureNo changes in 6 monthsArchitecture should evolve; stasis is a smell
Wrong CouplingServices chatty across team boundariesReorganize teams or service boundaries
Premature ExtractionMicroservices at 3-person startupStart monolith, extract when pain appears

πŸ“‹ Evolutionary Architecture Checklist

When starting a new project:

  • Identified 3-5 critical architectural dimensions
  • Defined fitness functions for each dimension
  • Integrated fitness functions into CI/CD
  • Chose appropriate coupling (monolith β†’ modular β†’ microservices)
  • Aligned team structure with architecture boundaries
  • Planned strangler fig path for legacy integration (if applicable)
  • Documented architecture decisions in ADRs

πŸ”— Integration with Other Skills

SkillIntegration
c4-modelC4 diagrams show current architecture; fitness functions verify it
ddd-coreBounded Contexts = natural architectural quantum boundaries
architecture-decision-recordsADRs document "why" for each evolutionary step
dora-coreDeployment Frequency + Lead Time = incremental change velocity

πŸ“š References

What ships with it: 1 file

2.7 KB alongside SKILL.md

Keep looking

Skills are one crate of 326,764. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.