aeo-architecture

Analyze and protect code architecture. Detects circular dependencies and layer violations.

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "aeo-architecture" with this command: npx skills add ivzc07/aeo-skills/ivzc07-aeo-skills-aeo-architecture

AEO Architecture

Purpose: Analyze and protect code architecture. Detects circular dependencies, layer violations, and manages ADRs (Architecture Decision Records).

Configuration

Define architecture layers at $PAI_DIR/USER/aeo-layers.yaml:

layers:
  - name: "presentation"
    path: "src/components/"
    may_import: ["domain", "application"]
    may_not_import: ["infrastructure", "presentation"]

  - name: "domain"
    path: "src/domain/"
    may_import: []
    may_not_import: ["presentation", "application", "infrastructure"]

  - name: "application"
    path: "src/services/"
    may_import: ["domain"]
    may_not_import: ["presentation", "infrastructure"]

  - name: "infrastructure"
    path: "src/infrastructure/"
    may_import: ["domain"]
    may_not_import: ["presentation", "application"]

Default: No layers defined - only detect circular dependencies

When to Analyze

Run architecture analysis:

  • After feature implementation
  • Before git commit (via aeo-qa-agent)
  • When circular dependency suspected
  • During code review

Detection Types

1. Circular Dependencies

Detection:

# Build dependency graph
find src -name "*.js" -o -name "*.ts" | while read file; do
  grep -h "^import" "$file" | \
    sed "s/.*from ['\"]\(.*\)['\"].*/\1/" | \
    while read import; do
      echo "$file -> $import"
    done
done > /tmp/deps.txt

# Detect cycles
# (Use graph algorithm or madge)
npx madge --circular --extensions ts,tsx,js,jsx src/

Example Circular Dependency:

❌ CIRCULAR DEPENDENCY DETECTED

Cycle:
  src/services/UserService.js
    → src/repositories/UserRepository.js
      → src/models/User.js
        → src/services/UserService.js
          (back to start - cycle!)

Why this matters:
• Creates tight coupling
• Makes code impossible to test in isolation
• Can cause runtime errors during module loading
• Violates clean architecture principles

Resolution Options:
1. Extract shared code - Create new module for shared functionality
2. Invert dependency - Use dependency injection
3. Introduce interface - Abstract the dependency

Recommended: Option 1 - Extract shared functionality

Your choice (1-3):

2. Layer Violations

Detection:

# Check if presentation layer imports infrastructure
grep -r "import.*from.*infrastructure" src/components/

# Check if domain imports presentation
grep -r "import.*from.*components" src/domain/

Example Layer Violation:

⚠️ LAYER VIOLATION DETECTED

Violation: Presentation layer importing Infrastructure

File: src/components/UserList.tsx:5
Import: import db from '../infrastructure/database.js'

Why this violates architecture:
• Presentation should only import from Application/Domain
• Direct database access in component creates tight coupling
• Makes testing difficult (need real database)
• Violates separation of concerns

Correct Pattern:
❌ src/components/UserList.tsx
   import db from '../infrastructure/database.js'

✅ src/components/UserList.tsx
   import { getUsers } from '../services/UserService.js'

✅ src/services/UserService.js
   import db from '../infrastructure/database.js'
   export function getUsers() {
     return db.query('SELECT * FROM users')
   }

Action: Fix violation before commit

3. Breaking Encapsulation

Detection:

# Check for private field access from outside class
grep -r "#[a-zA-Z]*\s*=" src/ | grep -v "this\.#"

Example Encapsulation Breaking:

❌ ENCAPSULATION VIOLATION

File: src/utils/userHelper.js:42
Issue: Accessing private field #passwordHash from outside

Code:
```javascript
class User {
  #passwordHash  // Private field
}

// In another file:
user.#passwordHash = 'new'  // ❌ VIOLATION

Why this violates encapsulation: • Private fields are implementation details • Bypasses validation and invariants • Makes code fragile to internal changes • Breaks abstraction boundary

Correct Approach:

class User {
  #passwordHash

  setPassword(newPassword) {
    // Validate and hash
    this.#passwordHash = hash(newPassword)
  }

  getPassword() {
    return this.#passwordHash
  }
}

// Use public API:
user.setPassword('new')

Action: Fix encapsulation violation


---

## Architecture Decision Records (ADRs)

### ADR Format

Create ADRs at `$PAI_DIR/USER/ADRs/`:

```markdown
# ADR-001: Use JWT for Authentication

## Status
Accepted

## Context
We need authentication for our API. Options considered:
- Session-based auth
- JWT tokens
- API keys

## Decision
Use JWT tokens because:
1. Stateless - scales horizontally
2. Standard - well-supported libraries
3. Flexible - supports multiple auth providers

## Consequences
- Positive: No session storage needed
- Positive: Works well with microservices
- Negative: Token revocation requires blacklist
- Negative: Larger payload than session IDs

## Implementation
- Use jose library for JWT handling
- Store refresh tokens in Redis
- Set access token expiry to 15 minutes

## Date
2026-01-22

Recording ADRs

When making significant architectural decisions:

  1. Create ADR file:

    # Find next ADR number
    next_num=$(ls ~/.claude/USER/ADRs/ | grep ADR- | wc -l)
    adr_file=~/.claude/USER/ADRs/ADR-$(printf "%03d" $((next_num + 1)))-${title}.md
    
  2. Use template:

    cat > "$adr_file" << 'EOF'
    # ADR-XXX: [Title]
    
    ## Status
    Proposed
    
    ## Context
    [Problem statement and context]
    
    ## Decision
    [The decision]
    
    ## Consequences
    - Positive: [Benefits]
    - Negative: [Drawbacks]
    
    ## Date
    $(date -u +%Y-%m-%d)
    EOF
    
  3. Reference ADRs in code:

    // See ADR-001: Use JWT for Authentication
    import { generateToken } from './auth/jwt.js'
    

