# ADR-006: Provisioning CLI Refactoring to Modular Architecture

**Status**: Implemented ✅
**Date**: 2025-09-30
**Authors**: Infrastructure Team
**Related**: ADR-001 (Project Structure), ADR-004 (Hybrid Architecture)

## Context

The main provisioning CLI script (`provisioning/core/nulib/provisioning`) had grown to **1,329 lines** with a massive 1,100+ line match statement handling all commands. This monolithic structure created multiple critical problems:

### Problems Identified

1. **Maintainability Crisis**
   - 54 command branches in one file
   - Code duplication: Flag handling repeated 50+ times
   - Hard to navigate: Finding specific command logic required scrolling through 1,000+ lines
   - Mixed concerns: Routing, validation, and execution all intertwined

2. **Development Friction**
   - Adding new commands required editing massive file
   - Testing was nearly impossible (monolithic, no isolation)
   - High cognitive load for contributors
   - Code review difficult due to file size

3. **Technical Debt**
   - 10+ lines of repetitive flag handling per command
   - No separation of concerns
   - Poor code reusability
   - Difficult to test individual command handlers

4. **User Experience Issues**
   - No bi-directional help system
   - Inconsistent command shortcuts
   - Help system not fully integrated

## Decision

We refactored the monolithic CLI into a **modular, domain-driven architecture** with the following structure:

```plaintext
provisioning/core/nulib/
├── provisioning (211 lines) ⬅️ 84% reduction
├── main_provisioning/
│   ├── flags.nu (139 lines) ⭐ Centralized flag handling
│   ├── dispatcher.nu (264 lines) ⭐ Command routing
│   ├── mod.nu (updated)
│   └── commands/ ⭐ Domain-focused handlers
│       ├── configuration.nu (316 lines)
│       ├── development.nu (72 lines)
│       ├── generation.nu (78 lines)
│       ├── infrastructure.nu (117 lines)
│       ├── orchestration.nu (64 lines)
│       ├── utilities.nu (157 lines)
│       └── workspace.nu (56 lines)
```plaintext

### Key Components

#### 1. Centralized Flag Handling (`flags.nu`)

Single source of truth for all flag parsing and argument building:

```nushell
export def parse_common_flags [flags: record]: nothing -> record
export def build_module_args [flags: record, extra: string = ""]: nothing -> string
export def set_debug_env [flags: record]
export def get_debug_flag [flags: record]: nothing -> string
```plaintext

**Benefits:**

- Eliminates 50+ instances of duplicate code
- Single place to add/modify flags
- Consistent flag handling across all commands
- Reduced from 10 lines to 3 lines per command handler

#### 2. Command Dispatcher (`dispatcher.nu`)

Central routing with 80+ command mappings:

```nushell
export def get_command_registry []: nothing -> record  # 80+ shortcuts
export def dispatch_command [args: list, flags: record]  # Main router
```plaintext

**Features:**

- Command registry with shortcuts (ws → workspace, orch → orchestrator, etc.)
- Bi-directional help support (`provisioning ws help` works)
- Domain-based routing (infrastructure, orchestration, development, etc.)
- Special command handling (create, delete, price, etc.)

#### 3. Domain Command Handlers (`commands/*.nu`)

Seven focused modules organized by domain:

| Module | Lines | Responsibility |
|--------|-------|----------------|
| `infrastructure.nu` | 117 | Server, taskserv, cluster, infra |
| `orchestration.nu` | 64 | Workflow, batch, orchestrator |
| `development.nu` | 72 | Module, layer, version, pack |
| `workspace.nu` | 56 | Workspace, template |
| `generation.nu` | 78 | Generate commands |
| `utilities.nu` | 157 | SSH, SOPS, cache, providers |
| `configuration.nu` | 316 | Env, show, init, validate |

Each handler:

- Exports `handle_<domain>_command` function
- Uses shared flag handling
- Provides error messages with usage hints
- Isolated and testable

## Architecture Principles

### 1. Separation of Concerns

