# CLI Refactor Verification Protocol

> **Purpose:** Deterministic verification workflow for cli-refactor tasks that automatically
> handles the distinction between expected plan artifacts and code changes.

## Overview

The **clean-baseline protocol** solves the blocker where verification requires a clean working 
tree, but vectl-managed plan artifacts are legitimately modified during normal operation.

## Protocol Workflow

```
┌─────────────────────────────────────────────────────────────────┐
│  1. IDENTIFY: Categorize dirty files                           │
│     ├─ Plan artifacts (plan.yaml, plan-dashboard.html)         │
│     ├─ Code changes (source files)                              │
│     └─ Ignored files (.serena/, coverage.xml, etc.)            │
│                                                                 │
│  2. STASH: Preserve ALL changes (atomic operation)             │
│     ├─ Create full stash (includes plan artifacts)             │
│     ├─ Immediately restore plan artifacts to working tree       │
│     └─ Verify: plan artifacts visible, code changes stashed   │
│                                                                 │
│  3. VERIFY: Run invar guard                                    │
│     ├─ Clean baseline (no code changes)                        │
│     ├─ Plan artifacts remain visible for verification          │
│     └─ Deterministic results                                    │
│                                                                 │
│  4. RESTORE: Return code changes (GUARANTEED)                  │
│     ├─ Automatic on success via normal flow                     │
│     ├─ Automatic on failure/exit via trap handler              │
│     └─ Ensures stash is always cleaned up                      │
└─────────────────────────────────────────────────────────────────┘
```

## Scripts

### Primary Script: `scripts/cli-refactor-verify.sh`

**Purpose:** Automated verification with clean-baseline handling.

**Usage:**

```bash
# Standard verification workflow (recommended)
./scripts/cli-refactor-verify.sh --check

# See what would happen without executing
./scripts/cli-refactor-verify.sh --check --dry-run

# Manual workflow: stash, verify, restore
./scripts/cli-refactor-verify.sh --stash-only
# ... run manual checks ...
./scripts/cli-refactor-verify.sh --restore-only

# JSON output for tooling/CICD
./scripts/cli-refactor-verify.sh --check --format json
```

**Exit Codes:**
- `0` - Success (verification passed)
- `1` - Verification failed
- `2` - Precondition error (conflicting stash, etc.)
- `3` - Invalid arguments

**Environment Variables:**
- `SKIP_STASH=1` - Skip stashing (use if you have a clean baseline)
- `KEEP_STASH=1` - Keep stash after restore (for debugging)

### Supporting Script: `scripts/gate-cleanliness-check.sh`

**Purpose:** Low-level cleanliness verification. Used internally by cli-refactor-verify.sh.

**See Also:** [Gate Cleanliness Procedure](./gate-cleanliness.md)

## File Categories

### Plan Artifacts (Expected, preserved in working tree)

```
plan.yaml             # vectl-managed plan state
plan-dashboard.html   # vectl-managed dashboard
```

These files are **never stashed** - they remain in the working tree during verification.

### Code Changes (Stashed during verification)

```
src/**/*.py           # Source code
tests/**/*.py         # Tests
docs/**/*.md          # Documentation (except plan files)
```

These files are **stashed** before verification and restored after.

### Ignored Files (Not tracked)

```
.serena/              # Serena agent files
coverage.xml          # Test coverage reports
*.pyc                 # Bytecode
__pycache__/          # Cache directories
.pytest_cache/        # Test cache
.mypy_cache/          # Type checker cache
*.egg-info/           # Package metadata
```

These files don't affect verification and are ignored.

## Common Workflows

### Workflow A: Standard CLI Refactor Verification

```bash
# 1. Make code changes (working tree dirty)
vim src/anima/shell/cli_commands/query.py

# 2. Run verification (auto-stashes changes)
./scripts/cli-refactor-verify.sh --check

# 3. Script output:
# [STEP] Analyzing working tree...
# [INFO] Plan artifacts: 2
# [INFO] Code changes: 3
# [INFO] Ignored files: 1
# [STEP] Stashing code changes...
# [INFO] Code changes stashed as 'cli-refactor-verify-temp'
# [STEP] Running verification...
# ... (invar guard output) ...
# [STEP] Restoring stashed changes...
# [INFO] Stash restored and removed
# [INFO] ✓ Verification passed
```

### Workflow B: Multiple Verification Rounds

```bash
# Round 1: Initial check
./scripts/cli-refactor-verify.sh --check

# Script stashes changes, verifies, restores.
# If verification fails, working tree is restored with your changes.

# Fix issues
vim src/anima/shell/cli_commands/cleanup_cmds.py

# Round 2: Re-verify
./scripts/cli-refactor-verify.sh --check

# Round 3: Continue until verification passes
```

