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)
421 lines
11 KiB
Markdown
421 lines
11 KiB
Markdown
# ADR-002: Bundle Wrapper Deployment Architecture
|
|
|
|
**Date**: 2025-11-17
|
|
**Status**: ACCEPTED
|
|
**Version**: 2.0 (Updated with hybrid NuShell + Bash fallback)
|
|
**Author**: Architecture Review
|
|
**Scope**: Hybrid runtime wrapper deployment for bundle installations
|
|
|
|
---
|
|
|
|
## Problem Statement
|
|
|
|
**Question**: Should bundle installations create the same three-layer wrapper structure that development installations create?
|
|
|
|
**Current State**:
|
|
- **Development users** (`scripts/install-syntaxis.nu`): Get full wrapper infrastructure
|
|
- Binaries renamed to `.real`
|
|
- Bash wrappers at original locations
|
|
- NuShell wrappers deployed to `~/.config/syntaxis/scripts/`
|
|
- Result: Auto-config injection ✅ → Users type: `syntaxis-cli status`
|
|
|
|
- **Bundle users** (`scripts/provisioning/install.sh`): Get direct binaries only
|
|
- Binaries installed directly
|
|
- No wrapper infrastructure
|
|
- No config auto-injection
|
|
- Result: Manual config flags ❌ → Users must type: `syntaxis-cli --config path status`
|
|
|
|
**The Issue**: Inconsistent user experience between installation methods.
|
|
|
|
---
|
|
|
|
## Wrapper Architecture: Hybrid Design (NuShell + Bash Fallback)
|
|
|
|
### With NuShell Installed (Preferred): Three Layers
|
|
|
|
**Layer 1: Bash Wrapper**
|
|
```bash
|
|
~/.local/bin/syntaxis-cli (300 bytes)
|
|
├─ Checks: Is NuShell available?
|
|
├─ If YES: Sets NU_LIB_DIRS="$HOME/.config/syntaxis/scripts"
|
|
└─ Calls: nu "$HOME/.config/syntaxis/scripts/syntaxis-cli.nu" "$@"
|
|
```
|
|
|
|
**Layer 2: NuShell Wrapper**
|
|
```nushell
|
|
~/.config/syntaxis/scripts/syntaxis-cli.nu (2.2 KB)
|
|
├─ Searches: Config file locations
|
|
├─ Discovers: ~/.config/syntaxis/syntaxis-cli.toml
|
|
├─ Injects: --config ~/.config/syntaxis/syntaxis-cli.toml
|
|
└─ Calls: ~/.local/bin/syntaxis-cli.real --config ... status
|
|
```
|
|
|
|
**Layer 3: Real Binary**
|
|
```
|
|
~/.local/bin/syntaxis-cli.real (7.2 MB)
|
|
└─ Actual compiled Rust binary
|
|
```
|
|
|
|
### Without NuShell: Two Layers (Simplified)
|
|
|
|
**Layer 1: Bash Wrapper (with inline config discovery)**
|
|
```bash
|
|
~/.local/bin/syntaxis-cli (300 bytes)
|
|
├─ Checks: Is NuShell available?
|
|
├─ If NO: Use bash-only config discovery
|
|
├─ Searches: Config in ~/.config/syntaxis/*, .syntaxis/, .project/, .coder/
|
|
├─ If found: Injects --config flag
|
|
└─ Calls: ~/.local/bin/syntaxis-cli.real --config <found> status
|
|
```
|
|
|
|
**Layer 2: Real Binary**
|
|
```
|
|
~/.local/bin/syntaxis-cli.real (7.2 MB)
|
|
└─ Actual compiled Rust binary
|
|
```
|
|
|
|
### User Experience
|
|
```bash
|
|
$ syntaxis-cli status
|
|
# Wrapper automatically injects --config
|
|
# Clean, simple, no typing burden
|
|
```
|
|
|
|
---
|
|
|
|
## Decision: ADD HYBRID WRAPPERS TO BUNDLE
|
|
|
|
**Recommendation**: Bundle installations should create hybrid wrappers that work with or without NuShell.
|
|
|
|
### Rationale
|
|
|
|
1. **Self-Contained Bundle**
|
|
- No hard dependency on NuShell
|
|
- Works offline (no downloads required)
|
|
- Fallback ensures functionality
|
|
|
|
2. **User Flexibility**
|
|
- NuShell users get full features immediately
|
|
- Non-NuShell users still get auto-config
|
|
- User prompted to install NuShell (optional upgrade)
|
|
|
|
3. **Graceful Degradation**
|
|
- With NuShell: Full three-layer architecture (best UX)
|
|
- Without NuShell: Simple bash discovery (good UX)
|
|
- Both modes provide auto-config injection
|
|
|
|
4. **Minimal Maintenance**
|
|
- Only ~15 lines of bash fallback code
|
|
- No library translation needed
|
|
- NuShell libraries only used when available
|
|
|
|
5. **Daily UX Impact**
|
|
- Users invoke 100s of times per day/week
|
|
- Auto-config saves significant typing burden
|
|
- Works regardless of NuShell availability
|
|
|
|
---
|
|
|
|
## Implementation Plan
|
|
|
|
### 1. Update `scripts/provisioning/install.sh`
|
|
|
|
**Key functions added**:
|
|
|
|
**a) Detect NuShell**:
|
|
```bash
|
|
check_nushell() {
|
|
if command -v nu &> /dev/null; then
|
|
NUSHELL_VERSION=$(nu --version 2>/dev/null | head -1)
|
|
return 0
|
|
else
|
|
return 1
|
|
fi
|
|
}
|
|
```
|
|
|
|
**b) Prompt user about NuShell**:
|
|
```bash
|
|
prompt_nushell() {
|
|
# Shows installation guide if NuShell not found
|
|
# Offers user choice: continue or install NuShell
|
|
# Non-blocking (continues with fallback if needed)
|
|
}
|
|
```
|
|
|
|
**c) Create hybrid bash wrapper**:
|
|
```bash
|
|
create_bash_wrapper() {
|
|
local dest="$1"
|
|
local binary_name=$(basename "$dest")
|
|
|
|
# Create wrapper that:
|
|
# 1. Checks if NuShell is available
|
|
# 2a. If YES: use full three-layer architecture
|
|
# 2b. If NO: use bash-only config discovery
|
|
}
|
|
```
|
|
|
|
**d) Wrapper logic**:
|
|
```bash
|
|
#!/bin/bash
|
|
# Hybrid wrapper - tries NuShell first
|
|
|
|
if command -v nu &>/dev/null; then
|
|
# Full mode: NuShell + libraries
|
|
export NU_LIB_DIRS="$HOME/.config/syntaxis/scripts"
|
|
exec nu "$HOME/.config/syntaxis/scripts/${BINARY_NAME}.nu" "$@"
|
|
fi
|
|
|
|
# Fallback: Bash-only config discovery
|
|
for cfg_path in \
|
|
"$HOME/.config/syntaxis/${BINARY_NAME}.toml" \
|
|
"$HOME/.config/syntaxis/config.toml" \
|
|
".syntaxis/${BINARY_NAME}.toml"; do
|
|
|
|
if [[ -f "$cfg_path" ]]; then
|
|
exec "$REAL_BINARY" --config "$cfg_path" "$@"
|
|
fi
|
|
done
|
|
|
|
# No config found
|
|
exec "$REAL_BINARY" "$@"
|
|
```
|
|
|
|
### 2. Deploy NuShell Wrapper Scripts
|
|
|
|
**Add to `install.sh`**:
|
|
```bash
|
|
deploy_wrapper_scripts() {
|
|
local scripts_dir="./scripts"
|
|
local config_scripts_dir="$HOME/.config/syntaxis/scripts"
|
|
|
|
mkdir -p "$config_scripts_dir"
|
|
|
|
# Deploy shared library
|
|
cp "$scripts_dir/syntaxis-lib.nu" "$config_scripts_dir/"
|
|
|
|
# Deploy binary-specific wrappers
|
|
for binary in syntaxis-cli syntaxis-tui syntaxis-api; do
|
|
cp "$scripts_dir/${binary}.nu" "$config_scripts_dir/" 2>/dev/null || true
|
|
cp "$scripts_dir/${binary}-lib.nu" "$config_scripts_dir/" 2>/dev/null || true
|
|
done
|
|
|
|
chmod +x "$config_scripts_dir"/*.nu
|
|
}
|
|
```
|
|
|
|
### 3. Update `provisioning.toml`
|
|
|
|
**Add wrapper scripts to artifacts**:
|
|
```toml
|
|
[artifacts]
|
|
# ... existing config ...
|
|
|
|
# Wrapper scripts for auto-config injection
|
|
wrapper_scripts = [
|
|
"scripts/syntaxis-lib.nu",
|
|
"scripts/syntaxis-cli.nu",
|
|
"scripts/syntaxis-cli-lib.nu",
|
|
"scripts/syntaxis-tui.nu",
|
|
"scripts/syntaxis-tui-lib.nu",
|
|
"scripts/syntaxis-api.nu",
|
|
"scripts/syntaxis-api-lib.nu",
|
|
]
|
|
```
|
|
|
|
### 4. Update Bundle Structure
|
|
|
|
**Result after installation**:
|
|
```
|
|
User's system after bundle installation:
|
|
~/.cargo/bin/
|
|
├── syntaxis-cli ← Bash wrapper
|
|
├── syntaxis-cli.real ← Actual binary
|
|
├── syntaxis-tui ← Bash wrapper
|
|
├── syntaxis-tui.real ← Actual binary
|
|
└── syntaxis-api ← Bash wrapper
|
|
└── syntaxis-api.real ← Actual binary
|
|
|
|
~/.config/syntaxis/scripts/
|
|
├── syntaxis-lib.nu ← Shared library
|
|
├── syntaxis-cli.nu ← NuShell wrapper
|
|
├── syntaxis-cli-lib.nu ← CLI utilities
|
|
├── syntaxis-tui.nu ← NuShell wrapper
|
|
├── syntaxis-tui-lib.nu ← TUI utilities
|
|
├── syntaxis-api.nu ← NuShell wrapper
|
|
└── syntaxis-api-lib.nu ← API utilities
|
|
```
|
|
|
|
---
|
|
|
|
## Technical Specifications
|
|
|
|
### Wrapper Scripts to Include
|
|
|
|
| Script | Size | Purpose |
|
|
|--------|------|---------|
|
|
| `syntaxis-lib.nu` | 1.1 KB | Shared library (config discovery) |
|
|
| `syntaxis-cli.nu` | 2.2 KB | CLI wrapper (auto-config injection) |
|
|
| `syntaxis-cli-lib.nu` | 1.5 KB | CLI utilities |
|
|
| `syntaxis-tui.nu` | 2.2 KB | TUI wrapper |
|
|
| `syntaxis-tui-lib.nu` | 743 B | TUI utilities |
|
|
| `syntaxis-api.nu` | 3.6 KB | API wrapper |
|
|
| `syntaxis-api-lib.nu` | 2.2 KB | API utilities |
|
|
| **Total** | ~13.5 KB | All wrapper infrastructure |
|
|
|
|
### Bundle Size Impact
|
|
|
|
- **Before**: Binaries + configs + docs = ~9.2 MB
|
|
- **After**: + wrapper scripts (~13.5 KB) = ~9.2 MB (negligible)
|
|
|
|
### Installation Steps
|
|
|
|
1. Extract bundle
|
|
2. Run `bash install.sh --interactive`
|
|
- Installs binaries to `~/.local/bin/` (or custom prefix)
|
|
- Deploys wrapper scripts to `~/.config/syntaxis/scripts/`
|
|
- Renames binaries to `.real`
|
|
- Creates bash wrappers at original locations
|
|
3. Run `bash setup-config.sh --interactive`
|
|
- Creates configuration files
|
|
|
|
---
|
|
|
|
## Benefits
|
|
|
|
✅ **Users Don't Type `--config`**
|
|
- Every invocation automatically injects config path
|
|
- Saves millions of characters per year
|
|
|
|
✅ **Transparent**
|
|
- Users see no difference from direct binary
|
|
- Wrapper is invisible to end users
|
|
|
|
✅ **Flexible**
|
|
- Config files can be in multiple locations
|
|
- Wrapper discovers automatically
|
|
|
|
✅ **Consistent**
|
|
- Same experience as development installation
|
|
- Feature parity across installation methods
|
|
|
|
✅ **Maintainable**
|
|
- Clear separation: wrapper scripts vs binaries
|
|
- Easy to update wrappers without rebuilding binaries
|
|
|
|
---
|
|
|
|
## Trade-offs
|
|
|
|
### With NuShell (Full Mode)
|
|
**Pros**:
|
|
- ✅ Excellent user experience (no --config needed)
|
|
- ✅ Advanced config discovery (multiple paths, precedence)
|
|
- ✅ Full feature set available
|
|
- ✅ Consistent with development installation
|
|
|
|
**Cons**:
|
|
- ⚠️ Startup overhead (~50ms from NuShell)
|
|
- ⚠️ Requires NuShell to be installed
|
|
- ⚠️ Slightly more complex
|
|
|
|
### Without NuShell (Simplified Mode)
|
|
**Pros**:
|
|
- ✅ No external dependencies
|
|
- ✅ Works offline (self-contained)
|
|
- ✅ Still provides auto-config injection
|
|
- ✅ Simple bash-only fallback
|
|
|
|
**Cons**:
|
|
- ⚠️ Less advanced config discovery
|
|
- ⚠️ Simplified version of full features
|
|
- ⚠️ User prompted to install NuShell (optional)
|
|
|
|
### Overall Hybrid Approach
|
|
**Pros**:
|
|
- ✅ Self-contained bundle (no requirements)
|
|
- ✅ Works for all users (NuShell or not)
|
|
- ✅ Graceful degradation (best effort)
|
|
- ✅ Minimal maintenance (only ~15 lines bash fallback)
|
|
- ✅ User-aware (prompted to upgrade if desired)
|
|
|
|
**Cons**:
|
|
- ⚠️ Two code paths to test
|
|
- ⚠️ Slightly more complexity in wrapper
|
|
- ⚠️ NuShell libraries deployment (optional when not available)
|
|
|
|
---
|
|
|
|
## Risk Assessment
|
|
|
|
### Low Risk ✅
|
|
- Exact same code as development installation
|
|
- NuShell is already required for development
|
|
- Startup overhead is acceptable for CLI tools
|
|
- Can always use `.real` binaries if needed
|
|
|
|
---
|
|
|
|
## Implementation Checklist
|
|
|
|
- [ ] Modify `scripts/provisioning/install.sh` to create wrappers
|
|
- [ ] Add `deploy_wrapper_scripts()` function to install.sh
|
|
- [ ] Update `configs/provisioning.toml` to include wrapper scripts
|
|
- [ ] Update `scripts/provisioning/pack.nu` to package wrapper scripts
|
|
- [ ] Test bundle installation creates complete wrapper structure
|
|
- [ ] Update documentation (docs/installation.md, README.md)
|
|
- [ ] Rebuild bundle with wrapper support
|
|
- [ ] Verify wrapper functionality post-install
|
|
|
|
---
|
|
|
|
## Comparison: With vs Without Wrappers
|
|
|
|
### Without Wrappers (Current Bundle)
|
|
```bash
|
|
$ syntaxis-cli project list
|
|
# User must provide --config flag every time
|
|
$ syntaxis-cli --config ~/.config/syntaxis/syntaxis-cli.toml project list
|
|
|
|
# Burden: 50+ characters per invocation
|
|
# 100 invocations = 5,000+ characters of typing
|
|
```
|
|
|
|
### With Wrappers (Proposed)
|
|
```bash
|
|
$ syntaxis-cli project list
|
|
# Wrapper injects --config automatically
|
|
# Clean, simple, Unix-like experience
|
|
|
|
# Burden: 0 additional typing
|
|
# Users just type normal commands
|
|
```
|
|
|
|
---
|
|
|
|
## Related Documentation
|
|
|
|
- `docs/installation/WRAPPER_DESIGN.md` - Technical wrapper design
|
|
- `scripts/install-syntaxis.nu` - Development installation with wrappers
|
|
- `scripts/provisioning/install.sh` - Bundle installation (to be updated)
|
|
|
|
---
|
|
|
|
## Conclusion
|
|
|
|
**Decision**: Implement full wrapper deployment in bundle installations.
|
|
|
|
**Rationale**:
|
|
- High value (users don't type --config)
|
|
- Low complexity (existing code, ~14 KB)
|
|
- Better user experience
|
|
- Feature parity with development installation
|
|
|
|
This approach aligns with SYNTAXIS philosophy of providing excellent, transparent tooling for developers and teams.
|
|
|
|
---
|
|
|
|
**Status**: ACCEPTED - Ready for implementation
|
|
|