Architectural Fitness Functions and Governance: Measuring and Evolving Architecture Quality¶
Objective: Master production-grade architectural fitness functions and governance across distributed systems, databases, ML pipelines, and polyglot microservices. When you need to measure, evaluate, monitor, and evolve architecture quality—this guide provides complete patterns and implementations.
Introduction¶
Architectural fitness functions are measurable, automatable tests that ensure architecture aligns with desired qualities. Unlike unit tests that verify functionality, fitness functions verify architectural characteristics such as modularity, coupling, latency, and domain boundaries. This guide provides a complete framework for implementing continuous architecture governance.
What This Guide Covers: - Architectural characteristics and qualities - Fitness function categories and implementations - Continuous Architecture (CA) discipline - Architecture governance without bureaucracy - Fitness functions for each subsystem - Architecture observability and dashboards - Anti-patterns and architectural debt - End-to-end architectural evolution - Agentic LLM integration for architecture
Prerequisites: - Understanding of software architecture and design patterns - Familiarity with distributed systems and microservices - Experience with CI/CD and automated testing
Architectural Characteristics (The Qualities That Define Good Systems)¶
Modularity¶
Definition: System divided into cohesive, loosely-coupled modules.
Example: Postgres schema modularity
-- Good: Modular schema design
CREATE SCHEMA users;
CREATE SCHEMA orders;
CREATE SCHEMA payments;
-- Each schema is self-contained with clear boundaries
Fitness Function:
# fitness_functions/modularity.py
def test_schema_modularity():
"""Ensure schemas don't have excessive cross-schema dependencies"""
cross_schema_deps = count_cross_schema_dependencies()
assert cross_schema_deps < 10, f"Too many cross-schema dependencies: {cross_schema_deps}"
Cohesion & Coupling¶
Cohesion: Elements within a module work together.
Coupling: Dependencies between modules.
Example: Microservice coupling
# Good: Low coupling
class UserService:
def get_user(self, user_id: str):
# Self-contained, no direct DB access
return self.user_repository.find(user_id)
# Bad: High coupling
class UserService:
def get_user(self, user_id: str):
# Direct database access, tight coupling
return db.execute("SELECT * FROM users WHERE id = %s", user_id)
Fitness Function:
# fitness_functions/coupling.py
def test_service_coupling():
"""Ensure services don't have excessive dependencies"""
dependency_graph = build_dependency_graph()
max_dependencies = max(len(deps) for deps in dependency_graph.values())
assert max_dependencies < 5, f"Service has too many dependencies: {max_dependencies}"
Resilience¶
Definition: System's ability to recover from failures.
Example: Circuit breaker pattern
# Resilience pattern
from circuitbreaker import circuit
@circuit(failure_threshold=5, recovery_timeout=60)
def call_external_service():
"""Resilient service call with circuit breaker"""
return external_service.call()
Fitness Function:
# fitness_functions/resilience.py
def test_circuit_breaker_coverage():
"""Ensure all external calls have circuit breakers"""
external_calls = find_external_service_calls()
protected_calls = find_circuit_breaker_protected_calls()
coverage = len(protected_calls) / len(external_calls)
assert coverage > 0.9, f"Circuit breaker coverage too low: {coverage}"
Observability¶
Definition: Ability to understand system behavior from external outputs.
Example: Structured logging
# Observability pattern
import structlog
logger = structlog.get_logger()
def process_request(request):
logger.info("request_received", request_id=request.id, user_id=request.user_id)
# Process request
logger.info("request_processed", request_id=request.id, duration=duration)
Fitness Function:
# fitness_functions/observability.py
def test_logging_coverage():
"""Ensure critical paths have logging"""
critical_functions = find_critical_functions()
logged_functions = find_logged_functions()
coverage = len(logged_functions) / len(critical_functions)
assert coverage > 0.8, f"Logging coverage too low: {coverage}"
Scalability¶
Definition: System's ability to handle increased load.
Example: Horizontal scaling
# Kubernetes HPA for scalability
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: app-hpa
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: app
minReplicas: 2
maxReplicas: 10
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70
Fitness Function:
# fitness_functions/scalability.py
def test_horizontal_scaling():
"""Ensure services support horizontal scaling"""
deployments = get_kubernetes_deployments()
for deployment in deployments:
assert deployment.replicas >= 2, f"{deployment.name} not horizontally scalable"
assert has_hpa(deployment), f"{deployment.name} missing HPA"
Data Integrity¶
Definition: Data remains accurate and consistent.
Example: Transaction boundaries
# Data integrity pattern
@transactional
def transfer_funds(from_account, to_account, amount):
"""Atomic fund transfer"""
from_account.debit(amount)
to_account.credit(amount)
Fitness Function:
# fitness_functions/data_integrity.py
def test_transaction_coverage():
"""Ensure data modifications are transactional"""
data_modifications = find_data_modifications()
transactional_modifications = find_transactional_modifications()
coverage = len(transactional_modifications) / len(data_modifications)
assert coverage > 0.95, f"Transaction coverage too low: {coverage}"
Domain Isolation¶
Definition: Clear boundaries between business domains.
Example: Bounded contexts
# Domain isolation
class UserDomain:
"""User domain with clear boundaries"""
def create_user(self, user_data):
# User domain logic only
pass
class OrderDomain:
"""Order domain with clear boundaries"""
def create_order(self, order_data):
# Order domain logic only
pass
Fitness Function:
# fitness_functions/domain_isolation.py
def test_domain_boundaries():
"""Ensure domains don't leak into each other"""
user_domain_code = get_domain_code("user")
order_domain_code = get_domain_code("order")
# Check for domain leakage
user_in_order = check_code_references(user_domain_code, order_domain_code)
assert not user_in_order, "Domain boundary violation detected"
Interface Contract Strength¶
Definition: Well-defined, versioned interfaces between components.
Example: API versioning
# Strong interface contract
from pydantic import BaseModel
class UserV1(BaseModel):
id: int
name: str
class UserV2(BaseModel):
id: int
name: str
email: str # Backward compatible addition
Fitness Function:
# fitness_functions/interface_contracts.py
def test_api_versioning():
"""Ensure APIs are versioned"""
api_endpoints = get_api_endpoints()
versioned_endpoints = [ep for ep in api_endpoints if has_version(ep)]
coverage = len(versioned_endpoints) / len(api_endpoints)
assert coverage > 0.9, f"API versioning coverage too low: {coverage}"
Latency Paths & Tail Tolerance¶
Definition: System handles latency spikes gracefully.
Example: Timeout and retry
# Latency tolerance
from tenacity import retry, stop_after_attempt, wait_exponential
@retry(stop=stop_after_attempt(3), wait=wait_exponential(multiplier=1, min=4, max=10))
def call_service_with_retry():
"""Service call with exponential backoff"""
return service.call()
Fitness Function:
# fitness_functions/latency.py
def test_p95_latency():
"""Ensure P95 latency is within SLA"""
latency_metrics = get_latency_metrics()
p95_latency = calculate_percentile(latency_metrics, 95)
assert p95_latency < 500, f"P95 latency too high: {p95_latency}ms"
Time-Governance Architecture¶
Definition: Consistent time handling across system.
Example: NTP synchronization
# Time governance
from datetime import datetime
import ntplib
def get_synchronized_time():
"""Get NTP-synchronized time"""
ntp_client = ntplib.NTPClient()
response = ntp_client.request('pool.ntp.org')
return datetime.fromtimestamp(response.tx_time)
Fitness Function:
# fitness_functions/time_governance.py
def test_time_synchronization():
"""Ensure all nodes are time-synchronized"""
nodes = get_cluster_nodes()
for node in nodes:
time_skew = get_time_skew(node)
assert time_skew < 0.1, f"Node {node} time skew too high: {time_skew}s"
Predictability¶
Definition: System behavior is consistent and deterministic.
Example: Idempotent operations
# Predictable, idempotent operation
def create_user(user_id: str, user_data: dict):
"""Idempotent user creation"""
if user_exists(user_id):
return get_user(user_id)
return create_new_user(user_id, user_data)
Fitness Function:
# fitness_functions/predictability.py
def test_idempotency():
"""Ensure critical operations are idempotent"""
critical_operations = find_critical_operations()
idempotent_operations = find_idempotent_operations()
coverage = len(idempotent_operations) / len(critical_operations)
assert coverage > 0.8, f"Idempotency coverage too low: {coverage}"
Component Autonomy¶
Definition: Components can operate independently.
Example: Stateless services
# Autonomous, stateless service
class StatelessService:
def process_request(self, request):
# No shared state, fully autonomous
return self.process(request)
Fitness Function:
# fitness_functions/autonomy.py
def test_stateless_services():
"""Ensure services are stateless"""
services = get_services()
for service in services:
assert is_stateless(service), f"Service {service.name} is not stateless"
Complexity Management¶
Definition: System complexity is controlled and measurable.
Example: Cyclomatic complexity limits
# Complexity management
def simple_function(data):
"""Low complexity function"""
if data:
return process(data)
return None
# Bad: High complexity
def complex_function(data):
"""High complexity function - should be refactored"""
if data:
if data.type == "A":
if data.value > 10:
# ... many nested conditions
pass
Fitness Function:
# fitness_functions/complexity.py
def test_cyclomatic_complexity():
"""Ensure functions don't exceed complexity threshold"""
functions = get_all_functions()
for func in functions:
complexity = calculate_cyclomatic_complexity(func)
assert complexity < 10, f"Function {func.name} too complex: {complexity}"
Architectural Fitness Functions¶
What Are Fitness Functions?¶
Fitness Function: A measurable, automatable test that ensures architecture aligns with desired qualities.
Key Properties: - Measurable: Produces quantitative results - Automatable: Can run in CI/CD - Architectural: Tests architecture, not functionality - Evolutionary: Enables architecture to evolve safely
Structural Fitness Functions¶
Purpose: Verify architectural structure and boundaries.
Example: Boundary Integrity:
# fitness_functions/structural/boundary_integrity.py
def test_layer_boundaries():
"""Ensure layers don't violate boundaries"""
# Presentation layer should not import from data layer
presentation_imports = get_imports("presentation")
data_layer_imports = [imp for imp in presentation_imports if "data" in imp]
assert len(data_layer_imports) == 0, f"Boundary violation: {data_layer_imports}"
Example: Module Dependency Limits:
# fitness_functions/structural/dependency_limits.py
def test_module_dependencies():
"""Ensure modules don't have excessive dependencies"""
modules = get_modules()
for module in modules:
dependencies = get_dependencies(module)
assert len(dependencies) < 10, f"Module {module} has too many dependencies: {len(dependencies)}"
Behavioral Fitness Functions¶
Purpose: Verify system behavior and performance.
Example: Latency Ceilings:
# fitness_functions/behavioral/latency.py
def test_api_latency():
"""Ensure API latency is within SLA"""
endpoints = get_api_endpoints()
for endpoint in endpoints:
latency = measure_latency(endpoint)
assert latency.p95 < 500, f"Endpoint {endpoint} P95 latency too high: {latency.p95}ms"
Example: Throughput Floors:
# fitness_functions/behavioral/throughput.py
def test_throughput():
"""Ensure system meets minimum throughput"""
throughput = measure_throughput()
assert throughput > 1000, f"Throughput too low: {throughput} req/s"
Example: Tail-Latency Guarantees:
# fitness_functions/behavioral/tail_latency.py
def test_tail_latency():
"""Ensure P99 latency is acceptable"""
latency_metrics = get_latency_metrics()
p99_latency = calculate_percentile(latency_metrics, 99)
assert p99_latency < 1000, f"P99 latency too high: {p99_latency}ms"
Data Fitness Functions¶
Purpose: Verify data quality and integrity.
Example: Schema Drift Detection:
# fitness_functions/data/schema_drift.py
def test_schema_consistency():
"""Ensure schemas don't drift"""
expected_schema = load_expected_schema()
actual_schema = get_actual_schema()
drift = calculate_schema_drift(expected_schema, actual_schema)
assert drift < 0.1, f"Schema drift detected: {drift}"
Example: Data Quality:
# fitness_functions/data/quality.py
def test_data_quality():
"""Ensure data meets quality standards"""
data = load_data()
# Check null rates
null_rates = calculate_null_rates(data)
for column, rate in null_rates.items():
assert rate < 0.05, f"Column {column} has too many nulls: {rate}"
# Check value ranges
ranges = get_expected_ranges()
for column, expected_range in ranges.items():
actual_range = get_actual_range(data[column])
assert actual_range.within(expected_range), f"Column {column} out of range"
Security Fitness Functions¶
Purpose: Verify security posture.
Example: Dependency Scanning:
# fitness_functions/security/dependencies.py
def test_dependency_vulnerabilities():
"""Ensure no known vulnerabilities in dependencies"""
vulnerabilities = scan_dependencies()
critical_vulns = [v for v in vulnerabilities if v.severity == "critical"]
assert len(critical_vulns) == 0, f"Critical vulnerabilities found: {critical_vulns}"
Example: Secret Detection:
# fitness_functions/security/secrets.py
def test_secret_exposure():
"""Ensure no secrets in code"""
secrets = scan_for_secrets()
assert len(secrets) == 0, f"Secrets found in code: {secrets}"
Resilience Fitness Functions¶
Purpose: Verify system resilience.
Example: Circuit Breaker Coverage:
# fitness_functions/resilience/circuit_breakers.py
def test_circuit_breaker_coverage():
"""Ensure external calls have circuit breakers"""
external_calls = find_external_calls()
protected_calls = find_circuit_breaker_protected_calls()
coverage = len(protected_calls) / len(external_calls)
assert coverage > 0.9, f"Circuit breaker coverage too low: {coverage}"
Example: Retry Logic:
# fitness_functions/resilience/retry.py
def test_retry_coverage():
"""Ensure transient failures have retry logic"""
external_calls = find_external_calls()
retry_protected = find_retry_protected_calls()
coverage = len(retry_protected) / len(external_calls)
assert coverage > 0.8, f"Retry coverage too low: {coverage}"
ML Reproducibility Fitness Functions¶
Purpose: Verify ML model reproducibility.
Example: Model Signature Validation:
# fitness_functions/ml/reproducibility.py
def test_model_signature_consistency():
"""Ensure model signatures are consistent"""
model_versions = get_model_versions()
for version in model_versions:
signature = get_model_signature(version)
expected_signature = get_expected_signature()
assert signature == expected_signature, f"Model {version} signature mismatch"
Example: Feature Parity:
# fitness_functions/ml/feature_parity.py
def test_feature_parity():
"""Ensure training and inference features match"""
training_features = get_training_features()
inference_features = get_inference_features()
assert set(training_features) == set(inference_features), "Feature mismatch"
Geospatial Consistency Fitness Functions¶
Purpose: Verify geospatial data consistency.
Example: CRS Consistency:
# fitness_functions/geospatial/crs_consistency.py
def test_crs_consistency():
"""Ensure all geometries use consistent CRS"""
geometries = get_geometries()
crs_counts = count_crs(geometries)
# Should have one dominant CRS
dominant_crs_ratio = max(crs_counts.values()) / sum(crs_counts.values())
assert dominant_crs_ratio > 0.95, f"CRS inconsistency: {crs_counts}"
Example: Geometry Validity:
# fitness_functions/geospatial/validity.py
def test_geometry_validity():
"""Ensure all geometries are valid"""
geometries = get_geometries()
invalid = [g for g in geometries if not g.is_valid]
invalid_ratio = len(invalid) / len(geometries)
assert invalid_ratio < 0.01, f"Too many invalid geometries: {invalid_ratio}"
API Stability Fitness Functions¶
Purpose: Verify API contract stability.
Example: Breaking Change Detection:
# fitness_functions/api/stability.py
def test_api_breaking_changes():
"""Ensure no breaking API changes"""
current_api = get_current_api_schema()
previous_api = get_previous_api_schema()
breaking_changes = detect_breaking_changes(current_api, previous_api)
assert len(breaking_changes) == 0, f"Breaking changes detected: {breaking_changes}"
Example: Version Compatibility:
# fitness_functions/api/versioning.py
def test_api_versioning():
"""Ensure APIs are properly versioned"""
endpoints = get_api_endpoints()
versioned_endpoints = [ep for ep in endpoints if has_version(ep)]
coverage = len(versioned_endpoints) / len(endpoints)
assert coverage > 0.9, f"API versioning coverage too low: {coverage}"
Governance Fitness Functions¶
Purpose: Verify architectural governance.
Example: ADR Consistency:
# fitness_functions/governance/adr.py
def test_adr_consistency():
"""Ensure ADRs are consistent with implementation"""
adrs = load_adrs()
implementations = get_implementations()
for adr in adrs:
implementation = find_implementation(adr)
assert implementation.matches(adr), f"ADR {adr.id} not consistent with implementation"
Example: Versioning Discipline:
# fitness_functions/governance/versioning.py
def test_versioning_discipline():
"""Ensure all components are versioned"""
components = get_components()
versioned_components = [c for c in components if has_version(c)]
coverage = len(versioned_components) / len(components)
assert coverage > 0.95, f"Versioning coverage too low: {coverage}"
Example: Repo Structure Consistency:
# fitness_functions/governance/repo_structure.py
def test_repo_structure():
"""Ensure repos follow standard structure"""
repos = get_repos()
for repo in repos:
structure = get_repo_structure(repo)
expected_structure = get_standard_structure()
drift = calculate_structure_drift(structure, expected_structure)
assert drift < 0.1, f"Repo {repo} structure drift: {drift}"
Continuous Architecture (CA) Overview¶
Architecture as Continuously Validated Asset¶
Principle: Architecture is not a one-time design, but a continuously evolving, validated asset.
Practice: - Fitness functions run in CI/CD - Architecture metrics tracked over time - Architectural decisions validated continuously - Drift detected and remediated automatically
Small, Iterative Architectural Experiments¶
Principle: Make small architectural changes, measure impact, iterate.
Practice: - Feature flags for architectural changes - A/B testing architectural patterns - Gradual migration strategies - Rollback capabilities
Architecture Measurement in CI/CD¶
Integration:
# .github/workflows/architecture-fitness.yml
name: Architecture Fitness
on: [push, pull_request]
jobs:
fitness:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Run Fitness Functions
run: |
pytest fitness_functions/
- name: Generate Architecture Report
run: |
python scripts/generate_architecture_report.py
Architectural Drift Detection¶
Drift Types: - Structural Drift: Architecture diverges from intended design - Behavioral Drift: Performance characteristics degrade - Governance Drift: Policies not followed
Detection:
# drift_detection/architectural_drift.py
class ArchitecturalDriftDetector:
def detect_drift(self, baseline: dict, current: dict) -> dict:
"""Detect architectural drift"""
drift = {
'structural': self.detect_structural_drift(baseline, current),
'behavioral': self.detect_behavioral_drift(baseline, current),
'governance': self.detect_governance_drift(baseline, current)
}
return drift
Architectural Technical Debt Tracking¶
Debt Categories: - Structural Debt: Poor modularity, high coupling - Performance Debt: Latency issues, scalability problems - Security Debt: Vulnerabilities, weak security posture - Governance Debt: Missing ADRs, inconsistent patterns
Tracking:
# debt_tracking/architectural_debt.py
class ArchitecturalDebtTracker:
def calculate_debt(self) -> dict:
"""Calculate architectural technical debt"""
return {
'structural': self.calculate_structural_debt(),
'performance': self.calculate_performance_debt(),
'security': self.calculate_security_debt(),
'governance': self.calculate_governance_debt()
}
Evolutionary Adaptation¶
Principle: Architecture evolves based on fitness function feedback.
Process: 1. Measure current architecture 2. Identify improvement opportunities 3. Make small changes 4. Measure impact 5. Iterate
Architecture Governance Without Bureaucracy¶
Architectural Scorecards¶
Scorecard Template:
# scorecards/architecture_scorecard.yaml
architecture_scorecard:
component: "user-service"
date: "2024-01-15"
metrics:
modularity: 8.5
coupling: 7.0
cohesion: 9.0
resilience: 8.0
observability: 7.5
scalability: 8.0
fitness_functions:
- name: "boundary_integrity"
status: "pass"
score: 9.0
- name: "latency_p95"
status: "pass"
score: 8.5
recommendations:
- "Reduce coupling with order-service"
- "Add circuit breakers for external calls"
Component Maturity Ratings¶
Maturity Levels: - Level 1 (Initial): Ad-hoc, no standards - Level 2 (Managed): Some standards, inconsistent - Level 3 (Defined): Standards defined, followed - Level 4 (Quantitatively Managed): Metrics-driven - Level 5 (Optimizing): Continuous improvement
Rating:
# governance/maturity_rating.py
class ComponentMaturityRater:
def rate_component(self, component: str) -> int:
"""Rate component maturity"""
scores = {
'standards': self.assess_standards(component),
'metrics': self.assess_metrics(component),
'automation': self.assess_automation(component),
'documentation': self.assess_documentation(component)
}
average_score = sum(scores.values()) / len(scores)
return int(average_score) # 1-5 scale
Quality Attribute Acceptance Criteria (QAAC)¶
QAAC Template:
# qaac/quality_attributes.yaml
quality_attributes:
availability:
target: 99.9%
measurement: "Uptime percentage"
acceptance_criteria:
- "Service available 99.9% of time"
- "Automatic failover within 30 seconds"
latency:
target: "P95 < 500ms"
measurement: "95th percentile response time"
acceptance_criteria:
- "P95 latency < 500ms"
- "P99 latency < 1000ms"
scalability:
target: "Handle 10x load increase"
measurement: "Throughput under load"
acceptance_criteria:
- "System handles 10x load with < 2x resources"
- "No degradation in latency"
Standard Architecture Review Cadence¶
Review Schedule: - Weekly: Fitness function results review - Monthly: Architecture scorecard review - Quarterly: Comprehensive architecture review - Annually: Architecture strategy review
Review Process: 1. Collect metrics 2. Analyze trends 3. Identify issues 4. Propose improvements 5. Track action items
Golden Paths / Paved Roads¶
Definition: Standard, well-supported architectural patterns.
Example:
# golden_paths/api_service.yaml
golden_path:
name: "API Service"
description: "Standard pattern for API services"
components:
- "FastAPI framework"
- "Pydantic validation"
- "Structured logging"
- "Prometheus metrics"
- "Circuit breakers"
fitness_functions:
- "test_api_versioning"
- "test_latency_p95"
- "test_circuit_breaker_coverage"
templates:
- "api-service-template"
Architectural Guardrails¶
Guardrails: Automated enforcement of architectural rules.
Example:
# guardrails/architectural_guardrails.py
class ArchitecturalGuardrails:
def enforce_guardrails(self, change: dict) -> bool:
"""Enforce architectural guardrails"""
# Check layer boundaries
if not self.check_layer_boundaries(change):
return False
# Check dependency limits
if not self.check_dependency_limits(change):
return False
# Check complexity limits
if not self.check_complexity_limits(change):
return False
return True
Architecture KPIs¶
Data Pipelines: - Schema drift rate - Data quality score - Pipeline latency - Failure rate
Geospatial Processing: - Geometry validity rate - CRS consistency - Processing latency - Tile generation time
Postgres Clusters: - Replication lag - Query performance - Connection pool utilization - WAL growth rate
UI Architecture: - Component reusability - Bundle size - Load time - User interaction latency
Lakehouse Ingestion: - Ingestion latency - Parquet file quality - Metadata consistency - Query performance
ML Reproducibility: - Model signature consistency - Feature parity - Inference latency - Prediction accuracy
Creating Fitness Functions for This Ecosystem¶
Postgres Fitness Functions¶
Table Count Limits:
# fitness_functions/postgres/table_count.py
def test_schema_table_count():
"""Ensure schemas don't have excessive tables"""
schemas = get_postgres_schemas()
for schema in schemas:
table_count = count_tables(schema)
assert table_count < 50, f"Schema {schema} has too many tables: {table_count}"
Relationship Density:
# fitness_functions/postgres/relationship_density.py
def test_relationship_density():
"""Ensure relationship density is reasonable"""
tables = get_postgres_tables()
for table in tables:
relationships = count_relationships(table)
density = relationships / count_columns(table)
assert density < 0.5, f"Table {table} relationship density too high: {density}"
WAL Growth Ceilings:
# fitness_functions/postgres/wal_growth.py
def test_wal_growth():
"""Ensure WAL growth is within limits"""
wal_size = get_wal_size()
wal_growth_rate = get_wal_growth_rate()
assert wal_size < 100 * 1024 * 1024 * 1024, f"WAL size too large: {wal_size}"
assert wal_growth_rate < 1 * 1024 * 1024 * 1024, f"WAL growth rate too high: {wal_growth_rate}"
Geospatial Index Quality:
# fitness_functions/postgres/geospatial_index.py
def test_geospatial_index_quality():
"""Ensure geospatial indexes are effective"""
spatial_tables = get_spatial_tables()
for table in spatial_tables:
index_usage = get_index_usage(table)
assert index_usage > 0.8, f"Table {table} geospatial index usage too low: {index_usage}"
Kubernetes Fitness Functions¶
Pod Start Time SLA:
# fitness_functions/kubernetes/pod_startup.py
def test_pod_startup_time():
"""Ensure pods start within SLA"""
pods = get_kubernetes_pods()
for pod in pods:
startup_time = measure_pod_startup_time(pod)
assert startup_time < 30, f"Pod {pod.name} startup time too high: {startup_time}s"
Service Dependency Graph Constraints:
# fitness_functions/kubernetes/dependency_graph.py
def test_service_dependencies():
"""Ensure service dependency graph is acyclic"""
dependency_graph = build_service_dependency_graph()
cycles = detect_cycles(dependency_graph)
assert len(cycles) == 0, f"Cyclic dependencies detected: {cycles}"
Maximum Hop Count:
# fitness_functions/kubernetes/hop_count.py
def test_interservice_hop_count():
"""Ensure interservice calls don't exceed hop limit"""
service_calls = trace_service_calls()
for call in service_calls:
hop_count = count_hops(call)
assert hop_count < 5, f"Service call {call} has too many hops: {hop_count}"
Redis Fitness Functions¶
Stream Lag Thresholds:
# fitness_functions/redis/stream_lag.py
def test_stream_lag():
"""Ensure Redis stream lag is within limits"""
streams = get_redis_streams()
for stream in streams:
lag = get_stream_lag(stream)
assert lag < 1000, f"Stream {stream} lag too high: {lag} messages"
Memory Fragmentation:
# fitness_functions/redis/memory_fragmentation.py
def test_memory_fragmentation():
"""Ensure memory fragmentation is acceptable"""
fragmentation = get_redis_memory_fragmentation()
assert fragmentation < 1.5, f"Memory fragmentation too high: {fragmentation}"
NiceGUI Fitness Functions¶
UI Input → Backend Latency:
# fitness_functions/nicegui/latency.py
def test_ui_backend_latency():
"""Ensure UI to backend latency is acceptable"""
ui_actions = get_ui_actions()
for action in ui_actions:
latency = measure_ui_backend_latency(action)
assert latency < 200, f"UI action {action} latency too high: {latency}ms"
Component Coupling Limits:
# fitness_functions/nicegui/coupling.py
def test_component_coupling():
"""Ensure UI components aren't overly coupled"""
components = get_nicegui_components()
for component in components:
dependencies = get_component_dependencies(component)
assert len(dependencies) < 5, f"Component {component} has too many dependencies: {len(dependencies)}"
ML Inference Fitness Functions¶
Model Load Time:
# fitness_functions/ml/load_time.py
def test_model_load_time():
"""Ensure model load time is acceptable"""
models = get_ml_models()
for model in models:
load_time = measure_model_load_time(model)
assert load_time < 5, f"Model {model} load time too high: {load_time}s"
ONNX Shape Mismatch Detection:
# fitness_functions/ml/onnx_shape.py
def test_onnx_shape_consistency():
"""Ensure ONNX model shapes are consistent"""
models = get_onnx_models()
for model in models:
input_shape = get_model_input_shape(model)
expected_shape = get_expected_input_shape(model)
assert input_shape == expected_shape, f"Model {model} shape mismatch"
Reproducibility Confidence:
# fitness_functions/ml/reproducibility.py
def test_ml_reproducibility():
"""Ensure ML models are reproducible"""
models = get_ml_models()
for model in models:
reproducibility_score = calculate_reproducibility_score(model)
assert reproducibility_score > 0.95, f"Model {model} reproducibility too low: {reproducibility_score}"
Data Pipeline Fitness Functions¶
Schema Drift Fences:
# fitness_functions/pipelines/schema_drift.py
def test_schema_drift():
"""Ensure schemas don't drift beyond acceptable limits"""
pipelines = get_data_pipelines()
for pipeline in pipelines:
drift = calculate_schema_drift(pipeline)
assert drift < 0.1, f"Pipeline {pipeline} schema drift too high: {drift}"
Transformation Idempotency:
# fitness_functions/pipelines/idempotency.py
def test_transformation_idempotency():
"""Ensure transformations are idempotent"""
transformations = get_transformations()
for transformation in transformations:
is_idempotent = test_idempotency(transformation)
assert is_idempotent, f"Transformation {transformation} is not idempotent"
Lakehouse Fitness Functions¶
Parquet Row-Group Consistency:
# fitness_functions/lakehouse/row_group_consistency.py
def test_parquet_row_group_consistency():
"""Ensure Parquet row groups are consistent"""
parquet_files = get_parquet_files()
for file in parquet_files:
row_groups = get_row_groups(file)
schemas = [get_row_group_schema(rg) for rg in row_groups]
# All row groups should have same schema
assert all(s == schemas[0] for s in schemas), f"File {file} has inconsistent row group schemas"
Metadata Evolutionary Locks:
# fitness_functions/lakehouse/metadata_locks.py
def test_metadata_evolution():
"""Ensure metadata evolution is backward compatible"""
metadata_versions = get_metadata_versions()
for i in range(1, len(metadata_versions)):
current = metadata_versions[i]
previous = metadata_versions[i-1]
assert is_backward_compatible(current, previous), f"Metadata version {i} not backward compatible"
Architecture Observability¶
Architecture Dashboards¶
Dashboard Components: - Fitness function results - Architecture metrics trends - Component maturity scores - Technical debt levels - Drift indicators
Example Dashboard:
{
"dashboard": {
"title": "Architecture Health",
"panels": [
{
"title": "Fitness Function Pass Rate",
"targets": [
{
"expr": "fitness_function_pass_rate",
"legendFormat": "{{category}}"
}
]
},
{
"title": "Architectural Debt",
"targets": [
{
"expr": "architectural_debt_score",
"legendFormat": "{{component}}"
}
]
},
{
"title": "Component Maturity",
"targets": [
{
"expr": "component_maturity_score",
"legendFormat": "{{component}}"
}
]
}
]
}
}
Architecture Heat Maps¶
Heat Map Types: - Coupling Heat Map: Shows coupling between components - Complexity Heat Map: Shows complexity distribution - Debt Heat Map: Shows technical debt concentration
Example:
# observability/heat_maps.py
class ArchitectureHeatMap:
def generate_coupling_heatmap(self):
"""Generate coupling heat map"""
components = get_components()
coupling_matrix = build_coupling_matrix(components)
# Visualize as heat map
import matplotlib.pyplot as plt
plt.imshow(coupling_matrix, cmap='hot', interpolation='nearest')
plt.colorbar()
plt.title('Component Coupling Heat Map')
plt.show()
Dependency Graph Monitoring¶
Monitoring:
graph TB
subgraph Services["Services"]
S1["Service 1"]
S2["Service 2"]
S3["Service 3"]
S4["Service 4"]
end
subgraph Databases["Databases"]
DB1["Postgres"]
DB2["Redis"]
end
S1 --> S2
S2 --> S3
S3 --> S4
S1 --> DB1
S2 --> DB2
S3 --> DB1
style Services fill:#e1f5ff
style Databases fill:#fff4e1 Monitoring Code:
# observability/dependency_graph.py
class DependencyGraphMonitor:
def monitor_dependencies(self):
"""Monitor dependency graph for changes"""
current_graph = build_dependency_graph()
baseline_graph = load_baseline_graph()
changes = detect_graph_changes(current_graph, baseline_graph)
if changes:
alert_on_dependency_changes(changes)
Complexity Growth Over Time¶
Tracking:
# observability/complexity_tracking.py
class ComplexityTracker:
def track_complexity(self):
"""Track complexity over time"""
complexity_metrics = {
'cyclomatic': calculate_cyclomatic_complexity(),
'coupling': calculate_coupling(),
'cohesion': calculate_cohesion(),
'lines_of_code': count_lines_of_code()
}
store_complexity_metrics(complexity_metrics)
plot_complexity_trends(complexity_metrics)
Drift from Intended Domain Boundaries¶
Detection:
# observability/domain_drift.py
class DomainDriftDetector:
def detect_domain_drift(self):
"""Detect drift from intended domain boundaries"""
intended_boundaries = load_intended_boundaries()
actual_boundaries = detect_actual_boundaries()
drift = calculate_boundary_drift(intended_boundaries, actual_boundaries)
if drift > threshold:
alert_on_domain_drift(drift)
Architecture Health Scoring Models¶
Health Score Calculation:
# observability/health_scoring.py
class ArchitectureHealthScorer:
def calculate_health_score(self, component: str) -> float:
"""Calculate architecture health score"""
metrics = {
'modularity': self.measure_modularity(component),
'coupling': self.measure_coupling(component),
'cohesion': self.measure_cohesion(component),
'resilience': self.measure_resilience(component),
'observability': self.measure_observability(component)
}
# Weighted average
weights = {
'modularity': 0.2,
'coupling': 0.2,
'cohesion': 0.2,
'resilience': 0.2,
'observability': 0.2
}
health_score = sum(metrics[key] * weights[key] for key in metrics)
return health_score
Anti-Patterns¶
Big Ball of Mud¶
Symptom: No clear structure, everything depends on everything.
Detection:
# anti_patterns/big_ball_of_mud.py
def detect_big_ball_of_mud():
"""Detect Big Ball of Mud anti-pattern"""
dependency_graph = build_dependency_graph()
# Check for high average coupling
avg_coupling = calculate_average_coupling(dependency_graph)
if avg_coupling > 0.8:
return True, "High average coupling indicates Big Ball of Mud"
return False, None
Fix: Refactor into bounded contexts with clear boundaries.
Invisible Architecture¶
Symptom: Architecture not documented or visible.
Detection:
# anti_patterns/invisible_architecture.py
def detect_invisible_architecture():
"""Detect invisible architecture anti-pattern"""
adr_count = count_adrs()
component_count = count_components()
if adr_count / component_count < 0.5:
return True, "Low ADR coverage indicates invisible architecture"
return False, None
Fix: Document architecture with ADRs and diagrams.
Overcoupled Geospatial Pipelines¶
Symptom: Geospatial pipelines tightly coupled to specific formats or systems.
Detection:
# anti_patterns/geospatial_coupling.py
def detect_overcoupled_geospatial():
"""Detect overcoupled geospatial pipelines"""
pipelines = get_geospatial_pipelines()
for pipeline in pipelines:
dependencies = get_pipeline_dependencies(pipeline)
if len(dependencies) > 10:
return True, f"Pipeline {pipeline} has too many dependencies"
return False, None
Fix: Introduce abstraction layers and interfaces.
Monolithic Postgres Schemas¶
Symptom: Single schema with hundreds of tables.
Detection:
# anti_patterns/monolithic_schema.py
def detect_monolithic_schema():
"""Detect monolithic Postgres schema"""
schemas = get_postgres_schemas()
for schema in schemas:
table_count = count_tables(schema)
if table_count > 50:
return True, f"Schema {schema} is monolithic: {table_count} tables"
return False, None
Fix: Split into domain-specific schemas.
MLflow Artifact Sprawl¶
Symptom: Thousands of unorganized MLflow artifacts.
Detection:
# anti_patterns/mlflow_sprawl.py
def detect_mlflow_sprawl():
"""Detect MLflow artifact sprawl"""
artifacts = get_mlflow_artifacts()
organized_artifacts = count_organized_artifacts(artifacts)
organization_ratio = organized_artifacts / len(artifacts)
if organization_ratio < 0.7:
return True, f"Low artifact organization: {organization_ratio}"
return False, None
Fix: Implement artifact organization and cleanup policies.
Multi-Layer Cyclic Dependencies¶
Symptom: Circular dependencies across layers.
Detection:
# anti_patterns/cyclic_dependencies.py
def detect_cyclic_dependencies():
"""Detect cyclic dependencies"""
dependency_graph = build_dependency_graph()
cycles = detect_cycles(dependency_graph)
if len(cycles) > 0:
return True, f"Cyclic dependencies detected: {cycles}"
return False, None
Fix: Break cycles by introducing interfaces or dependency inversion.
UI → DB Direct Coupling¶
Symptom: UI directly accesses database.
Detection:
# anti_patterns/ui_db_coupling.py
def detect_ui_db_coupling():
"""Detect UI to DB direct coupling"""
ui_components = get_ui_components()
for component in ui_components:
if has_direct_db_access(component):
return True, f"UI component {component} directly accesses DB"
return False, None
Fix: Introduce API layer between UI and database.
Distributed Monolith¶
Symptom: Microservices that are tightly coupled like a monolith.
Detection:
# anti_patterns/distributed_monolith.py
def detect_distributed_monolith():
"""Detect distributed monolith anti-pattern"""
services = get_microservices()
dependency_graph = build_service_dependency_graph()
avg_dependencies = calculate_average_dependencies(dependency_graph)
if avg_dependencies > 5:
return True, f"High service coupling indicates distributed monolith"
return False, None
Fix: Establish clear service boundaries and reduce coupling.
Hard-Coded Spatial Assumptions¶
Symptom: Spatial logic hard-coded instead of configurable.
Detection:
# anti_patterns/hard_coded_spatial.py
def detect_hard_coded_spatial():
"""Detect hard-coded spatial assumptions"""
code = get_codebase()
hard_coded_crs = find_hard_coded_crs(code)
hard_coded_bounds = find_hard_coded_bounds(code)
if len(hard_coded_crs) > 0 or len(hard_coded_bounds) > 0:
return True, "Hard-coded spatial assumptions detected"
return False, None
Fix: Move spatial configuration to config files or environment variables.
Versionless Domain Contracts¶
Symptom: Domain contracts without versioning.
Detection:
# anti_patterns/versionless_contracts.py
def detect_versionless_contracts():
"""Detect versionless domain contracts"""
contracts = get_domain_contracts()
versioned_contracts = [c for c in contracts if has_version(c)]
coverage = len(versioned_contracts) / len(contracts)
if coverage < 0.8:
return True, f"Low contract versioning coverage: {coverage}"
return False, None
Fix: Implement contract versioning and compatibility checks.
End-to-End Architectural Scenario Walkthrough¶
Writing Fitness Functions¶
Example: Complete Fitness Function:
# fitness_functions/complete_example.py
import pytest
from architecture_metrics import ArchitectureMetrics
class TestServiceArchitecture:
def test_boundary_integrity(self):
"""Ensure service boundaries are maintained"""
service_code = get_service_code("user-service")
# Check for direct database access
db_imports = find_imports(service_code, "psycopg", "sqlalchemy")
assert len(db_imports) == 0, "Service directly accesses database"
# Check for UI dependencies
ui_imports = find_imports(service_code, "nicegui", "react")
assert len(ui_imports) == 0, "Service depends on UI components"
def test_latency_sla(self):
"""Ensure service meets latency SLA"""
metrics = ArchitectureMetrics()
p95_latency = metrics.get_p95_latency("user-service")
assert p95_latency < 500, f"P95 latency {p95_latency}ms exceeds SLA"
def test_circuit_breaker_coverage(self):
"""Ensure external calls have circuit breakers"""
external_calls = find_external_calls("user-service")
protected_calls = find_circuit_breaker_protected_calls("user-service")
coverage = len(protected_calls) / len(external_calls) if external_calls else 1.0
assert coverage > 0.9, f"Circuit breaker coverage {coverage} too low"
Integrating into CI/CD¶
GitHub Actions Integration:
# .github/workflows/architecture-fitness.yml
name: Architecture Fitness Functions
on:
push:
branches: [main, develop]
pull_request:
branches: [main, develop]
jobs:
architecture-fitness:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: '3.11'
- name: Install dependencies
run: |
pip install -r requirements.txt
pip install pytest architecture-metrics
- name: Run fitness functions
run: |
pytest fitness_functions/ -v
- name: Generate architecture report
run: |
python scripts/generate_architecture_report.py
- name: Upload architecture report
uses: actions/upload-artifact@v3
with:
name: architecture-report
path: architecture-report.html
Measuring Architecture Drift Quarterly¶
Quarterly Drift Measurement:
# drift_measurement/quarterly_drift.py
class QuarterlyDriftMeasurement:
def measure_drift(self):
"""Measure architecture drift quarterly"""
baseline = load_baseline_architecture()
current = capture_current_architecture()
drift_report = {
'structural_drift': self.measure_structural_drift(baseline, current),
'behavioral_drift': self.measure_behavioral_drift(baseline, current),
'governance_drift': self.measure_governance_drift(baseline, current),
'recommendations': self.generate_recommendations(baseline, current)
}
save_drift_report(drift_report)
return drift_report
Evolving Architecture Intentionally¶
Evolution Process:
graph LR
Measure["Measure<br/>Current State"]
Identify["Identify<br/>Improvements"]
Design["Design<br/>Changes"]
Implement["Implement<br/>Changes"]
Validate["Validate<br/>with Fitness Functions"]
Deploy["Deploy"]
Measure --> Identify
Identify --> Design
Design --> Implement
Implement --> Validate
Validate --> Deploy
Deploy --> Measure
style Measure fill:#e1f5ff
style Identify fill:#fff4e1
style Design fill:#e8f5e9
style Implement fill:#f3e5f5
style Validate fill:#ffebee
style Deploy fill:#e1f5ff Rejecting Harmful Changes Early¶
Pre-Commit Hooks:
# pre_commit/architecture_guardrails.py
def pre_commit_architecture_check():
"""Reject harmful architectural changes"""
changes = get_staged_changes()
# Check for boundary violations
if violates_boundaries(changes):
print("ERROR: Boundary violation detected")
return False
# Check for dependency violations
if violates_dependency_rules(changes):
print("ERROR: Dependency rule violation")
return False
# Check for complexity increases
if increases_complexity(changes):
print("WARNING: Complexity increase detected")
# Allow but warn
return True
Architecture "Fails Safely"¶
Fail-Safe Patterns:
# fail_safe/architecture_failures.py
class ArchitectureFailSafe:
def handle_architecture_failure(self, failure: dict):
"""Handle architecture failure safely"""
# Log failure
log_architecture_failure(failure)
# Alert team
alert_architecture_team(failure)
# Attempt automatic remediation
if can_remediate_automatically(failure):
remediate(failure)
else:
# Escalate to manual intervention
escalate_to_manual(failure)
Agentic LLM Hooks¶
Automatically Generating Fitness Functions¶
LLM Fitness Function Generation:
# llm/fitness_function_generator.py
class LLMFitnessFunctionGenerator:
def generate_fitness_function(self, quality_attribute: str, component: str) -> str:
"""Generate fitness function using LLM"""
prompt = f"""
Generate a fitness function for {quality_attribute} in {component}.
Requirements:
1. Measurable and automatable
2. Tests architectural quality, not functionality
3. Includes assertions with thresholds
4. Can run in CI/CD
Provide Python code with pytest.
"""
response = self.llm_client.chat.completions.create(
model="gpt-4",
messages=[
{"role": "system", "content": "You are an architecture fitness function expert."},
{"role": "user", "content": prompt}
]
)
return response.choices[0].message.content
Detecting Excessive Coupling¶
LLM Coupling Analysis:
# llm/coupling_detector.py
class LLMCouplingDetector:
def detect_excessive_coupling(self, codebase: dict) -> dict:
"""Detect excessive coupling using LLM"""
prompt = f"""
Analyze this codebase for excessive coupling:
{json.dumps(codebase, indent=2)}
Identify:
1. Highly coupled components
2. Coupling patterns
3. Recommendations for reducing coupling
"""
response = self.llm_client.chat.completions.create(
model="gpt-4",
messages=[
{"role": "system", "content": "You are a coupling analysis expert."},
{"role": "user", "content": prompt}
]
)
return json.loads(response.choices[0].message.content)
Proposing Architecture Improvements¶
LLM Architecture Improvement Proposer:
# llm/architecture_improver.py
class LLMArchitectureImprover:
def propose_improvements(self, current_architecture: dict, metrics: dict) -> List[dict]:
"""Propose architecture improvements using LLM"""
prompt = f"""
Propose architecture improvements based on:
Current architecture:
{json.dumps(current_architecture, indent=2)}
Metrics:
{json.dumps(metrics, indent=2)}
Provide:
1. Improvement recommendations
2. Expected impact
3. Implementation steps
4. Priority levels
"""
response = self.llm_client.chat.completions.create(
model="gpt-4",
messages=[
{"role": "system", "content": "You are an architecture improvement expert."},
{"role": "user", "content": prompt}
]
)
return json.loads(response.choices[0].message.content)
Analyzing Dependency Graphs¶
LLM Dependency Graph Analysis:
# llm/dependency_analyzer.py
class LLMDependencyAnalyzer:
def analyze_dependency_graph(self, graph: dict) -> dict:
"""Analyze dependency graph using LLM"""
prompt = f"""
Analyze this dependency graph:
{json.dumps(graph, indent=2)}
Identify:
1. Cyclic dependencies
2. Overly complex dependencies
3. Missing abstractions
4. Refactoring opportunities
"""
response = self.llm_client.chat.completions.create(
model="gpt-4",
messages=[
{"role": "system", "content": "You are a dependency graph analysis expert."},
{"role": "user", "content": prompt}
]
)
return json.loads(response.choices[0].message.content)
Converting ADRs → Measurable Standards¶
LLM ADR to Standards Converter:
# llm/adr_to_standards.py
class LLMADRToStandardsConverter:
def convert_adr_to_standards(self, adr: dict) -> dict:
"""Convert ADR to measurable standards using LLM"""
prompt = f"""
Convert this ADR to measurable architectural standards:
{json.dumps(adr, indent=2)}
Provide:
1. Measurable criteria
2. Fitness functions
3. Acceptance thresholds
4. Monitoring metrics
"""
response = self.llm_client.chat.completions.create(
model="gpt-4",
messages=[
{"role": "system", "content": "You are an ADR to standards conversion expert."},
{"role": "user", "content": prompt}
]
)
return json.loads(response.choices[0].message.content)
Predicting Architecture Failure Modes¶
LLM Failure Mode Predictor:
# llm/failure_mode_predictor.py
class LLMFailureModePredictor:
def predict_failure_modes(self, architecture: dict) -> List[dict]:
"""Predict architecture failure modes using LLM"""
prompt = f"""
Predict potential architecture failure modes for:
{json.dumps(architecture, indent=2)}
Provide:
1. Likely failure modes
2. Probability estimates
3. Impact assessments
4. Prevention strategies
"""
response = self.llm_client.chat.completions.create(
model="gpt-4",
messages=[
{"role": "system", "content": "You are a failure mode prediction expert."},
{"role": "user", "content": prompt}
]
)
return json.loads(response.choices[0].message.content)
Recommending Domain Refactor Boundaries¶
LLM Domain Boundary Recommender:
# llm/domain_boundary_recommender.py
class LLMDomainBoundaryRecommender:
def recommend_boundaries(self, codebase: dict) -> dict:
"""Recommend domain refactor boundaries using LLM"""
prompt = f"""
Recommend domain refactor boundaries for:
{json.dumps(codebase, indent=2)}
Provide:
1. Proposed domain boundaries
2. Rationale
3. Migration strategy
4. Risk assessment
"""
response = self.llm_client.chat.completions.create(
model="gpt-4",
messages=[
{"role": "system", "content": "You are a domain boundary design expert."},
{"role": "user", "content": prompt}
]
)
return json.loads(response.choices[0].message.content)
Identifying Hidden Architectural Risks¶
LLM Risk Identifier:
# llm/risk_identifier.py
class LLMRiskIdentifier:
def identify_risks(self, architecture: dict) -> List[dict]:
"""Identify hidden architectural risks using LLM"""
prompt = f"""
Identify hidden architectural risks in:
{json.dumps(architecture, indent=2)}
Provide:
1. Hidden risks
2. Risk severity
3. Likelihood
4. Mitigation strategies
"""
response = self.llm_client.chat.completions.create(
model="gpt-4",
messages=[
{"role": "system", "content": "You are an architectural risk analysis expert."},
{"role": "user", "content": prompt}
]
)
return json.loads(response.choices[0].message.content)
Generating Architecture Scorecards¶
LLM Scorecard Generator:
# llm/scorecard_generator.py
class LLMScorecardGenerator:
def generate_scorecard(self, component: str, metrics: dict) -> dict:
"""Generate architecture scorecard using LLM"""
prompt = f"""
Generate an architecture scorecard for {component}:
Metrics:
{json.dumps(metrics, indent=2)}
Include:
1. Overall score
2. Category scores
3. Strengths
4. Weaknesses
5. Recommendations
"""
response = self.llm_client.chat.completions.create(
model="gpt-4",
messages=[
{"role": "system", "content": "You are an architecture scorecard expert."},
{"role": "user", "content": prompt}
]
)
return json.loads(response.choices[0].message.content)
See Also¶
- ADR and Technical Decision Governance - Decision recording
- Repository Standardization - Repository governance
- System Resilience - Resilience patterns
This guide provides a complete framework for architectural fitness functions and governance. Start with measurable qualities, implement fitness functions, integrate into CI/CD, and continuously evolve. The goal is architecture that improves over time through measurement and intentional evolution.