provisioning/docs/src/architecture/adr/adr-018-help-system-fluent-integration.md

282 lines
9.2 KiB
Markdown
Raw Normal View History

2026-01-14 01:56:30 +00:00
# ADR-018: Help System Fluent Integration & Data-Driven Architecture
**Status**: Proposed
**Date**: 2026-01-13
**Author**: Architecture Team
**Supersedes**: Hardcoded help strings in `main_provisioning/help_system.nu`
## Context
The current help system in `main_provisioning/help_system.nu` (1303 lines) consists almost entirely of hardcoded string concatenation with embedded
ANSI formatting codes:
```
def help-infrastructure [] {
print "╔════════════════════════════════════════════════════╗"
print "║ SERVER & INFRASTRUCTURE ║"
print "╚════════════════════════════════════════════════════╝"
}
```
**Current Problems**:
1. **No Internationalization**: Help text trapped in English-only code
2. **Hard to Maintain**: Updating text requires editing Nushell code
3. **Mixed Concerns**: Content (strings) mixed with presentation (ANSI codes)
4. **No Hot-Reload**: Changes require recompilation
5. **Difficult to Test**: String content buried in function definitions
## Problem Statement
**Metrics**:
- 1303 lines of code-embedded help text
- 17 help categories with 65 strings total
- All help functions manually maintained
- No separation of data from presentation
## Decision
Implement **Data-Driven Help with Mozilla Fluent Integration**:
1. Extract help content to Fluent files (`.ftl` format)
2. Support multilingual help (English base, Spanish translations)
3. Implement runtime language resolution via `LANG` environment variable
4. Reduce help_system.nu to wrapper functions only
### Architecture
```
Help Content (Fluent Files)
├─ en-US/help.ftl (65 strings - English base)
└─ es-ES/help.ftl (65 strings - Spanish translations)
Language Detection & Loading
├─ Check LANG environment variable
├─ Load appropriate Fluent file
└─ Implement fallback chain (es-ES → en-US)
Help System Wrapper
├─ help-main [] - Display main menu
├─ help-infrastructure [] - Infrastructure category
├─ help-orchestration [] - Orchestration category
└─ help-setup [] - Setup category
User Interface
├─ LANG=en_US provisioning help infrastructure
└─ LANG=es_ES provisioning help infrastructure
```
## Implementation
### 1. Fluent File Structure
**en-US/help.ftl**:
```
help-main-title = PROVISIONING SYSTEM
help-main-subtitle = Layered Infrastructure Automation
help-main-categories = COMMAND CATEGORIES
help-main-categories-hint = Use 'provisioning help <category>' for details
help-main-infrastructure-name = infrastructure
help-main-infrastructure-desc = Server, taskserv, cluster, VM, and infra management
help-main-orchestration-name = orchestration
help-main-orchestration-desc = Workflow, batch operations, and orchestrator control
help-infrastructure-title = SERVER & INFRASTRUCTURE
help-infra-server = Server Operations
help-infra-server-create = Create a new server
help-infra-server-list = List all servers
help-infra-server-status = Show server status
help-infra-taskserv = TaskServ Management
help-infra-taskserv-create = Deploy taskserv to server
help-infra-cluster = Cluster Management
help-infra-vm = Virtual Machine Operations
help-orchestration-title = ORCHESTRATION & WORKFLOWS
help-orch-control = Orchestrator Management
help-orch-start = Start orchestrator [--background]
help-orch-workflows = Single Task Workflows
help-orch-batch = Multi-Provider Batch Operations
```
**es-ES/help.ftl** (Spanish translations):
```
help-main-title = SISTEMA DE PROVISIÓN
help-main-subtitle = Automatización de Infraestructura por Capas
help-main-categories = CATEGORÍAS DE COMANDOS
help-main-categories-hint = Use 'provisioning help <categoría>' para más detalles
help-main-infrastructure-name = infraestructura
help-main-infrastructure-desc = Gestión de servidores, taskserv, clusters, VM e infraestructura
help-main-orchestration-name = orquestación
help-main-orchestration-desc = Flujos de trabajo, operaciones por lotes y control del orquestador
help-infrastructure-title = SERVIDOR E INFRAESTRUCTURA
help-infra-server = Operaciones de Servidor
help-infra-server-create = Crear un nuevo servidor
help-infra-server-list = Listar todos los servidores
help-infra-server-status = Mostrar estado del servidor
help-infra-taskserv = Gestión de TaskServ
help-infra-taskserv-create = Desplegar taskserv en servidor
help-infra-cluster = Gestión de Clusters
help-infra-vm = Operaciones de Máquinas Virtuales
help-orchestration-title = ORQUESTACIÓN Y FLUJOS DE TRABAJO
help-orch-control = Gestión del Orquestador
help-orch-start = Iniciar orquestador [--background]
help-orch-workflows = Flujos de Trabajo de Tarea Única
help-orch-batch = Operaciones por Lotes Multi-Proveedor
```
### 2. Fluent Loading in Nushell
```
def load-fluent-file [category: string] {
let lang = ($env.LANG? | default "en_US" | str replace "_" "-")
let fluent_path = $"provisioning/locales/($lang)/help.ftl"
# Parse Fluent file and extract strings for category
# Fallback to en-US if lang not available
}
```
### 3. Help System Wrapper
```
export def help-infrastructure [] {
let strings = (load-fluent-file "infrastructure")
# Apply formatting and render
print $"╔════════════════════════════════════════════════════╗"
print $"║ ($strings.title | str upcase) ║"
print $"╚════════════════════════════════════════════════════╝"
}
```
## Consequences
### Positive
- **Internationalization Ready**: Easy to add new languages (Portuguese, French, Japanese)
- **Data/Presentation Separation**: Content in Fluent, formatting in Nushell
- **Maintainability**: Edit Fluent files, not Nushell code
- **Hot-Reload Support**: Can update help text without recompilation
- **Testing**: Help content testable independently from rendering
- **Code Reduction**: 1303 lines → ~50 lines (wrapper) + ~700 lines (Fluent data)
### Negative
- **Tool Complexity**: Need Fluent parser and loader
- **Fallback Chain Management**: Must handle missing translations gracefully
- **Performance**: File I/O for loading translations (mitigated by caching)
## Integration Strategy
### Phase 1: Infrastructure & Extraction
- ✅ Create `provisioning/locales/` directory structure
- ✅ Create `i18n-config.toml` with locale configuration
- ✅ Extract strings to `en-US/help.ftl` (65 strings)
- ✅ Create Spanish translations `es-ES/help.ftl`
### Phase 2: Integration (This Task)
- [ ] Modify `help_system.nu` to load from Fluent
- [ ] Implement language detection (`$env.LANG`)
- [ ] Implement fallback chain logic
- [ ] Test with `LANG=en_US` and `LANG=es_ES`
### Phase 3: Validation & Documentation
- [ ] Comprehensive integration tests
- [ ] Performance benchmarks
- [ ] Documentation for adding new languages
- [ ] Examples in provisioning/docs/
## Language Resolution Flow
```
1. Check LANG environment variable
LANG=es_ES.UTF-8 → extract "es_ES" or "es-ES"
2. Check if locale file exists
provisioning/locales/es-ES/help.ftl exists? → YES
3. Load locale file
Parse and extract help strings
4. On missing key:
Check fallback chain in i18n-config.toml
es-ES → en-US
5. Render with formatting
Apply ANSI codes, boxes, alignment
```
## Testing Strategy
### Unit Tests
```
# Test language detection
LANG=en_US provisioning help infrastructure
# Expected: English output
LANG=es_ES provisioning help infrastructure
# Expected: Spanish output
LANG=fr_FR provisioning help infrastructure
# Expected: Fallback to English (fr-FR not available)
```
## File Structure
```
provisioning/
├── locales/
│ ├── i18n-config.toml # Locale metadata & fallback chains
│ ├── en-US/
│ │ └── help.ftl # 65 English help strings
│ └── es-ES/
│ └── help.ftl # 65 Spanish help strings
└── core/nulib/main_provisioning/
└── help_system.nu # ~50 lines (wrapper only)
```
## Configuration
**i18n-config.toml** defines:
```
[locales]
default = "en-US"
fallback = "en-US"
[locales.en-US]
name = "English (United States)"
[locales.es-ES]
name = "Spanish (Spain)"
[fallback_chains]
es-ES = ["en-US"]
```
## Related ADRs
- **ADR-010**: Configuration Format Strategy
- **ADR-011**: Nickel Migration
- **ADR-013**: TypeDialog Integration (forms also use Fluent)
## Open Questions
1. Should help strings support Fluent attributes for metadata?
2. Should we implement Fluent caching for performance?
3. How do we handle dynamic help (commands not in Fluent)?
4. Should help system auto-update when Fluent files change?
## References
- Mozilla Fluent: [https://projectfluent.org/](https://projectfluent.org/)
- Fluent Syntax: [https://projectfluent.org/fluent/guide/](https://projectfluent.org/fluent/guide/)
- Nushell 0.109 Guidelines: `.claude/guidelines/nushell.md`
- Current Help Implementation: `provisioning/core/nulib/main_provisioning/help_system.nu`
- Fluent Files: `provisioning/locales/{en-US,es-ES}/help.ftl`