### Workflow C: Manual Stash Control

```bash
# Stash only (don't verify yet)
./scripts/cli-refactor-verify.sh --stash-only

# Now working tree only has plan artifacts
git status
# Modified: plan.yaml
# Modified: plan-dashboard.html

# Run manual checks
uvx invar-tools guard --all
pytest tests/

# When done, restore your changes
./scripts/cli-refactor-verify.sh --restore-only
```

### Workflow D: CI/CD Integration

```yaml
# .github/workflows/cli-refactor.yml
- name: Verify CLI Refactor
  run: |
    ./scripts/cli-refactor-verify.sh --check --format json
```

JSON output example:

```json
{
  "plan_artifacts": 2,
  "code_changes": 3,
  "ignored_files": 1
}
```

## Expected Files Configuration

The script uses `.anima/gate/expected-generated.txt` to identify plan artifacts:

```
# Expected Generated Files for CLI Refactor Verification
# vectl plan artifacts
plan.yaml
plan-dashboard.html

# Gate baseline directory
.anima/gate/baseline-status.txt
```

**To add new expected files:**

1. Edit `.anima/gate/expected-generated.txt`
2. Add one file per line
3. Test with `./scripts/cli-refactor-verify.sh --check --dry-run`

## Troubleshooting

### "Stash already exists"

**Problem:** Previous run left a stash.

**Solution:**

```bash
# Check existing stashes
git stash list

# If safe to drop
git stash drop stash@{0}

# Or restore and clean up
./scripts/cli-refactor-verify.sh --restore-only
git stash drop stash@{0}
```

### "No stash found" (during restore)

**Problem:** Trying to restore without stashing first.

**Solution:** This is normal if verification was run with `SKIP_STASH=1`.

### "Verification failed"

**Problem:** Code changes don't pass invar guard.

**Solution:**

```bash
# The script automatically restores your changes
# Fix the issues in the code
vim src/anima/shell/cli_commands/...

# Re-run verification
./scripts/cli-refactor-verify.sh --check

# Repeat until verification passes
```

### "Unexpected files found"

**Problem:** Files not recognized as plan artifacts or code.

**Solution:**

1. Check if they should be in `.gitignore`
2. Or add to `.anima/gate/expected-generated.txt` if legitimately generated

## Decision Matrix

| When to Use | Script Mode |
|-------------|-------------|
| Standard CLI refactor workflow | `./scripts/cli-refactor-verify.sh --check` |
| Manual verification control | `--stash-only` / `--restore-only` |
| CI/CD pipeline | `--check --format json` |
| Debug workflow | `--check --dry-run` |
| Keep stash for inspection | `KEEP_STASH=1 ./scripts/cli-refactor-verify.sh --check` |
| Already clean baseline | `SKIP_STASH=1 ./scripts/cli-refactor-verify.sh --check` |

## Protocol Rules

### Rule 1: Automatic Stash Management (ATOMIC)

The script **guarantees atomicity**:
- Creates **full stash** (includes plan artifacts temporarily)
- Immediately restores plan artifacts to working tree
- **NEVER** hides plan artifacts behind fallback behavior
- Automatic cleanup via trap handler (EXIT, ERR, HUP, INT, TERM)

**Atomicity Guarantee:**
```
ON ANY EXIT (success, failure, signal):
  - Stash is restored if created
  - Plan artifacts remain visible throughout
  - No stale stashes left behind
```

### Rule 2: Deterministic Verification

Verification must be **deterministic**:
- Same code → same verification result
- No "sometimes passes, sometimes fails"
- Plan artifacts remain visible during verification
- **NO hidden state** from fallback stash strategies

### Rule 3: Transparent Workflow

All operations are **logged**:
- Categorization (plan vs code)
- Stash operations (including full-stash strategy)
- Plan artifact restoration steps
- Verification commands
- Restore operations (manual + automatic)

### Rule 4: No Behavior Changes

Protocol is **non-destructive**:
- Code changes are preserved (stashed/restored)
- Plan artifacts are **always visible** (restored after stash)
- No changes to CLI functionality
- **Automatic cleanup** on all exit paths (success, failure, signal)

### Rule 5: Reproducible Full-Run

Both `--check` and `--dry-run` modes are **safe and atomic**:
- `--check`: Full workflow with automatic restore
- `--dry-run`: Shows what would happen (no state changes)
- Both preserve working tree state on all exit paths

## Related Documentation

- [Gate Cleanliness Procedure](./gate-cleanliness.md) - Low-level cleanliness checks
- [vectl Guide](../.agents/instructions.md) - Plan management
- [INVAR.md](../INVAR.md) - Verification protocol

