Core Principles
The foundational rules of ASA.
Core Principles
The architectural foundations of ASA
The Four Pillars
ASA is built on four non-negotiable principles:
- Determinism — Same input, same output, always
- Zero Magic — Explicit over implicit
- Boundary Enforcement — Isolation over sharing
- Marker-Based Preservation — Regeneration without loss
Principle 1: Determinism
What It Means
Every ASA operation produces identical output for identical input. No randomness, no heuristics, no AI inference in the core pipeline.
slice.spec.md (v1) → slice.contract.json (v1) → skeleton (v1)
slice.spec.md (v1) → slice.contract.json (v1) → skeleton (v1) // Same!
Why It Matters
| Benefit | Impact |
|---|---|
| Reproducibility | Any developer gets the same result |
| Debugging | Differences indicate real changes |
| Version Control | Clean diffs, meaningful commits |
| AI Safety | Agents can't introduce randomness |
| Testing | Predictable behavior to validate |
How ASA Achieves It
- Strict spec parser (regex-based, no NLP)
- Ordered JSON output (consistent field ordering)
- Template-based generation (Jinja2 with deterministic context)
- No runtime decisions (all logic is compile-time)
Principle 2: Zero Magic
What It Means
ASA does exactly what you tell it. No hidden behavior, no automatic assumptions, no "smart" defaults that change based on context.
The Anti-Patterns ASA Avoids
| Magic Pattern | ASA Alternative |
|---|---|
| Auto-detecting intent | Explicit spec sections |
| Inferring types | Declared types required |
| Smart defaults | Explicit defaults or errors |
| Hidden transformations | Visible in templates |
| Context-dependent behavior | Same behavior everywhere |
Explicit Over Implicit
Bad (Magic):
# Framework guesses what you want
@auto_endpoint
def login(email, password):
pass # Framework infers types, validation, errors
Good (ASA):
## Inputs
- email: string
- password: string
## Errors
- INVALID_CREDENTIALS: Invalid email or password.
Everything is declared. Nothing is guessed.
Principle 3: Boundary Enforcement
What It Means
Slices are isolated units. They cannot import from other slices. Cross-domain dependencies are forbidden and caught by the linter.
The Isolation Rule
domains/
├── auth/ # Auth domain
│ ├── login/ # Login slice — self-contained
│ ├── register/ # Register slice — self-contained
│ └── logout/ # Logout slice — self-contained
└── billing/ # Billing domain
└── invoice/ # Invoice slice — self-contained
Allowed Dependencies
| From | To | Allowed |
|---|---|---|
auth/login |
auth/register |
❌ No cross-slice imports |
auth/login |
shared/utils |
✅ Shared modules only |
auth/login |
billing/invoice |
❌ No cross-domain imports |
Enforcement Mechanism
The linter uses AST analysis to detect violations:
# domains/auth/login/repository.py
from domains.billing.invoice import InvoiceService # ❌ FORBIDDEN
$ asa lint auth/login
❌ [LINT FAIL] Boundary violation in repository.py:
Line 1: Illegal import 'domains.billing.invoice'
-> Cannot import from other domains.
Why Boundaries Matter
- Isolation — Changes don't cascade
- Testability — Slices test independently
- Team Ownership — Clear responsibilities
- Cognitive Load — Understand one slice at a time
- Deployment — Potential for independent deployment
Principle 4: Marker-Based Preservation
The Problem
Code generators face a dilemma:
- Regenerate everything → Lose custom code
- Never regenerate → Drift from spec
The ASA Solution
Explicit markers define protected regions:
# Generated structure (regenerated)
class LoginService:
def __init__(self) -> None:
self.repo = LoginRepository()
# === BEGIN USER CODE ===
# PROTECTED REGION
def execute(self, request: LoginRequest) -> LoginResponse:
# Your implementation here - safe during regeneration
user = self.repo.get_user_by_email(request.email)
if not verify_password(user, request.password):
raise UnauthorizedError()
return LoginResponse(jwt_token=generate_jwt(user.id), expires_in=3600)
# === END USER CODE ===
Regeneration Behavior
| Region | On Regeneration |
|---|---|
| Outside markers | Regenerated from template |
| Inside markers | Preserved exactly |
What Gets Preserved
- Business logic
- Custom implementations
- Comments and documentation
- Error handling
- Performance optimizations
What Gets Regenerated
- Imports
- Class structure
- Method signatures (outside markers)
- Type hints
- Pydantic models
Supporting Principles
Duplication Over Sharing
The Rule: Prefer duplication inside slices. Never extract business helpers into shared modules.
Why: Shared business logic creates coupling. Coupling creates drift. Drift destroys determinism.
# ❌ WRONG: Creating shared helper
# shared/utils/password.py
def validate_password(password: str) -> bool:
return len(password) >= 8 and any(c.isupper() for c in password)
# ❌ Then importing in multiple slices
from shared.utils.password import validate_password
# ✅ CORRECT: Duplicating in each slice
# domains/auth/register/service.py
def _validate_password(password: str) -> bool:
return len(password) >= 8 and any(c.isupper() for c in password)
# domains/auth/reset_password/service.py
def _validate_password(password: str) -> bool:
return len(password) >= 8 and any(c.isupper() for c in password)
What to Duplicate vs Share:
| Code Type | Duplicate? | Share? |
|---|---|---|
| Validators, mappers | ✅ Yes | ❌ No |
| Business calculations | ✅ Yes | ❌ No |
| DB session, config | ❌ No | ✅ Yes |
| Email/SMS adapters | ❌ No | ✅ Yes |
In ASA: Coupling is expensive. Duplication is free.
The Deterministic Pipeline
Flow
┌─────────────────┐
│ slice.spec.md │ Human-authored intent
└────────┬────────┘
│ asa generate-contract
▼
┌─────────────────────┐
│ slice.contract.json │ Machine-readable contract
└────────┬────────────┘
│ asa generate-skeleton
▼
┌─────────────────┐
│ Python Files │ handler.py, service.py, etc.
└────────┬────────┘
│ Developer implements
▼
┌─────────────────┐
│ Working Slice │ Ready for integration
└─────────────────┘
Each Step Is Reversible
- Spec changes? Regenerate contract
- Contract changes? Regenerate skeleton (code preserved)
- Need to audit? Contract is the source of truth
ASA Guarantees
When you follow ASA principles:
- ✅ Your code is never lost during regeneration
- ✅ Output is always identical for same input
- ✅ Boundaries are always enforced
- ✅ Errors are always explicit
- ✅ Duplication is safe and encouraged for business logic
What ASA Does Not Guarantee
ASA does not:
- ❌ Generate perfect business logic
- ❌ Eliminate the need for testing
- ❌ Replace code review
- ❌ Prevent all bugs
ASA provides architectural safety, not correctness guarantees.
Your implementation quality still depends on:
- Clear specifications
- Proper testing
- Code review
- Domain expertise
Practical Implications
For Developers
- Write specs, not boilerplate
- Implement business logic between markers
- Trust regeneration to update structure
- Use the linter to catch violations
For Architects
- Design domain boundaries carefully
- Define shared modules explicitly
- Enforce ASA rules via CI/CD
- Review specs, not just code
For Teams
- Specs become the source of truth
- Onboarding is faster (read the spec)
- Code reviews focus on logic, not structure
- Refactoring is safer (boundaries prevent cascades)
Summary
| Principle | Meaning | Benefit |
|---|---|---|
| Determinism | Same input → same output | Reproducibility, debugging, safety |
| Zero Magic | Explicit over implicit | Predictability, clarity |
| Boundary Enforcement | Isolation over sharing | Zero drift, safe changes |
| Marker-Based Preservation | Regeneration without loss | Continuous improvement |
These principles work together to create maintainable AI-generated code.
Next Steps
- How ASA Works — See the principles in action
- Problems ASA Solves — Understand the real-world impact
- FAQ — Common questions answered