- **Routing** → `dispatcher.nu`
- **Flag parsing** → `flags.nu`
- **Business logic** → `commands/*.nu`
- **Help system** → `help_system.nu` (existing)

### 2. Single Responsibility

Each module has ONE clear purpose:

- Command handlers execute specific domains
- Dispatcher routes to correct handler
- Flags module normalizes all inputs

### 3. DRY (Don't Repeat Yourself)

Eliminated repetition:

- Flag handling: 50+ instances → 1 function
- Command routing: Scattered logic → Command registry
- Error handling: Consistent across all domains

### 4. Open/Closed Principle

- Open for extension: Add new handlers easily
- Closed for modification: Core routing unchanged

### 5. Dependency Inversion

All handlers depend on abstractions (flag records, not concrete flags):

```nushell
# Handler signature
export def handle_infrastructure_command [
  command: string
  ops: string
  flags: record  # ⬅️ Abstraction, not concrete flags
]
```plaintext

## Implementation Details

### Migration Path (Completed in 2 Phases)

**Phase 1: Foundation**

1. ✅ Created `commands/` directory structure
2. ✅ Created `flags.nu` with common flag handling
3. ✅ Created initial command handlers (infrastructure, utilities, configuration)
4. ✅ Created `dispatcher.nu` with routing logic
5. ✅ Refactored main file (1,329 → 211 lines)
6. ✅ Tested basic functionality

**Phase 2: Completion**

1. ✅ Fixed bi-directional help (`provisioning ws help` now works)
2. ✅ Created remaining handlers (orchestration, development, workspace, generation)
3. ✅ Removed duplicate code from dispatcher
4. ✅ Added comprehensive test suite
5. ✅ Verified all shortcuts work

### Bi-directional Help System

Users can now access help in multiple ways:

```bash
# All these work equivalently:
provisioning help workspace
provisioning workspace help  # ⬅️ NEW: Bi-directional
provisioning ws help         # ⬅️ NEW: With shortcuts
provisioning help ws         # ⬅️ NEW: Shortcut in help
```plaintext

**Implementation:**

```nushell
# Intercept "command help" → "help command"
let first_op = if ($ops_list | length) > 0 { ($ops_list | get 0) } else { "" }
if $first_op in ["help" "h"] {
  exec $"($env.PROVISIONING_NAME)" help $task --notitles
}
```plaintext

### Command Shortcuts

Comprehensive shortcut system with 30+ mappings:

**Infrastructure:**

- `s` → `server`
- `t`, `task` → `taskserv`
- `cl` → `cluster`
- `i` → `infra`

**Orchestration:**

- `wf`, `flow` → `workflow`
- `bat` → `batch`
- `orch` → `orchestrator`

**Development:**

- `mod` → `module`
- `lyr` → `layer`

**Workspace:**

- `ws` → `workspace`
- `tpl`, `tmpl` → `template`

## Testing

Comprehensive test suite created (`tests/test_provisioning_refactor.nu`):

### Test Coverage

- ✅ Main help display
- ✅ Category help (infrastructure, orchestration, development, workspace)
- ✅ Bi-directional help routing
- ✅ All command shortcuts
- ✅ Category shortcut help
- ✅ Command routing to correct handlers

### Test Results

```plaintext
📋 Testing main help... ✅
📋 Testing category help... ✅
🔄 Testing bi-directional help... ✅
⚡ Testing command shortcuts... ✅
📚 Testing category shortcut help... ✅
🎯 Testing command routing... ✅

📊 TEST RESULTS: 6 passed, 0 failed
```plaintext

## Results

### Quantitative Improvements

| Metric | Before | After | Improvement |
|--------|--------|-------|-------------|
| **Main file size** | 1,329 lines | 211 lines | **84% reduction** |
| **Command handler** | 1 massive match (1,100+ lines) | 7 focused modules | **Domain separation** |
| **Flag handling** | Repeated 50+ times | 1 function | **98% duplication removal** |
| **Code per command** | 10 lines | 3 lines | **70% reduction** |
| **Modules count** | 1 monolith | 9 modules | **Modular architecture** |
| **Test coverage** | None | 6 test groups | **Comprehensive testing** |