## Atomicity Fixes (v2)

**Issue:** Original implementation had critical atomicity problems in stash management.

### Problems Fixed:

1. **Hidden Plan Artifacts**
   - **Old:** Fallback to full stash when partial stash fails
   - **Problem:** Plan artifacts (plan.yaml, plan-dashboard.html) hidden in stash, invisible during verification
   - **Fix:** Backup plan artifacts before stashing, restore them immediately after creating stash
   
2. **Missing Restore on Failure**
   - **Old:** Early return on verification failure without cleanup
   - **Problem:** Stash left in limbo, working tree dirty, code changes "lost"
   - **Fix:** Trap handler ensures selective restore on EXIT (all paths: success, failure, signal)
   
3. **Non-Atomic Full-Run**
   - **Old:** Restore could be missed if script exits early (signal, error, etc.)
   - **Problem:** Working tree state not guaranteed to be restored
   - **Fix:** `STASH_CREATED` flag + EXIT trap + selective restore logic
   
4. **Stash Conflicts During Pop**
   - **Old:** `git stash pop` conflicts with restored plan artifacts
   - **Problem:** Pop fails, stash not cleaned up, manual intervention required
   - **Fix:** Selective restore: checkout code files from stash, then drop stash. Plan artifacts remain in working tree.

### Implementation Details:

```bash
# Backup strategy (ensures plan visibility)
if [[ $plan_count -gt 0 ]]; then
    mkdir -p "$backup_dir"
    cp "$artifact" "$backup_dir/$artifact"    # Backup
fi

git stash push -m "$STASH_NAME"              # Stash all changes
git checkout HEAD -- "$artifact"             # Reset to HEAD
git checkout "stash@{0}" -- "$code_file"     # Restore code changes only
git stash drop "stash@{0}"                   # Clean up

# Trap handler (automatic cleanup on all exit paths)
trap cleanup_stash EXIT
STASH_CREATED=false                            # State tracking

# Selective restore (avoids plan artifact conflicts)
while IFS= read -r file; do
    git checkout "stash@{0}" -- "$file"        # Code files only
done < /tmp/code_files.txt
git stash drop "stash@{0}"                    # Remove stash
```

### Verification Tests:

```bash
# Test 1: Failure path restores automatically
./scripts/cli-refactor-verify.sh --check      # Should fail (verification errors)
git status                                    # ✅ Should show original dirty state
git stash list                                # ✅ Should be empty (cleaned up)

# Test 2: Plan artifacts always visible
echo "test" >> plan.yaml                      # Modify plan artifact
./scripts/cli-refactor-verify.sh --check      # Run verification
git status                                    # ✅ Should show plan.yaml still dirty
git diff plan.yaml | head -5                  # ✅ Should show "test" modification

# Test 3: Dry-run safety (no state changes)
./scripts/cli-refactor-verify.sh --check --dry-run
git status                                    # ✅ Should be unchanged
git stash list                                # ✅ Should be empty

# Test 4: Signal handling (Ctrl+C during verification)
# Start: ./scripts/cli-refactor-verify.sh --check
# Press: Ctrl+C
git status                                    # ✅ Should show original dirty state
git stash list                                # ✅ Should be empty (trap cleaned up)
```

### Key Guarantees:

1. **Plan Artifacts Always Visible**: Backed up before stash, restored immediately after stash creation, never hidden
2. **Automatic Restore on ALL Paths**: EXIT trap handles success, failure, signals (HUP, INT, TERM)
3. **No Stash Conflicts**: Selective restore (code files only) avoids merge conflicts with plan artifacts
4. **Reproducible**: Both `--check` and `--dry-run` are safe and atomic
5. **No Manual Intervention**: Failure in verification → automatic cleanup, working tree restored

### Verification Tests:

```bash
# Test 1: Failure path restores automatically
./scripts/cli-refactor-verify.sh --check  # Should fail
git status                                # Should show original dirty state

# Test 2: Plan artifacts always visible
echo "test" >> plan.yaml                  # Modify plan artifact
./scripts/cli-refactor-verify.sh --check  # Run verification
git status                                # Should show plan artifact still dirty

# Test 3: Dry-run safety
./scripts/cli-refactor-verify.sh --check --dry-run
git status                                # Should be unchanged

# Test 4: Signal handling (Ctrl+C during verification)
# Start verification, press Ctrl+C
git stash list                            # Should be empty (cleaned up)
```

## History

**Created:** 2026-03-02
**Purpose:** Fix `cli-refactor.fix-clean-baseline-protocol` blocker
**Issue:** Independent retest failed due to dirty working tree precondition violation
**Solution:** Automatic stash/restore workflow that distinguishes plan artifacts from code changes