skills/docs/MIGRATION-GUIDE-ops-dev.md
dan 5fea49b7c0 feat(tufte-press): evolve skill to complete workflow with JSON generation and build automation
- Transform tufte-press from reference guide to conversation-aware generator
- Add JSON generation from conversation context following strict schema
- Create build automation scripts with Nix environment handling
- Integrate CUPS printing with duplex support
- Add comprehensive workflow documentation

Scripts added:
- skills/tufte-press/scripts/generate-and-build.sh (242 lines)
- skills/tufte-press/scripts/build-card.sh (23 lines)

Documentation:
- Updated SKILL.md with complete workflow instructions (370 lines)
- Updated README.md with usage examples (340 lines)
- Created SKILL-DEVELOPMENT-STRATEGY-tufte-press.md (450 lines)
- Added worklog: 2025-11-10-tufte-press-skill-evolution.org

Features:
- Agent generates valid JSON from conversation
- Schema validation before build (catches errors early)
- Automatic Nix shell entry for dependencies
- PDF build via tufte-press toolchain
- Optional print with duplex support
- Self-contained margin notes enforced
- Complete end-to-end testing

Workflow: Conversation → JSON → Validate → Build → Print

Related: niri-window-capture, screenshot-latest, worklog skills
2025-11-10 15:03:44 -08:00

415 lines
9.5 KiB
Markdown