### Qualitative Improvements

**Maintainability**

- ✅ Easy to find specific command logic
- ✅ Clear separation of concerns
- ✅ Self-documenting structure
- ✅ Focused modules (< 320 lines each)

**Extensibility**

- ✅ Add new commands: Just update appropriate handler
- ✅ Add new flags: Single function update
- ✅ Add new shortcuts: Update command registry
- ✅ No massive file edits required

**Testability**

- ✅ Isolated command handlers
- ✅ Mockable dependencies
- ✅ Test individual domains
- ✅ Fast test execution

**Developer Experience**

- ✅ Lower cognitive load
- ✅ Faster onboarding
- ✅ Easier code review
- ✅ Better IDE navigation

## Trade-offs

### Advantages

1. **Dramatically reduced complexity**: 84% smaller main file
2. **Better organization**: Domain-focused modules
3. **Easier testing**: Isolated, testable units
4. **Improved maintainability**: Clear structure, less duplication
5. **Enhanced UX**: Bi-directional help, shortcuts
6. **Future-proof**: Easy to extend

### Disadvantages

1. **More files**: 1 file → 9 files (but smaller, focused)
2. **Module imports**: Need to import multiple modules (automated via mod.nu)
3. **Learning curve**: New structure requires documentation (this ADR)

**Decision**: Advantages significantly outweigh disadvantages.

## Examples

### Before: Repetitive Flag Handling

```nushell
"server" => {
  let use_check = if $check { "--check "} else { "" }
  let use_yes = if $yes { "--yes" } else { "" }
  let use_wait = if $wait { "--wait" } else { "" }
  let use_keepstorage = if $keepstorage { "--keepstorage "} else { "" }
  let str_infra = if $infra != null  { $"--infra ($infra) "} else { "" }
  let str_outfile = if $outfile != null  { $"--outfile ($outfile) "} else { "" }
  let str_out = if $out != null  { $"--out ($out) "} else { "" }
  let arg_include_notuse = if $include_notuse { $"--include_notuse "} else { "" }
  run_module $"($str_ops) ($str_infra) ($use_check)..." "server" --exec
}
```plaintext

### After: Clean, Reusable

```nushell
def handle_server [ops: string, flags: record] {
  let args = build_module_args $flags $ops
  run_module $args "server" --exec
}
```plaintext

**Reduction: 10 lines → 3 lines (70% reduction)**

## Future Considerations

### Potential Enhancements

1. **Unit test expansion**: Add tests for each command handler
2. **Integration tests**: End-to-end workflow tests
3. **Performance profiling**: Measure routing overhead (expected to be negligible)
4. **Documentation generation**: Auto-generate docs from handlers
5. **Plugin architecture**: Allow third-party command extensions

### Migration Guide for Contributors

See `docs/development/COMMAND_HANDLER_GUIDE.md` for:

- How to add new commands
- How to modify existing handlers
- How to add new shortcuts
- Testing guidelines

## Related Documentation

- **Architecture Overview**: `docs/architecture/system-overview.md`
- **Developer Guide**: `docs/development/COMMAND_HANDLER_GUIDE.md`
- **Main Project Docs**: `CLAUDE.md` (updated with new structure)
- **Test Suite**: `tests/test_provisioning_refactor.nu`

## Conclusion

This refactoring transforms the provisioning CLI from a monolithic, hard-to-maintain script into a modular, well-organized system following software engineering best practices. The 84% reduction in main file size, elimination of code duplication, and comprehensive test coverage position the project for sustainable long-term growth.

The new architecture enables:

- **Faster development**: Add commands in minutes, not hours
- **Better quality**: Isolated testing catches bugs early
- **Easier maintenance**: Clear structure reduces cognitive load
- **Enhanced UX**: Shortcuts and bi-directional help improve usability

**Status**: Successfully implemented and tested. All commands operational. Ready for production use.

---

*This ADR documents a major architectural improvement completed on 2025-09-30.*
