# ADR-006: Provisioning CLI Refactoring to Modular Architecture\n\n**Status**: Implemented ✅\n**Date**: 2025-09-30\n**Authors**: Infrastructure Team\n**Related**: ADR-001 (Project Structure), ADR-004 (Hybrid Architecture)\n\n## Context\n\nThe main provisioning CLI script (`provisioning/core/nulib/provisioning`) had grown to\n**1,329 lines** with a massive 1,100+ line match statement handling all commands. This\nmonolithic structure created multiple critical problems:\n\n### Problems Identified\n\n1. **Maintainability Crisis**\n   - 54 command branches in one file\n   - Code duplication: Flag handling repeated 50+ times\n   - Hard to navigate: Finding specific command logic required scrolling through 1,000+ lines\n   - Mixed concerns: Routing, validation, and execution all intertwined\n\n2. **Development Friction**\n   - Adding new commands required editing massive file\n   - Testing was nearly impossible (monolithic, no isolation)\n   - High cognitive load for contributors\n   - Code review difficult due to file size\n\n3. **Technical Debt**\n   - 10+ lines of repetitive flag handling per command\n   - No separation of concerns\n   - Poor code reusability\n   - Difficult to test individual command handlers\n\n4. **User Experience Issues**\n   - No bi-directional help system\n   - Inconsistent command shortcuts\n   - Help system not fully integrated\n\n## Decision\n\nWe refactored the monolithic CLI into a **modular, domain-driven architecture** with the following structure:\n\n```\nprovisioning/core/nulib/\n├── provisioning (211 lines) ⬅️ 84% reduction\n├── main_provisioning/\n│   ├── flags.nu (139 lines) ⭐ Centralized flag handling\n│   ├── dispatcher.nu (264 lines) ⭐ Command routing\n│   ├── mod.nu (updated)\n│   └── commands/ ⭐ Domain-focused handlers\n│       ├── configuration.nu (316 lines)\n│       ├── development.nu (72 lines)\n│       ├── generation.nu (78 lines)\n│       ├── infrastructure.nu (117 lines)\n│       ├── orchestration.nu (64 lines)\n│       ├── utilities.nu (157 lines)\n│       └── workspace.nu (56 lines)\n```\n\n### Key Components\n\n#### 1. Centralized Flag Handling (`flags.nu`)\n\nSingle source of truth for all flag parsing and argument building:\n\n```\nexport def parse_common_flags [flags: record]: nothing -> record\nexport def build_module_args [flags: record, extra: string = ""]: nothing -> string\nexport def set_debug_env [flags: record]\nexport def get_debug_flag [flags: record]: nothing -> string\n```\n\n**Benefits:**\n\n- Eliminates 50+ instances of duplicate code\n- Single place to add/modify flags\n- Consistent flag handling across all commands\n- Reduced from 10 lines to 3 lines per command handler\n\n#### 2. Command Dispatcher (`dispatcher.nu`)\n\nCentral routing with 80+ command mappings:\n\n```\nexport def get_command_registry []: nothing -> record  # 80+ shortcuts\nexport def dispatch_command [args: list, flags: record]  # Main router\n```\n\n**Features:**\n\n- Command registry with shortcuts (ws → workspace, orch → orchestrator, etc.)\n- Bi-directional help support (`provisioning ws help` works)\n- Domain-based routing (infrastructure, orchestration, development, etc.)\n- Special command handling (create, delete, price, etc.)\n\n#### 3. Domain Command Handlers (`commands/*.nu`)\n\nSeven focused modules organized by domain:\n\n| Module | Lines | Responsibility |\n| -------- | ------- | ---------------- |\n| `infrastructure.nu` | 117 | Server, taskserv, cluster, infra |\n| `orchestration.nu` | 64 | Workflow, batch, orchestrator |\n| `development.nu` | 72 | Module, layer, version, pack |\n| `workspace.nu` | 56 | Workspace, template |\n| `generation.nu` | 78 | Generate commands |\n| `utilities.nu` | 157 | SSH, SOPS, cache, providers |\n| `configuration.nu` | 316 | Env, show, init, validate |\n\nEach handler:\n\n- Exports `handle_<domain>_command` function\n- Uses shared flag handling\n- Provides error messages with usage hints\n- Isolated and testable\n\n## Architecture Principles\n\n### 1. Separation of Concerns\n\n- **Routing** → `dispatcher.nu`\n- **Flag parsing** → `flags.nu`\n- **Business logic** → `commands/*.nu`\n- **Help system** → `help_system.nu` (existing)\n\n### 2. Single Responsibility\n\nEach module has ONE clear purpose:\n\n- Command handlers execute specific domains\n- Dispatcher routes to correct handler\n- Flags module normalizes all inputs\n\n### 3. DRY (Don't Repeat Yourself)\n\nEliminated repetition:\n\n- Flag handling: 50+ instances → 1 function\n- Command routing: Scattered logic → Command registry\n- Error handling: Consistent across all domains\n\n### 4. Open/Closed Principle\n\n- Open for extension: Add new handlers easily\n- Closed for modification: Core routing unchanged\n\n### 5. Dependency Inversion\n\nAll handlers depend on abstractions (flag records, not concrete flags):\n\n```\n# Handler signature\nexport def handle_infrastructure_command [\n  command: string\n  ops: string\n  flags: record  # ⬅️ Abstraction, not concrete flags\n]\n```\n\n## Implementation Details\n\n### Migration Path (Completed in 2 Phases)\n\n**Phase 1: Foundation**\n\n1. ✅ Created `commands/` directory structure\n2. ✅ Created `flags.nu` with common flag handling\n3. ✅ Created initial command handlers (infrastructure, utilities, configuration)\n4. ✅ Created `dispatcher.nu` with routing logic\n5. ✅ Refactored main file (1,329 → 211 lines)\n6. ✅ Tested basic functionality\n\n**Phase 2: Completion**\n\n1. ✅ Fixed bi-directional help (`provisioning ws help` now works)\n2. ✅ Created remaining handlers (orchestration, development, workspace, generation)\n3. ✅ Removed duplicate code from dispatcher\n4. ✅ Added comprehensive test suite\n5. ✅ Verified all shortcuts work\n\n### Bi-directional Help System\n\nUsers can now access help in multiple ways:\n\n```\n# All these work equivalently:\nprovisioning help workspace\nprovisioning workspace help  # ⬅️ NEW: Bi-directional\nprovisioning ws help         # ⬅️ NEW: With shortcuts\nprovisioning help ws         # ⬅️ NEW: Shortcut in help\n```\n\n**Implementation:**\n\n```\n# Intercept "command help" → "help command"\nlet first_op = if ($ops_list | length) > 0 { ($ops_list | get 0) } else { "" }\nif $first_op in ["help" "h"] {\n  exec $"($env.PROVISIONING_NAME)" help $task --notitles\n}\n```\n\n### Command Shortcuts\n\nComprehensive shortcut system with 30+ mappings:\n\n**Infrastructure:**\n\n- `s` → `server`\n- `t`, `task` → `taskserv`\n- `cl` → `cluster`\n- `i` → `infra`\n\n**Orchestration:**\n\n- `wf`, `flow` → `workflow`\n- `bat` → `batch`\n- `orch` → `orchestrator`\n\n**Development:**\n\n- `mod` → `module`\n- `lyr` → `layer`\n\n**Workspace:**\n\n- `ws` → `workspace`\n- `tpl`, `tmpl` → `template`\n\n## Testing\n\nComprehensive test suite created (`tests/test_provisioning_refactor.nu`):\n\n### Test Coverage\n\n- ✅ Main help display\n- ✅ Category help (infrastructure, orchestration, development, workspace)\n- ✅ Bi-directional help routing\n- ✅ All command shortcuts\n- ✅ Category shortcut help\n- ✅ Command routing to correct handlers\n\n### Test Results\n\n```\n📋 Testing main help... ✅\n📋 Testing category help... ✅\n🔄 Testing bi-directional help... ✅\n⚡ Testing command shortcuts... ✅\n📚 Testing category shortcut help... ✅\n🎯 Testing command routing... ✅\n\n📊 TEST RESULTS: 6 passed, 0 failed\n```\n\n## Results\n\n### Quantitative Improvements\n\n| Metric | Before | After | Improvement |\n| -------- | -------- | ------- | ------------- |\n| **Main file size** | 1,329 lines | 211 lines | **84% reduction** |\n| **Command handler** | 1 massive match (1,100+ lines) | 7 focused modules | **Domain separation** |\n| **Flag handling** | Repeated 50+ times | 1 function | **98% duplication removal** |\n| **Code per command** | 10 lines | 3 lines | **70% reduction** |\n| **Modules count** | 1 monolith | 9 modules | **Modular architecture** |\n| **Test coverage** | None | 6 test groups | **Comprehensive testing** |\n\n### Qualitative Improvements\n\n**Maintainability**\n\n- ✅ Easy to find specific command logic\n- ✅ Clear separation of concerns\n- ✅ Self-documenting structure\n- ✅ Focused modules (< 320 lines each)\n\n**Extensibility**\n\n- ✅ Add new commands: Just update appropriate handler\n- ✅ Add new flags: Single function update\n- ✅ Add new shortcuts: Update command registry\n- ✅ No massive file edits required\n\n**Testability**\n\n- ✅ Isolated command handlers\n- ✅ Mockable dependencies\n- ✅ Test individual domains\n- ✅ Fast test execution\n\n**Developer Experience**\n\n- ✅ Lower cognitive load\n- ✅ Faster onboarding\n- ✅ Easier code review\n- ✅ Better IDE navigation\n\n## Trade-offs\n\n### Advantages\n\n1. **Dramatically reduced complexity**: 84% smaller main file\n2. **Better organization**: Domain-focused modules\n3. **Easier testing**: Isolated, testable units\n4. **Improved maintainability**: Clear structure, less duplication\n5. **Enhanced UX**: Bi-directional help, shortcuts\n6. **Future-proof**: Easy to extend\n\n### Disadvantages\n\n1. **More files**: 1 file → 9 files (but smaller, focused)\n2. **Module imports**: Need to import multiple modules (automated via mod.nu)\n3. **Learning curve**: New structure requires documentation (this ADR)\n\n**Decision**: Advantages significantly outweigh disadvantages.\n\n## Examples\n\n### Before: Repetitive Flag Handling\n\n```\n"server" => {\n  let use_check = if $check { "--check "} else { "" }\n  let use_yes = if $yes { "--yes" } else { "" }\n  let use_wait = if $wait { "--wait" } else { "" }\n  let use_keepstorage = if $keepstorage { "--keepstorage "} else { "" }\n  let str_infra = if $infra != null  { $"--infra ($infra) "} else { "" }\n  let str_outfile = if $outfile != null  { $"--outfile ($outfile) "} else { "" }\n  let str_out = if $out != null  { $"--out ($out) "} else { "" }\n  let arg_include_notuse = if $include_notuse { $"--include_notuse "} else { "" }\n  run_module $"($str_ops) ($str_infra) ($use_check)..." "server" --exec\n}\n```\n\n### After: Clean, Reusable\n\n```\ndef handle_server [ops: string, flags: record] {\n  let args = build_module_args $flags $ops\n  run_module $args "server" --exec\n}\n```\n\n**Reduction: 10 lines → 3 lines (70% reduction)**\n\n## Future Considerations\n\n### Potential Enhancements\n\n1. **Unit test expansion**: Add tests for each command handler\n2. **Integration tests**: End-to-end workflow tests\n3. **Performance profiling**: Measure routing overhead (expected to be negligible)\n4. **Documentation generation**: Auto-generate docs from handlers\n5. **Plugin architecture**: Allow third-party command extensions\n\n### Migration Guide for Contributors\n\nSee `docs/development/COMMAND_HANDLER_GUIDE.md` for:\n\n- How to add new commands\n- How to modify existing handlers\n- How to add new shortcuts\n- Testing guidelines\n\n## Related Documentation\n\n- **Architecture Overview**: `docs/architecture/system-overview.md`\n- **Developer Guide**: `docs/development/COMMAND_HANDLER_GUIDE.md`\n- **Main Project Docs**: `CLAUDE.md` (updated with new structure)\n- **Test Suite**: `tests/test_provisioning_refactor.nu`\n\n## Conclusion\n\nThis refactoring transforms the provisioning CLI from a monolithic, hard-to-maintain script into a modular, well-organized system following software\nengineering best practices. The 84% reduction in main file size, elimination of code duplication, and comprehensive test coverage position the project\nfor sustainable long-term growth.\n\nThe new architecture enables:\n\n- **Faster development**: Add commands in minutes, not hours\n- **Better quality**: Isolated testing catches bugs early\n- **Easier maintenance**: Clear structure reduces cognitive load\n- **Enhanced UX**: Shortcuts and bi-directional help improve usability\n\n**Status**: Successfully implemented and tested. All commands operational. Ready for production use.\n\n---\n\n*This ADR documents a major architectural improvement completed on 2025-09-30.*