# Migration Guide: ops-dev to Skills Flake Input
**Objective**: Migrate ops-dev VM from local skill copies to consuming skills via Nix flake input
**Current State**: tufte-press and worklog copied locally to `~/proj/ops-dev/skills/`
**Target State**: All skills consumed from `dan/skills` flake input
**Philosophy**: Skills repo is single source of truth
## Prerequisites
- [x] Skills repo deployed to Forgejo: `http://192.168.1.108:3000/dan/skills`
- [x] Skills repo has working flake with ai-skills module
- [x] ops-dev VM running NixOS with flake-based configuration
- [x] SSH access to ops-dev VM (192.168.1.73)
## Migration Steps
### Step 1: Add Skills Flake Input
**File**: `~/proj/ops-dev/flake.nix`
**Choose input URL based on your use case**:
**Option A: Local path (recommended for development)**:
```nix
{
description = "ops-dev NixOS configuration";
inputs = {
nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";
# Local path - works offline, great for development
skills = {
url = "path:/home/dan/proj/skills";
inputs.nixpkgs.follows = "nixpkgs";
};
};
outputs = { self, nixpkgs, skills }: {
# ... rest of config
};
}
```
**Option B: Git URL (for remote deployment)**:
```nix
{
description = "ops-dev NixOS configuration";
inputs = {
nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";
# Git URL - explicit versioning, works remotely
skills = {
url = "git+http://192.168.1.108:3000/dan/skills.git";
inputs.nixpkgs.follows = "nixpkgs";
};
};
outputs = { self, nixpkgs, skills }: {
# ... rest of config
};
}
```
**When to use which**:
- **`path:`** - Local development machine, offline work, fast iteration
- **`git+http:`** - Remote VMs, explicit version control, shared deployments
**Why `inputs.nixpkgs.follows`?**
Ensures skills flake uses the same nixpkgs as ops-dev, avoiding duplicate dependencies and reducing closure size.
**Network dependency note**: Both approaches fetch to `/nix/store` once, then work offline. Use `nix flake prefetch` to pre-cache.
### Step 2: Import ai-skills Module
**File**: `~/proj/ops-dev/flake.nix`
**In nixosConfigurations.dev.modules**:
```nix
nixosConfigurations.dev = nixpkgs.lib.nixosSystem {
system = "x86_64-linux";
modules = [
./configuration.nix
# Import skills module
skills.nixosModules.ai-skills
# Configure skills
{
services.ai-skills = {
enable = true;
selectedSkills = [
"tufte-press"
"worklog"
# Add more skills as needed:
# "screenshot-latest"
# "niri-window-capture"
];
deployTargets = [ "claude" "opencode" ];
};
}
];
};
```
### Step 3: Remove Local Skills Configuration
**File**: `~/proj/ops-dev/flake.nix`
**Remove these sections** (if present):
```nix
# DELETE: Old local skills deployment
environment.etc."opencode/skills" = {
source = ./skills;
};
environment.etc."claude/skills" = {
source = ./skills;
};
# DELETE: Old symlink activation script
system.activationScripts.skills-symlinks = {
text = ''
# ... old symlink code ...
'';
deps = [ "etc" ];
};
```
**Why remove?**
The ai-skills module handles all skill deployment. Keeping old config creates conflicts.
### Step 4: Remove Local Skills Directory
**Commands** (on development machine):
```bash
cd ~/proj/ops-dev
# Backup first (just in case)
tar czf skills-backup-$(date +%Y%m%d).tar.gz skills/
# Remove local skills
rm -rf skills/
# Commit the change
git add -A
git commit -m "Switch to skills repo flake input
- Add skills flake input from Forgejo
- Import ai-skills NixOS module
- Remove local skill copies (now from flake)
- Enable tufte-press and worklog skills
"
```
### Step 5: Update Flake Lock
**Command**:
```bash
cd ~/proj/ops-dev
nix flake lock
```
**This creates/updates** `flake.lock` with:
- Skills repo commit hash
- Input dependencies
- Reproducible versions
**Check the lock file**:
```bash
cat flake.lock | jq '.nodes.skills'
```
Should show:
```json
{
"locked": {
"lastModified": 1234567890,
"narHash": "sha256-...",
"ref": "refs/heads/master",
"rev": "abc123...",
"type": "git",
"url": "http://192.168.1.108:3000/dan/skills.git"
}
}
```
### Step 6: Deploy to VM
**Option A: Via SCP (current method)**:
```bash
# Copy updated config to VM
scp -i ~/.ssh/id_ed25519_2025 flake.nix flake.lock root@192.168.1.73:/home/dev/ops-dev/
# Rebuild on VM
ssh root@192.168.1.73 "cd /home/dev/ops-dev && nixos-rebuild switch --flake .#dev"
```
**Option B: Via Git (cleaner)**:
```bash
# Push to Forgejo
git push origin master
# Pull and rebuild on VM
ssh root@192.168.1.73 "cd /home/dev/ops-dev && git pull && nixos-rebuild switch --flake .#dev"
```
### Step 7: Verify Deployment
**Check skills are deployed**:
```bash
ssh dev@192.168.1.73 "ls -la /etc/opencode/skills/"
# Should show: tufte-press, worklog
ssh dev@192.168.1.73 "ls -la /etc/claude/skills/"
# Should show: tufte-press, worklog
ssh dev@192.168.1.73 "cat /etc/opencode/skills/tufte-press/SKILL.md | head -5"
# Should show skill content
```
**Check symlinks in user home**:
```bash
ssh dev@192.168.1.73 "ls -la ~/.config/opencode/skills"
# Should be symlink to /etc/opencode/skills
ssh dev@192.168.1.73 "ls -la ~/.claude/skills"
# Should be symlink to /etc/claude/skills
```
**Verify with agents** (if opencode-skills plugin installed):
```bash
ssh dev@192.168.1.73
cd ~/some-project
opencode # or claude-code
# In agent, try:
# "What skills are available?"
# "Use tufte-press skill"
```
## Updating Skills
### When Skills Repo Changes
**Update to latest**:
```bash
cd ~/proj/ops-dev
# Update skills input to latest commit
nix flake lock --update-input skills
# Check what changed
git diff flake.lock
# Deploy to VM
ssh root@192.168.1.73 "cd /home/dev/ops-dev && nixos-rebuild switch --flake .#dev"
```
### Pin to Specific Commit
**Lock to a known-good version**:
```bash
cd ~/proj/ops-dev
# Update flake.nix input to specific commit
nix flake lock --override-input skills git+http://192.168.1.108:3000/dan/skills.git?rev=abc123...
# Or edit flake.nix:
inputs.skills.url = "git+http://192.168.1.108:3000/dan/skills.git?rev=abc123...";
```
### Add New Skills
**Edit ops-dev flake.nix**:
```nix
services.ai-skills = {
enable = true;
selectedSkills = [
"tufte-press"
"worklog"
"screenshot-latest" # Add new skill
];
deployTargets = [ "claude" "opencode" ];
};
```
Then rebuild:
```bash
ssh root@192.168.1.73 "cd /home/dev/ops-dev && nixos-rebuild switch --flake .#dev"
```
## Rollback Plan
### If Migration Fails
**Restore local skills**:
```bash
cd ~/proj/ops-dev
# Extract backup
tar xzf skills-backup-YYYYMMDD.tar.gz
# Revert flake.nix changes
git revert HEAD
# Rebuild with old config
ssh root@192.168.1.73 "cd /home/dev/ops-dev && nixos-rebuild switch --flake .#dev"
```
### If Specific Skill Broken
**Remove from selectedSkills**:
```nix
services.ai-skills = {
enable = true;
selectedSkills = [
"tufte-press"
# "worklog" # Temporarily disabled
];
};
```
**Or pin skills input to older commit**:
```bash
nix flake lock --override-input skills git+http://192.168.1.108:3000/dan/skills.git?rev=<old-working-commit>
```
## Troubleshooting
### Issue: "error: getting status of '/nix/store/.../skills': No such file or directory"
**Cause**: Skills flake not properly fetched
**Solution**:
```bash
cd ~/proj/ops-dev
nix flake lock --update-input skills
ssh root@192.168.1.73 "cd /home/dev/ops-dev && nix flake update"
```
### Issue: "error: attribute 'nixosModules.ai-skills' missing"
**Cause**: Skills repo doesn't export the module
**Solution**:
```bash
# Check skills repo exports
cd ~/proj/skills
nix flake show
# Should see:
# └───nixosModules
# └───ai-skills: NixOS module
```
### Issue: Skills not appearing in /etc/opencode/skills
**Cause**: Module not properly enabled or paths wrong
**Check**:
```bash
ssh root@192.168.1.73 "systemctl status"
ssh root@192.168.1.73 "ls -la /etc/opencode/"
ssh root@192.168.1.73 "readlink -f /etc/opencode/skills/tufte-press"
# Should point to /nix/store/.../tufte-press
```
**Debug**:
```bash
# Check what the module evaluated to
ssh root@192.168.1.73 "nixos-option services.ai-skills"
```
### Issue: Permission denied accessing skills
**Cause**: Wrong ownership on symlinks
**Solution**: Module should handle this, but manually fix:
```bash
ssh root@192.168.1.73 "chown -h dev:users ~/.config/opencode/skills ~/.claude/skills"
```
## Benefits After Migration
### Before (Local Copy)
- ❌ Manual sync between repos required
- ❌ Risk of divergence
- ❌ No version control of deployment
- ❌ Changes require copying files and rebuilding
- ❌ Unclear which version is deployed
### After (Flake Input)
- ✅ Single source of truth (skills repo)
- ✅ Version controlled via flake.lock
- ✅ Automatic updates via `nix flake lock --update-input skills`
- ✅ Can pin to specific commits
- ✅ Declarative deployment
- ✅ Same pattern for all consuming projects
- ✅ Reproducible builds
## Related Documentation
- `NIX-FLAKE-USAGE.md` - How to consume the skills flake
- `CROSS-REPO-SKILL-COLLABORATION.md` - Collaboration patterns
- `modules/ai-skills.nix` - Module implementation details
- `flake.nix` - Skills repo flake definition
## Next Steps After Migration
1. **Test thoroughly** - Verify all skills work in both Claude and OpenCode
2. **Document for team** - Update ops-dev README with new pattern
3. **Apply to other VMs** - Use same pattern for other NixOS systems
4. **Establish update cadence** - How often to update skills input?
5. **Monitor for issues** - Watch for skill loading problems