<!-- START doctoc generated TOC please keep comment here to allow auto update -->
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
**Table of Contents**

- [Enterprise clap-noun-verb Architecture](#enterprise-clap-noun-verb-architecture)
  - [Fortune 5 Reality: 5 Years at Scale](#fortune-5-reality-5-years-at-scale)
    - [Scale Factors](#scale-factors)
  - [Core Problem: The Regeneration Dilemma](#core-problem-the-regeneration-dilemma)
    - [The Solution: Separation of Concerns via File Boundaries](#the-solution-separation-of-concerns-via-file-boundaries)
  - [Pattern 1: Trait-Based Domain Protection](#pattern-1-trait-based-domain-protection)
    - [Generated Code (Regenerated Freely)](#generated-code-regenerated-freely)
    - [Domain Code (Never Touched by Generator)](#domain-code-never-touched-by-generator)
  - [Pattern 2: Per-Noun RDF Ownership](#pattern-2-per-noun-rdf-ownership)
    - [File Structure for 35 Teams](#file-structure-for-35-teams)
    - [OWNERS File (Poka-Yoke: Wrong Team Can't Merge)](#owners-file-poka-yoke-wrong-team-cant-merge)
  - [Pattern 3: Adding Commands Without Merge Conflicts](#pattern-3-adding-commands-without-merge-conflicts)
    - [The Problem](#the-problem)
    - [The Solution: One File Per Verb](#the-solution-one-file-per-verb)
    - [Adding a New Command (Zero Conflict Workflow)](#adding-a-new-command-zero-conflict-workflow)
  - [FMEA: Failure Mode and Effects Analysis](#fmea-failure-mode-and-effects-analysis)
    - [RPN Priority (Risk Priority Number = S × O × D)](#rpn-priority-risk-priority-number--s-%C3%97-o-%C3%97-d)
  - [Poka-Yoke Control Matrix](#poka-yoke-control-matrix)
    - [Physical Controls (File System)](#physical-controls-file-system)
    - [Sequence Controls (Must Do X Before Y)](#sequence-controls-must-do-x-before-y)
    - [Grouping Controls (Related Items Together)](#grouping-controls-related-items-together)
    - [Information Controls (Warnings, Errors)](#information-controls-warnings-errors)
  - [Enterprise File Organization (200+ Commands)](#enterprise-file-organization-200-commands)
  - [Key Takeaways](#key-takeaways)

<!-- END doctoc generated TOC please keep comment here to allow auto update -->

# Enterprise clap-noun-verb Architecture

## Fortune 5 Reality: 5 Years at Scale

### Scale Factors
- **50+ developers** across 8 teams
- **200+ commands** across 35 nouns
- **3M+ lines** of domain logic
- **24/7 operations** with 99.99% SLA
- **SOX/HIPAA compliance** requirements

---

## Core Problem: The Regeneration Dilemma

```
┌─────────────────────────────────────────────────────────────┐
│  ANTI-PATTERN: Monolithic Generated Code                    │
│                                                             │
│  generated/                                                 │
│  └── main.rs  ← 50,000 lines, NEVER regenerate             │
│                 because domain logic mixed in               │
│                                                             │
│  Result: Generation abandoned after Month 3                 │
└─────────────────────────────────────────────────────────────┘
```

### The Solution: Separation of Concerns via File Boundaries

```
┌─────────────────────────────────────────────────────────────┐
│  PATTERN: Generated Skeleton + Domain Implementation        │
│                                                             │
│  src/                                                       │
│  ├── generated/          ← REGENERATE FREELY (git-ignored) │
│  │   ├── mod.rs                                            │
│  │   ├── nouns/                                            │
│  │   │   ├── user.rs     ← trait UserCommands              │
│  │   │   └── order.rs    ← trait OrderCommands             │
│  │   └── routing.rs      ← clap macro invocations          │
│  │                                                          │
│  ├── domain/             ← NEVER TOUCHED BY GENERATOR       │
│  │   ├── user/                                             │
│  │   │   ├── mod.rs      ← impl UserCommands for UserDomain│
│  │   │   ├── create.rs   ← actual business logic           │
│  │   │   └── delete.rs                                     │
│  │   └── order/                                            │
│  │       └── ...                                           │
│  │                                                          │
│  └── main.rs             ← 10 lines, imports + runs         │
└─────────────────────────────────────────────────────────────┘
```

---

## Pattern 1: Trait-Based Domain Protection

### Generated Code (Regenerated Freely)

```rust
// src/generated/nouns/user.rs
// ⚠️ DO NOT EDIT - Generated by ggen from ontology/cli.ttl
// Regenerate with: ggen generate --domain ontology/cli.ttl

use crate::domain::user::UserDomain;
use clap_noun_verb::Result;

/// Trait defining all user commands - implement in domain layer
pub trait UserCommands {
    fn create(&self, name: String, email: String) -> Result<UserOutput>;
    fn delete(&self, id: String, force: bool) -> Result<DeleteOutput>;
    fn list(&self, limit: Option<u32>, filter: Option<String>) -> Result<ListOutput>;
}

// Output types - generated from RDF schema
#[derive(Serialize, Deserialize)]
pub struct UserOutput {
    pub id: String,
    pub name: String,
    pub email: String,
    pub created_at: DateTime<Utc>,
}

// ... more output types ...

// Routing - connects CLI args to trait methods
#[noun("user", "Manage user accounts")]
pub mod user_commands {
    use super::*;

    #[verb("create", "Create a new user")]
    pub fn create(
        #[arg(help = "User's full name")] name: String,
        #[arg(help = "User's email address")] email: String,
    ) -> Result<serde_json::Value> {
        let domain = UserDomain::new();
        let result = domain.create(name, email)?;
        Ok(serde_json::to_value(result)?)
    }
}
```

### Domain Code (Never Touched by Generator)

```rust
// src/domain/user/mod.rs
// ✅ SAFE - Generator never touches this file

use crate::generated::nouns::user::{UserCommands, UserOutput, DeleteOutput, ListOutput};
use crate::infrastructure::{Database, Telemetry, FeatureFlags};

pub struct UserDomain {
    db: Database,
    telemetry: Telemetry,
    flags: FeatureFlags,
}

impl UserDomain {
    pub fn new() -> Self {
        Self {
            db: Database::from_env(),
            telemetry: Telemetry::new("user"),
            flags: FeatureFlags::load(),
        }
    }
}

impl UserCommands for UserDomain {
    fn create(&self, name: String, email: String) -> Result<UserOutput> {
        // 3 years of battle-tested business logic here
        // - Input validation with 47 edge cases
        // - Duplicate detection across regions
        // - GDPR compliance checks
        // - Audit logging for SOX
        // - Feature flag for gradual rollout
        // - Circuit breaker for downstream services
        // - Retry logic with exponential backoff
        // ...
    }

    fn delete(&self, id: String, force: bool) -> Result<DeleteOutput> {
        // More production-hardened logic
    }

    fn list(&self, limit: Option<u32>, filter: Option<String>) -> Result<ListOutput> {
        // Paginated, filtered, cached queries
    }
}
```

---

## Pattern 2: Per-Noun RDF Ownership

### File Structure for 35 Teams

```
ontology/
├── _core/                    ← Platform team owns
│   ├── types.ttl            ← Shared types (Result, Error, Pagination)
│   ├── traits.ttl           ← Cross-cutting concerns
│   └── conventions.ttl      ← Naming standards
│
├── user/                     ← Identity team owns
│   ├── noun.ttl             ← User noun definition
│   ├── OWNERS               ← GitHub CODEOWNERS format
│   └── CHANGELOG.md         ← Breaking change history
│
├── order/                    ← Commerce team owns
│   ├── noun.ttl
│   ├── OWNERS
│   └── CHANGELOG.md
│
├── inventory/                ← Supply chain team owns
│   └── ...
│
└── cli.ttl                   ← Master file, imports all nouns
                               ← ONLY platform team can modify
```

### OWNERS File (Poka-Yoke: Wrong Team Can't Merge)

```
# ontology/user/OWNERS
# Changes require approval from Identity team

@company/identity-team
@john.smith
@jane.doe

# Breaking changes require platform team
*.breaking.ttl @company/platform-team
```

---

## Pattern 3: Adding Commands Without Merge Conflicts

### The Problem
```
Developer A: Adds "user promote" command
Developer B: Adds "user demote" command
Both modify: ontology/user/noun.ttl
Result: MERGE CONFLICT
```

### The Solution: One File Per Verb

```
ontology/
└── user/
    ├── noun.ttl              ← Noun metadata only (rarely changes)
    ├── verbs/
    │   ├── create.ttl        ← Developer A's file
    │   ├── delete.ttl        ← Developer B's file
    │   ├── promote.ttl       ← New file, no conflict
    │   └── demote.ttl        ← New file, no conflict
    └── types/
        ├── user_output.ttl
        └── permissions.ttl
```

### Adding a New Command (Zero Conflict Workflow)

```bash
# 1. Create verb definition (new file = no conflict)
cat > ontology/user/verbs/suspend.ttl << 'EOF'
@prefix cnv: <https://ggen.dev/clap-noun-verb/> .
@prefix user: <https://company.com/cli/user/> .

user:suspend a cnv:Verb ;
    cnv:verbName "suspend" ;
    cnv:description "Temporarily suspend a user account" ;
    cnv:hasArguments user:suspend_id, user:suspend_reason ;
    cnv:returnType user:SuspendOutput .

user:suspend_id a cnv:Argument ;
    cnv:argumentName "id" ;
    cnv:argumentType cnv:String ;
    cnv:required true .

user:suspend_reason a cnv:Argument ;
    cnv:argumentName "reason" ;
    cnv:argumentType cnv:String ;
    cnv:required true .
EOF

# 2. Regenerate (only generated/ changes)
ggen generate --domain ontology/cli.ttl --output src/generated/

# 3. Implement domain logic (new file = no conflict)
cat > src/domain/user/suspend.rs << 'EOF'
impl UserCommands for UserDomain {
    fn suspend(&self, id: String, reason: String) -> Result<SuspendOutput> {
        // Your implementation here
    }
}
EOF

# 4. Commit (3 new files, 0 modified files = no conflicts)
git add ontology/user/verbs/suspend.ttl
git add src/domain/user/suspend.rs
git commit -m "feat(user): Add suspend command"
```

---

## FMEA: Failure Mode and Effects Analysis

| ID | Failure Mode | Effect | Severity (1-10) | Occurrence (1-10) | Detection (1-10) | RPN | Control |
|----|--------------|--------|-----------------|-------------------|------------------|-----|---------|
| F1 | Developer edits generated file | Changes lost on regenerate | 8 | 9 | 3 | 216 | **File header warning + .gitignore generated/** |
| F2 | Regenerate overwrites domain logic | Loss of business logic | 10 | 7 | 2 | 140 | **Trait boundary - domain in separate files** |
| F3 | Two teams create same noun name | Namespace collision | 7 | 4 | 6 | 168 | **CI validation: unique noun names across ontology/** |
| F4 | Breaking change to verb signature | Runtime failures | 9 | 5 | 4 | 180 | **Semver in RDF + compile-time trait check** |
| F5 | Missing error handling in command | Prod crash, bad UX | 8 | 6 | 5 | 240 | **Trait requires Result<T> return type** |
| F6 | Inconsistent output format | Client integration breaks | 7 | 5 | 6 | 210 | **Output types generated from RDF schema** |
| F7 | Missing telemetry on command | Blind spot in prod | 6 | 7 | 4 | 168 | **Telemetry trait auto-injected by generator** |
| F8 | Command works in test, fails prod | Production incident | 9 | 4 | 7 | 252 | **Feature flags + canary deployment** |
| F9 | Merge conflict in ontology | Blocked deployment | 5 | 8 | 2 | 80 | **One file per verb pattern** |
| F10 | Orphaned domain code after verb removal | Dead code accumulation | 4 | 6 | 8 | 192 | **CI: unused impl warning** |

### RPN Priority (Risk Priority Number = S × O × D)
- **> 200**: CRITICAL - Must have control before launch
- **100-200**: HIGH - Implement control in first quarter
- **< 100**: MEDIUM - Backlog for continuous improvement

---

## Poka-Yoke Control Matrix

### Physical Controls (File System)

| Control | Mistake Prevented | Implementation | Enforcement |
|---------|-------------------|----------------|-------------|
| `generated/` in .gitignore | Committing generated code | `.gitignore` entry | Block |
| CODEOWNERS per noun | Wrong team modifying ontology | GitHub CODEOWNERS | Block (PR) |
| Read-only generated/ in CI | Editing generated files | `chmod 444` in CI | Block |
| Separate domain/ directory | Generator touching domain | Generator config | Block |

### Sequence Controls (Must Do X Before Y)

| Control | Mistake Prevented | Implementation | Enforcement |
|---------|-------------------|----------------|-------------|
| Compile after regenerate | Trait signature mismatch | `ggen generate && cargo check` | Block |
| RDF validation before generate | Invalid ontology | `ggen ontology validate` | Block |
| Breaking change review | Unreviewed API changes | `*.breaking.ttl` CODEOWNERS | Block (PR) |
| Domain impl required | Stub left in production | `#[cfg(not(test))]` on unimplemented | Block |

### Grouping Controls (Related Items Together)

| Control | Mistake Prevented | Implementation | Enforcement |
|---------|-------------------|----------------|-------------|
| Noun directory structure | Scattered related files | `ontology/{noun}/` convention | Warn |
| Verb + types in same PR | Orphaned types | PR template checklist | Warn |
| CHANGELOG with breaking | Undocumented breaks | CI check for CHANGELOG | Block |

### Information Controls (Warnings, Errors)

| Control | Mistake Prevented | Implementation | Enforcement |
|---------|-------------------|----------------|-------------|
| Generated file header | Editing generated code | `// ⚠️ DO NOT EDIT` banner | Warn |
| Deprecation warnings | Using deprecated verbs | `#[deprecated]` attribute | Warn |
| Coverage report | Untested commands | CI coverage gate 80% | Block |
| Unused impl detection | Dead domain code | `#[warn(dead_code)]` | Warn |

---

## Enterprise File Organization (200+ Commands)

```
my-enterprise-cli/
├── Cargo.toml
├── Cargo.lock
│
├── ontology/                          # RDF definitions (source of truth)
│   ├── _core/                         # Platform team
│   │   ├── types.ttl                  # Shared types
│   │   ├── error.ttl                  # Error taxonomy
│   │   └── pagination.ttl             # List response patterns
│   │
│   ├── user/                          # Identity team
│   │   ├── noun.ttl
│   │   ├── OWNERS
│   │   ├── CHANGELOG.md
│   │   ├── verbs/
│   │   │   ├── create.ttl
│   │   │   ├── delete.ttl
│   │   │   ├── list.ttl
│   │   │   ├── get.ttl
│   │   │   ├── update.ttl
│   │   │   ├── suspend.ttl
│   │   │   ├── activate.ttl
│   │   │   └── ... (15 more verbs)
│   │   └── types/
│   │       ├── user.ttl
│   │       ├── role.ttl
│   │       └── permission.ttl
│   │
│   ├── order/                         # Commerce team (25 verbs)
│   ├── inventory/                     # Supply chain team (30 verbs)
│   ├── shipping/                      # Logistics team (20 verbs)
│   ├── payment/                       # Payments team (18 verbs)
│   ├── report/                        # Analytics team (40 verbs)
│   ├── config/                        # Platform team (12 verbs)
│   └── ...                            # 28 more nouns
│
├── src/
│   ├── main.rs                        # 15 lines - just runs CLI
│   │
│   ├── generated/                     # ⚠️ REGENERATED - DO NOT EDIT
│   │   ├── mod.rs                     # Re-exports all nouns
│   │   ├── routing.rs                 # Clap command tree
│   │   └── nouns/
│   │       ├── user.rs                # UserCommands trait + types
│   │       ├── order.rs
│   │       └── ... (35 noun files)
│   │
│   ├── domain/                        # ✅ SAFE - Business logic lives here
│   │   ├── mod.rs
│   │   ├── user/
│   │   │   ├── mod.rs                 # impl UserCommands
│   │   │   ├── create.rs              # Create logic (500 lines)
│   │   │   ├── delete.rs              # Delete logic (300 lines)
│   │   │   ├── validation.rs          # Shared validation (800 lines)
│   │   │   └── ... (team's code)
│   │   ├── order/
│   │   └── ... (35 domain modules)
│   │
│   └── infrastructure/                # Cross-cutting concerns
│       ├── database.rs
│       ├── telemetry.rs
│       ├── feature_flags.rs
│       ├── circuit_breaker.rs
│       └── auth.rs
│
├── tests/
│   ├── generated/                     # Auto-generated test stubs
│   └── domain/                        # Hand-written domain tests
│
└── .github/
    ├── CODEOWNERS                     # Per-noun ownership
    └── workflows/
        ├── validate-ontology.yml      # RDF validation
        ├── regenerate-check.yml       # Verify generated/ is fresh
        └── breaking-change-review.yml # Extra review for *.breaking.ttl
```

---

## Key Takeaways

1. **Trait Boundary = Domain Protection**: Generated code defines traits, domain code implements them. Generator NEVER touches `src/domain/`.

2. **One File Per Verb = Zero Conflicts**: New commands are new files. No merge conflicts between teams.

3. **CODEOWNERS = Team Boundaries**: Each noun directory has explicit owners. Wrong team can't merge.

4. **Regenerate Freely**: `src/generated/` can be blown away and regenerated at any time. Domain logic survives.

5. **Compile-Time Enforcement**: If generated trait changes, domain impl fails to compile. No silent breakage.

6. **FMEA-Driven Controls**: Every high-RPN failure mode has a Poka-Yoke control.