Architecture Analysis Commands

Check Circular Dependencies

# Using madge
npx madge --circular --extensions ts,tsx src/

# Output:
# ✅ No circular dependencies found
# or
# ❌ Circular dependencies found:
#   src/a.js → src/b.js → src/a.js

Check Layer Violations

# Check layer compliance
check_layers() {
  local layer=$1
  local path=$2
  local forbidden=$3

  echo "Checking $layer layer..."

  for forbidden_import in $forbidden; do
    violations=$(grep -r "import.*from.*$forbidden_import" "$path" 2>/dev/null)
    if [ -n "$violations" ]; then
      echo "❌ $layer importing from $forbidden_import:"
      echo "$violations"
    fi
  done
}

# Run checks
check_layers "presentation" "src/components" "infrastructure"
check_layers "domain" "src/domain" "presentation,application"

Generate Dependency Graph

# Visualize dependencies
npx madge --image deps.svg --extensions ts,tsx src/

# Output:
# Generated deps.svg

Integration

With aeo-qa-agent:

// In QA review, Step 4: Check Architecture
if (architecture_violations_found) {
  invoke_skill('aeo-architecture', {
    type: 'violation',
    violations: violations
  });
}

With aeo-escalation:

// When architecture violation detected
invoke_skill('aeo-escalation', {
  type: 'architecture_violation',
  issue: 'circular_dependency',
  options: [
    'Extract shared code',
    'Refactor dependencies',
    'Defer to architect'
  ],
  recommended: 1
});

Best Practices

DO:

  • Define clear layer boundaries upfront
  • Use dependency injection to break cycles
  • Record significant architectural decisions
  • Review architecture before committing
  • Generate dependency graphs periodically

DON'T:

  • Allow circular dependencies to persist
  • Let layers bleed into each other Skip architecture review for "quick fixes"
  • Break encapsapsulation for convenience
  • Forget to document architectural decisions

Example Session

AEO-QA: [Step 4: Check Architecture]

AEO-Architecture: Analyzing codebase...

                Detected Issues:
                ❌ Circular dependency: UserService → UserRepository → User → UserService
                ❌ Layer violation: UserList.tsx importing database.js
                ✅ Encapsulation: All private fields properly protected

                [Invokes aeo-escalation for circular dependency]

Escalation: ⚠️ ARCHITECTURE VIOLATION DETECTED

           Issue: Circular dependency between modules

           Circular Path:
            UserService.js imports UserRepository.js
            UserRepository.js imports User.js
            User.js imports UserService.js

           Options:
           1. Extract shared code - Create UserValueObject module
           2. Refactor dependencies - Introduce UserInterface
           3. Defer to architect - Let architect decide

           Recommended: Option 1 - Extract shared code

Developer: 1

AEO-Architecture: Creating UserValueObject module...

                [Refactoring...]
                [Updating imports...]
                [Running tests...]
                ✅ Circular dependency resolved

                [Recording ADR-003: Extract User Value Object]

AEO-QA: Architecture check passed

AEO-Core: Ready to commit

ADR Management

List ADRs

ls -1 ~/.claude/USER/ADRs/ | sort
# ADR-001-use-jwt-for-authentication.md
# ADR-002-adopt-event-sourcing.md
# ADR-003-extract-user-value-object.md

Find ADR by Topic

grep -r "JWT" ~/.claude/USER/ADRs/
# ADR-001-use-jwt-for-authentication.md:## Context
# ADR-001-use-jwt-for-authentication.md:# - Use JWT tokens

Propose New ADR

# Create proposed ADR
cat > ~/.claude/USER/ADRs/ADR-004-adopt-graphql.md << 'EOF'
# ADR-004: Adopt GraphQL

## Status
Proposed

## Context
Current REST API has issues:
- Over-fetching data
- Multiple round trips for related data
- Versioning complexity

## Decision
Adopt GraphQL for...

## Consequences
- Positive: Single query for related data
- Positive: Strongly typed schema
- Negative: Learning curve
- Negative: Complexity in caching

## Date
$(date -u +%Y-%m-%d)
EOF

# Then discuss with team before marking as "Accepted"

Architecture Health Score

Calculate architecture health:

# 100 points total
score=100

# Subtract for issues
circular_deps=$(npx madge --circular src/ 2>/dev/null | grep "Found" | wc -l)
score=$((score - circular_deps * 20))

layer_violations=$(grep -r "import.*infrastructure" src/components/ 2>/dev/null | wc -l)
score=$((score - layer_violations * 10))

echo "Architecture Health: $score/100"

Interpretation:

  • 90-100: Excellent architecture
  • 70-89: Good, minor issues
  • 50-69: Needs improvement
  • < 50: Critical architectural problems

Disable Architecture Checks

To disable for a project, delete $PAI_DIR/USER/aeo-layers.yaml:

rm ~/.claude/USER/aeo-layers.yaml
# AEO will skip layer checks, still detect circular deps

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

General

aeo-core

No summary provided by upstream source.

Repository SourceNeeds Review
Automation

aeo-qa-agent

No summary provided by upstream source.

Repository SourceNeeds Review
General

aeo-cost-governor

No summary provided by upstream source.

Repository SourceNeeds Review
General

aeo-spec-validator

No summary provided by upstream source.

Repository SourceNeeds Review