Policy Examples
Policy Examples
Section titled “Policy Examples”This guide provides real-world policy examples for different project types and architectural styles.
Understanding Policies
Section titled “Understanding Policies”Policies in Arxo are defined in YAML and consist of invariants - conditions that must always be true.
policy: invariants: - metric: <metric_id> op: <operator> value: <threshold> message: <optional_message>Operators: ==, !=, <, <=, >, >=
Zero-Cycle Policy (Strict)
Section titled “Zero-Cycle Policy (Strict)”Use Case: New projects, microservices, libraries
Enforce a completely acyclic architecture:
policy: invariants: # No circular dependencies at all - metric: scc.max_cycle_size op: "==" value: 0 message: "Circular dependencies are not allowed"
# All nodes should be in their own SCC - metric: scc.total_nodes_in_cycles op: "==" value: 0 message: "No modules should participate in cycles"Microservices Architecture
Section titled “Microservices Architecture”Use Case: Service-oriented architecture, domain boundaries
Ensure low coupling between services:
data: import_graph: group_by: folder group_depth: 2 # Group by service folders
policy: invariants: # Low system-wide coupling - metric: propagation_cost.system.ratio op: "<=" value: 0.10 message: "Services should be loosely coupled"
# No circular dependencies between services - metric: scc.max_cycle_size op: "==" value: 0 message: "Services must not have circular dependencies"
# Prevent god services - metric: centrality.module.max_fan_out op: "<=" value: 8 message: "No service should depend on more than 8 others"
# Good modular structure - metric: modularity.module.best_q op: ">=" value: 0.40 message: "Services should form clear modules"Feature-Sliced Design (FSD)
Section titled “Feature-Sliced Design (FSD)”Use Case: Frontend applications with FSD architecture
Enforce layer hierarchy:
data: import_graph: group_by: folder group_depth: 2 # app/pages, app/features, shared/ui, etc.
policy: invariants: # Strict hierarchy (low weighted upward flow) - metric: hierarchy.module.edge.upward_weight_ratio op: "<=" value: 0.05 message: "Layers should not import from upper layers"
# Low hierarchy erosion - metric: hierarchy.module.agony.weighted_depth_normalized op: "<=" value: 0.08 message: "Minimize inferred hierarchy erosion"
# No cycles between features - metric: scc.max_cycle_size op: "==" value: 0 message: "Features must not have circular dependencies"
# Good modular separation - metric: modularity.module.best_q op: ">=" value: 0.35 message: "Features should be well-separated"Monorepo with Multiple Apps
Section titled “Monorepo with Multiple Apps”Use Case: Nx, Turborepo, Lerna monorepos
Enforce package boundaries:
data: import_graph: group_by: folder group_depth: 2 exclude: - "**/node_modules/**" - "**/dist/**"
policy: invariants: # Apps should not depend on each other - metric: smells.cycles.count op: "==" value: 0 message: "Apps should not depend on each other"
# Reasonable coupling - metric: propagation_cost.system.ratio op: "<=" value: 0.15 message: "Keep inter-package coupling low"
# Shared libraries should be stable - metric: package_metrics.module.instability.max op: "<=" value: 0.5 message: "Shared packages should be stable"Legacy Codebase (Pragmatic)
Section titled “Legacy Codebase (Pragmatic)”Use Case: Existing projects with technical debt
Set achievable goals while preventing regression:
policy: invariants: # Allow small cycles, but limit size - metric: scc.max_cycle_size op: "<=" value: 5 message: "Keep cycles small (max 5 modules)"
# Limit nodes in cycles - metric: scc.total_nodes_in_cycles op: "<=" value: 30 message: "No more than 30 modules in cycles"
# Prevent new god components - metric: smells.god_components.count op: "<=" value: 3 message: "No more than 3 god components allowed"
# System coupling should not increase - metric: propagation_cost.system.ratio op: "<=" value: 0.30 message: "Do not increase system coupling"API Service
Section titled “API Service”Use Case: REST/GraphQL APIs, backend services
Focus on layering and boundaries:
data: import_graph: group_by: folder group_depth: 1 # controllers, services, repositories, models
policy: invariants: # Enforce layered architecture (weighted by dependency importance) - metric: hierarchy.module.edge.upward_weight_ratio op: "<=" value: 0.12 message: "Respect layer boundaries (controllers → services → repositories)"
# No cross-layer violations - metric: smells.hierarchy.cyclic_count op: "==" value: 0 message: "Controllers should not import from repositories directly"
# Keep services independent - metric: scc.max_cycle_size op: "==" value: 0 message: "No circular dependencies between services"React Native Mobile App
Section titled “React Native Mobile App”Use Case: Mobile applications with screens/features
data: import_graph: group_by: folder group_depth: 2 exclude: - "**/node_modules/**" - "**/__tests__/**" - "**/*.test.tsx"
policy: invariants: # Screens should not depend on each other - metric: smells.cycles.severe_count op: "==" value: 0 message: "Screens must not have circular dependencies"
# Reasonable coupling - metric: propagation_cost.system.ratio op: "<=" value: 0.20 message: "Keep coupling manageable for mobile"
# No navigation bloat - metric: centrality.module.max_fan_out op: "<=" value: 10 message: "No screen should navigate to more than 10 others"Python Package/Library
Section titled “Python Package/Library”Use Case: Reusable Python packages
data: import_graph: group_by: folder group_depth: 2 exclude: - "**/tests/**" - "**/__pycache__/**"
policy: invariants: # Library should be acyclic - metric: scc.max_cycle_size op: "==" value: 0 message: "No circular imports in library code"
# Public API should be stable - metric: package_metrics.module.instability.mean op: "<=" value: 0.3 message: "Keep public API stable"
# Prevent tight coupling - metric: propagation_cost.system.ratio op: "<=" value: 0.15 message: "Modules should be loosely coupled"AI/LLM Application
Section titled “AI/LLM Application”Use Case: Applications with LLM integrations
metrics: - id: llm_integration - id: rag_architecture - id: finetuning_architecture - id: agent_architecture
policy: invariants: # Observability is critical - metric: llm.observability_gap op: "<=" value: 0.20 message: "At least 80% of LLM calls must have tracing"
# No PII leakage - metric: llm.pii_leakage_risk op: "==" value: 0 message: "No PII should flow to LLM prompts without redaction"
# Cost tracking - metric: llm.cost_tracking_gap op: "<=" value: 0.30 message: "Track token usage for cost control"
# Require evaluation harness - metric: llm.eval_harness_present op: "==" value: 1.0 message: "Evaluation tests are required"
# Fine-tuning reproducibility and eval quality gate - metric: finetuning_architecture.overall_finetuning_health op: ">=" value: 0.70 message: "Fine-tuning architecture baseline not met"Agent Architecture Focused Gate
Section titled “Agent Architecture Focused Gate”Use Case: Teams that want a dedicated CI gate for agent reliability and governance
metrics: - id: agent_architecture
policy: invariants: - metric: agent_architecture.loop_guard_absence op: "<=" value: 0.20 message: "Agent loops must be bounded with step/time guards" - metric: agent_architecture.governance_readiness op: ">=" value: 80 message: "Tool governance baseline not met" - metric: agent_architecture.overall_agent_health op: ">=" value: 0.70 message: "Overall agent health below minimum threshold"See Agent Architecture policy and CI gates for strict/pragmatic/no-regression profiles.
Security-Critical Application
Section titled “Security-Critical Application”Use Case: Financial, healthcare, compliance-heavy apps
metrics: - id: scc - id: security - id: sensitive_data_flow
policy: invariants: # Zero cycles for predictability - metric: scc.max_cycle_size op: "==" value: 0 message: "Circular dependencies not allowed"
# No sensitive data leaks - metric: security.sensitive_data_flow_violations op: "==" value: 0 message: "Sensitive data must not flow to unsafe sinks"
# Low coupling for isolation - metric: propagation_cost.system.ratio op: "<=" value: 0.10 message: "Security-critical modules must be isolated"Progressive Enhancement
Section titled “Progressive Enhancement”Start strict, allow exceptions temporarily:
policy: invariants: # Ideal: zero cycles - metric: scc.max_cycle_size op: "==" value: 0 message: "No circular dependencies (eventually)"
# Current: allow up to 3 small cycles - metric: scc.component_count op: ">=" value: 147 # Total nodes minus allowed cycles message: "Do not introduce new cycles"
# Track progress - metric: scc.total_nodes_in_cycles op: "<=" value: 12 message: "Reduce cycles over time"Strategy: Tighten thresholds gradually in each sprint.
Multi-Metric Combination
Section titled “Multi-Metric Combination”Combine metrics for comprehensive policies:
policy: invariants: # Structural - metric: scc.max_cycle_size op: "==" value: 0
# Coupling - metric: propagation_cost.system.ratio op: "<=" value: 0.15
# Modularity - metric: modularity.module.best_q op: ">=" value: 0.35
# Smells - metric: smells.god_components.count op: "==" value: 0
- metric: smells.cycles.severe_count op: "==" value: 0
# Centrality - metric: centrality.module.max_fan_out op: "<=" value: 10Baseline Comparison (Ratcheting)
Section titled “Baseline Comparison (Ratcheting)”Prevent regression without fixing everything:
# Generate baseline from main branchgit checkout mainarxo analyze --format json --output baseline.jsongit checkout feature-branch
# Compare against baselinearxo analyze --baseline baseline.jsonPolicy: Metrics should not get worse than baseline.
Custom Messages
Section titled “Custom Messages”Provide actionable guidance:
policy: invariants: - metric: scc.max_cycle_size op: "==" value: 0 message: | Circular dependency detected!
To fix: 1. Run: arxo analyze --format json | jq '.results[] | select(.id=="scc")' 2. Identify the cycle nodes 3. Extract shared code to a new module 4. Use dependency injection
See: https://docs.arxo.io/guides/breaking-cyclesEnvironment-Specific Policies
Section titled “Environment-Specific Policies”Use different configs for different stages:
.arxo.dev.yaml (Development):
policy: invariants: - metric: scc.max_cycle_size op: "<=" value: 5 # Relaxed.arxo.ci.yaml (CI):
policy: invariants: - metric: scc.max_cycle_size op: "==" value: 0 # StrictUsage:
# Developmentarxo analyze --config .arxo.dev.yaml
# CIarxo analyze --config .arxo.ci.yamlAI-Assisted Policy Validation
Section titled “AI-Assisted Policy Validation”Use the MCP server for on-demand policy checks with your AI assistant:
You: "Check if my changes violate our architecture policies"AI: [Uses evaluate_policy] "Found 1 violation: scc.max_cycle_size exceeded..."The AI can evaluate policies inline or use your .arxo.yaml config automatically. See MCP Workflows for examples.
Next Steps
Section titled “Next Steps”- Configuration Guide - Full configuration reference
- CI Integration - Enforce policies in CI
- MCP Workflows - Policy validation with AI
- Metrics Overview - Available metrics
- Troubleshooting - Fix violations