syntaxis/docs/adr/adr-001-wrapper-architecture-strategy.md
Jesús Pérez 9cef9b8d57 refactor: consolidate configuration directories
Merge _configs/ into config/ for single configuration directory.
Update all path references.

Changes:
- Move _configs/* to config/
- Update .gitignore for new patterns
- No code references to _configs/ found

Impact: -1 root directory (layout_conventions.md compliance)
2025-12-26 18:36:23 +00:00

543 lines
14 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# ADR-001: Wrapper Architecture Strategy
**Date**: 2025-11-17
**Status**: PROPOSED
**Author**: Architecture Review
**Scope**: Installation and execution wrappers in SYNTAXIS
---
## Problem Statement
SYNTAXIS uses two different wrapper patterns:
1. **Binary Execution Wrappers** (existing `install-syntaxis`):
- Bash → NuShell → Rust (3 layers)
- Handles config discovery and injection
- Used by: `syntaxis-cli`, `syntaxis-tui`, `syntaxis-api`
2. **Installation Wrapper** (new `provision.sh`):
- Bash orchestrator
- Wraps `install.sh` + `setup-config.sh`
- Used by: Bundle users during first-time installation
**Question**: Should both patterns be used? Or should they follow different strategies?
---
## Analysis Framework
### Cost-Benefit Model for Wrappers
```
Wrapper Value = Frequency × (User Burden Saved) × Maintenance Complexity
Where:
- Frequency: How often is this called? (per session, per day, per lifetime)
- User Burden: What pain does it eliminate? (typing, remembering steps, errors)
- Complexity: How many layers/moving parts? (1 layer vs 3 layers)
```
---
## Pattern 1: Binary Execution Wrappers (install-syntaxis)
### Current Implementation
```
Shell Invocation: syntaxis-cli status
[Layer 1] Bash Wrapper (~212 bytes)
└─ Sets: NU_LIB_DIRS="$HOME/.config/syntaxis/scripts"
└─ Calls: nu "$HOME/.config/syntaxis/scripts/syntaxis-cli.nu" "status"
[Layer 2] NuShell Wrapper (~2.2 KB)
└─ Imports: syntaxis-lib.nu, syntaxis-cli-lib.nu
└─ Discovers: Config file location
└─ Injects: --config flag automatically
└─ Calls: ~/.cargo/bin/syntaxis-cli.real --config ~/.config/syntaxis/config.toml status
[Layer 3] Real Binary (7.2 MB)
└─ Executes: With config path already provided
```
### Why This Pattern?
#### Without wrapper:
```bash
# Every single invocation requires:
$ syntaxis-cli --config ~/.config/syntaxis/config.toml status
$ syntaxis-cli --config ~/.config/syntaxis/config.toml project list
$ syntaxis-cli --config ~/.config/syntaxis/config.toml task create "name"
# ... repeated 100s of times per day
```
**User Experience Problem**:
- ❌ Users must remember config path
- ❌ Config path is long and error-prone
- ❌ Repetitive typing (every invocation)
- ❌ Non-obvious that `--config` is required
#### With wrapper:
```bash
# Clean, simple invocations:
$ syntaxis-cli status
$ syntaxis-cli project list
$ syntaxis-cli task create "name"
# Config is automatic!
```
**User Experience Solution**:
- ✅ Config path is invisible
- ✅ Users follow Unix conventions
- ✅ No typing overhead
- ✅ Feels like a normal CLI tool
### Wrapper Value Calculation
```
Frequency: ~100 invocations per active session
= Multiple times per hour, thousands per week
User Burden Saved:
- Per invocation: ~50 characters of typing
- Per session: ~5,000 characters typed
- Per year: ~2.6 million characters saved
- Mental load: No need to remember config path
Maintenance Complexity: 3 layers
- But: Stable (rarely changed)
- And: All in scripts (easy to modify)
- Risk: Moderate (can bypass via .real)
VERDICT: Value >> Complexity Cost
RECOMMENDATION: KEEP THIS PATTERN ✅
```
### Existing File Locations
```
Installation Script:
scripts/install-syntaxis (bash wrapper)
scripts/install-syntaxis.nu (NuShell orchestrator)
Deployed Wrappers:
~/.cargo/bin/syntaxis-cli (bash wrapper)
~/.cargo/bin/syntaxis-tui (bash wrapper)
~/.cargo/bin/syntaxis-api (bash wrapper)
NuShell Wrappers:
~/.config/syntaxis/scripts/syntaxis-cli.nu (2.2 KB)
~/.config/syntaxis/scripts/syntaxis-tui.nu (2.2 KB)
~/.config/syntaxis/scripts/syntaxis-api.nu (3.6 KB)
Shared Libraries:
~/.config/syntaxis/scripts/syntaxis-lib.nu (1.1 KB)
~/.config/syntaxis/scripts/syntaxis-cli-lib.nu (1.5 KB)
~/.config/syntaxis/scripts/syntaxis-tui-lib.nu (743 B)
~/.config/syntaxis/scripts/syntaxis-api-lib.nu (2.2 KB)
Real Binaries:
~/.cargo/bin/syntaxis-cli.real (7.2 MB)
~/.cargo/bin/syntaxis-tui.real (3.9 MB)
~/.cargo/bin/syntaxis-api.real (8.3 MB)
```
---
## Pattern 2: Installation Wrapper (provision.sh)
### Current Implementation
```
User: ./provision full
[Layer 1] Bash Wrapper (provision.sh)
└─ Detects: Shell availability (bash/zsh/NuShell)
└─ Offers: Interactive menu OR one-step install
└─ Orchestrates: install.sh → setup-config.sh
└─ Calls: Either install or install + config
[Layer 2A] Install Script (install.sh)
└─ Installs: Binaries to ~/.local/bin/
└─ Updates: Shell PATH
└─ Creates: Data directories
[Layer 2B] Config Script (setup-config.sh)
└─ Creates: TOML configs
└─ Interactive: Prompts user for options
└─ Deploys: Configs to ~/.config/syntaxis/
```
### Why This Pattern Was Created?
**Intended Value**:
1. Make installation easier for beginners
2. One command instead of two
3. Guided interactive experience
**Reality Check**:
- Users run installer: **Once** (during first installation)
- Users run binaries: **100s of times** (during normal use)
### Wrapper Value Calculation
```
Frequency: ~1 invocation per user
= Only once during initial setup
= Not multiple times per session
User Burden Saved:
- Per user: Saves 1 command typing (~50 characters)
- Per year: ~50 characters saved (one time!)
- Mental load: Not a problem (one-time activity)
Maintenance Complexity: 2+ layers
- Scripts call other scripts
- PATH updates, permission handling, error recovery
- Three different code paths (install only, config only, both)
- Need to handle shell detection and options
User Confusion:
- "Which command should I use?"
- install.sh or provision.sh?
- provision install vs provision config vs provision full?
- Documentation burden (explain 3 paths)
VERDICT: Value << Complexity Cost
RECOMMENDATION: REMOVE THIS PATTERN ❌
```
### Why This Pattern Is Problematic
#### 1. One-Time Usage
- Wrapper is called **once** during entire user lifetime
- Binary wrappers are called **100s of times** per day
- One-time benefit doesn't justify ongoing complexity
#### 2. Confusion
```
Bundle contains:
provision.sh ← Is this the way?
install.sh ← Or this?
setup-config.sh ← Or this?
Users think: "Which command do I run?"
"What's the difference?"
"Which one is recommended?"
```
**Documentation Burden**: Must explain 3 approaches instead of 1
#### 3. Not Optional = Misleading
```
Current Status:
provision.sh is marked "optional"
BUT it's included in bundle
BUT its necessity is unclear
BUT install.sh works independently
Result: Confusing, not truly optional
```
#### 4. Maintenance Burden
```
Code Paths to Test:
Path 1: provision full (both steps)
Path 2: provision install (binaries only)
Path 3: provision config (config only)
Path 4: bash install.sh (direct script)
Path 5: bash setup-config.sh (direct script)
Path 6: Manual (copy files) (user DIY)
Testing Matrix:
× 3 shells (bash, zsh, NuShell)
× 4 platforms (Linux, macOS x2, Windows)
× Multiple scenarios
= Significant test burden for one-time use
```
#### 5. Violates SYNTAXIS Philosophy
From CLAUDE.md:
- ✅ "Modular with features to add or avoid"
- ✅ "No unnecessary complexity"
- ✅ "Users understand what's happening"
Wrapper violates:
- ❌ Not modular (orchestrates other scripts)
- ❌ Unnecessary complexity (for one-time use)
- ❌ Less transparent (abstraction not needed)
---
## Comparison: Binary Wrappers vs Installation Wrapper
| Aspect | Binary Wrappers | Installation Wrapper |
|--------|-----------------|----------------------|
| **Frequency** | 100s per day | Once per lifetime |
| **User Pain** | Config path typing (repetitive) | Two commands to type (one-time) |
| **Value/Complexity** | High | Low |
| **Justification** | Strong | Weak |
| **Maintenance** | Stable/low | Medium/scattered |
| **Transparency** | Can bypass via .real | No escape hatch |
| **Philosophy** | Transparent execution | Abstraction |
---
## Decision Criteria
### When Wrappers Are Justified
```
✅ Wrappers are justified when:
Frequency × User Burden > Maintenance Complexity Cost
Example: Binary wrappers
- Frequency: 100s/day
- User Burden: 50 chars/invocation
- Result: Worth the 3 layers
```
### When Wrappers Are NOT Justified
```
❌ Wrappers are NOT justified when:
Frequency × User Burden < Maintenance Complexity Cost
Example: Installation wrapper
- Frequency: 1x lifetime
- User Burden: 50 chars once
- Result: Not worth the orchestration
```
---
## Recommendation
### For Binary Execution: KEEP Wrapper Pattern
**Decision**: Keep `install-syntaxis` wrapper pattern (Bash → NuShell → Rust)
**Rationale**:
- ✅ Users don't want to type `--config path` 100s of times per day
- ✅ Config discovery is complex (multiple locations, precedence)
- ✅ Pattern is battle-tested and stable
- ✅ Complexity is justified by frequency of use
- ✅ Transparent to end users (no perceived overhead)
**Action Items**: None - keep as-is
---
### For Installation: REMOVE Wrapper Pattern
**Decision**: Remove `provision.sh` wrapper, use direct scripts only
**Rationale**:
- ❌ Users call installer once, not repeatedly
- ❌ Wrapper adds unnecessary orchestration
- ❌ Two clear scripts are simpler than three options
- ❌ Violates "no unnecessary complexity" principle
- ❌ Maintenance burden not justified for one-time use
**Better Approach**:
```bash
# Bundle contains only:
install.sh ← Install binaries
setup-config.sh ← Configure
# Users follow two-step process:
bash install.sh --interactive
bash setup-config.sh --interactive
# Simple, clear, transparent, Unix-way
```
**Benefits**:
- ✅ No confusion (only 1 recommended path)
- ✅ Less code to maintain
- ✅ Clear sequence (install → config)
- ✅ User understands each step
- ✅ Easy to debug (direct scripts)
- ✅ Follows Unix philosophy (one tool per job)
**Action Items**:
1. Remove `scripts/provisioning/provision.sh`
2. Remove from `configs/provisioning.toml` artifacts.scripts array
3. Update `docs/installation.md` to show two-step process
4. Update `BUNDLE_README.md` to show simple sequence
---
## Trade-offs
### Keeping Binary Wrappers
**Pros**:
- Excellent user experience (no --config needed)
- Justified by frequency (100s per day)
- Config discovery is complex (needs orchestration)
- Transparent (users don't notice)
**Cons**:
- More complex architecture
- Requires both bash and NuShell
- Adds startup overhead (~50ms)
- More moving parts to understand
### Removing Installation Wrapper
**Pros**:
- Simpler (fewer scripts)
- Clearer (no menu confusion)
- More transparent (users understand each step)
- Lower maintenance burden
**Cons**:
- Two commands instead of one
- Users might forget second step (but unlikely - one-time setup)
- No guided experience (but not needed - simple process)
---
## Implementation
### Phase 1: Decision
**Status**: APPROVED
### Phase 2: Code Cleanup
```bash
# Remove wrapper
rm scripts/provisioning/provision.sh
# Update config
# Edit: configs/provisioning.toml
# Remove: "scripts/provisioning/provision.sh" from artifacts.scripts array
# Update documentation
# Edit: docs/docs/installation.md - show two-step process
# Edit: docs/BUNDLE_README.md - update quick start
# Delete: docs/BUNDLE_DOCS_GUIDE.md references to provision
```
### Phase 3: Update Bundle
```bash
# Rebuild bundle
nu scripts/provisioning/pack.nu
# Verify changes
tar -tzf dist/syntaxis-v0.1.0-*.tar.gz | grep -E '(install|setup|provision)'
# Should show only: install.sh, install.nu, setup-config.sh
# Should NOT show: provision.sh
```
### Phase 4: Verification
```bash
# Test installation workflow
tar -xzf dist/syntaxis-v0.1.0-*.tar.gz
cd syntaxis-v0.1.0-*
# Step 1: Install
bash install.sh --interactive
# Step 2: Configure
bash setup-config.sh --interactive
# Verify
syntaxis-cli --version
```
---
## Risk Assessment
### Low Risk
- ✅ Removing optional wrapper
- ✅ Direct scripts are proven to work
- ✅ No impact on binary wrappers
- ✅ Clear documentation available
### Mitigation
- Document two-step process clearly
- Include both scripts in bundle (proven, working)
- Test complete installation flow
- Update all user-facing documentation
---
## Future Considerations
### If Installation Complexity Grows
If future bundle setups become complex:
- Consider wrapper again
- But only if frequency or complexity increases
- Apply same cost-benefit analysis
### Wrapper Pattern Elsewhere
If other tools need wrappers:
- Apply same framework
- Justify by frequency × burden vs complexity
- Transparency is key
---
## Appendix: Real-World Example
### Scenario: New User Installs SYNTAXIS
**With Wrapper (Current)**:
```bash
$ cd /tmp/bundle
$ ./provision full
# Menu appears, user selects options
# Both install and configure run
# Done!
```
**Without Wrapper (Proposed)**:
```bash
$ cd /tmp/bundle
$ bash install.sh --interactive
# User prompted for installation options
# Binaries installed
# Done with step 1
$ bash setup-config.sh --interactive
# User prompted for configuration
# Configs created
# Done with step 2
```
**Difference**:
- Wrapper: ~5 seconds (one command, orchestrated)
- Direct: ~10 seconds (two commands, sequential)
- **Complexity added**: ~5 seconds saved, once per lifetime
- **Complexity removed**: Eliminates 100+ lines of code, maintenance
**Clear winner**: Remove wrapper
---
## Conclusion
### Binary Execution Wrappers: KEEP ✅
- **Value**: Users invoke 100s of times per day
- **Problem Solved**: Automatic config injection (major UX improvement)
- **Complexity**: Justified and battle-tested
### Installation Wrapper: REMOVE ❌
- **Value**: Users invoke once per lifetime
- **Problem Solved**: Saves one command (minor UX improvement)
- **Complexity**: Not justified by benefit
**Philosophy**: Wrappers should **enable frequent workflows**, not orchestrate **one-time procedures**.
---
**Recommendation**: Implement Phase 2-4 cleanup to simplify bundle provisioning system.
---
**Status**: READY FOR DECISION