---
phase: 28-clone-rm-mv-clean-config-flags
plan: 02
type: execute
wave: 2
depends_on: ["28-01"]
files_modified:
  - tests/test_clone_flags.py
  - tests/test_rm_flags.py
  - tests/test_mv_flags.py
  - tests/test_clean_flags.py
  - tests/test_config_flags.py
autonomous: true

must_haves:
  truths:
    - "All 30 flag requirements have test coverage"
    - "Tests verify flag translation works correctly"
    - "Tests verify warning messages for unsupported flags"
    - "Tests use appropriate fixtures (sl_repo, sl_repo_with_commit)"
    - "All tests pass when run with pytest"
  artifacts:
    - path: "tests/test_clone_flags.py"
      provides: "E2E tests for CLON-01 through CLON-09"
      min_lines: 80
    - path: "tests/test_rm_flags.py"
      provides: "E2E tests for RM-01 through RM-05"
      min_lines: 50
    - path: "tests/test_mv_flags.py"
      provides: "E2E tests for MV-01 through MV-04"
      min_lines: 50
    - path: "tests/test_clean_flags.py"
      provides: "E2E tests for CLEN-01 through CLEN-04"
      min_lines: 60
    - path: "tests/test_config_flags.py"
      provides: "E2E tests for CONF-01 through CONF-08"
      min_lines: 80
  key_links:
    - from: "tests/test_clone_flags.py"
      to: "cmd_clone.py"
      via: "run_gitsl invocation"
      pattern: "run_gitsl.*clone"
    - from: "tests/test_config_flags.py"
      to: "cmd_config.py"
      via: "run_gitsl invocation"
      pattern: "run_gitsl.*config"
---

<objective>
Create E2E tests for all 30 flag requirements across clone, rm, mv, clean, and config commands (CLON-01 through CLON-09, RM-01 through RM-05, MV-01 through MV-04, CLEN-01 through CLEN-04, CONF-01 through CONF-08).

Purpose: Validate that all flag translations, pass-throughs, and warnings work correctly in real usage scenarios.

Output: Five test files following the established test pattern from test_grep_flags.py, covering all 30 requirements.
</objective>

<execution_context>
@~/.claude/get-shit-done/workflows/execute-plan.md
@~/.claude/get-shit-done/templates/summary.md
</execution_context>

<context>
@.planning/PROJECT.md
@.planning/ROADMAP.md
@.planning/STATE.md
@.planning/REQUIREMENTS.md
@.planning/phases/28-clone-rm-mv-clean-config-flags/28-RESEARCH.md
@.planning/phases/28-clone-rm-mv-clean-config-flags/28-01-SUMMARY.md
@tests/test_grep_flags.py (reference for test pattern)
@tests/conftest.py (available fixtures)
</context>

<tasks>

<task type="auto">
  <name>Task 1: Create Clone Flag Tests</name>
  <files>tests/test_clone_flags.py</files>
  <action>
Create tests/test_clone_flags.py following the pattern from test_grep_flags.py:

**Test structure:**
```python
"""E2E tests for git clone flags (CLON-01 through CLON-09)."""

import shutil
from pathlib import Path

import pytest

from conftest import run_gitsl

sl_available = shutil.which("sl") is not None
pytestmark = [
    pytest.mark.skipif(not sl_available, reason="Sapling (sl) not installed"),
    pytest.mark.clone,
]
```

**Test classes and methods:**

1. `TestCloneTranslation` - flags that translate:
   - `test_clone_branch_b(sl_repo_with_commit)`: CLON-01 - Create bookmark, clone with `-b <bookmark>`, verify correct bookmark checked out
   - `test_clone_branch_long(sl_repo_with_commit)`: CLON-01 - Same with `--branch=<bookmark>`
   - `test_clone_no_checkout_n(sl_repo_with_commit)`: CLON-05 - Clone with `-n`, verify working dir is empty
   - `test_clone_no_checkout_long(sl_repo_with_commit)`: CLON-05 - Same with `--no-checkout`

2. `TestClonePassThrough` - flags that pass through:
   - `test_clone_quiet_q(sl_repo_with_commit)`: CLON-08 - Clone with `-q`, verify minimal output
   - `test_clone_verbose_v(sl_repo_with_commit)`: CLON-09 - Clone with `-v`, verify command runs

3. `TestCloneUnsupported` - flags that warn:
   - `test_clone_depth_warning(sl_repo_with_commit)`: CLON-02 - Clone with `--depth 1`, verify warning in stderr
   - `test_clone_single_branch_warning(sl_repo_with_commit)`: CLON-03 - Clone with `--single-branch`, verify warning
   - `test_clone_origin_warning(sl_repo_with_commit)`: CLON-04 - Clone with `-o custom`, verify warning
   - `test_clone_recursive_warning(sl_repo_with_commit)`: CLON-06 - Clone with `--recursive`, verify warning
   - `test_clone_no_tags_warning(sl_repo_with_commit)`: CLON-07 - Clone with `--no-tags`, verify warning

**Clone test pattern:**
Clone tests need a source repo to clone from. Use sl_repo_with_commit as source, clone to a new directory within tmp_path.

```python
def test_clone_branch_b(self, sl_repo_with_commit: Path, tmp_path: Path):
    """CLON-01: git clone -b translates to sl clone -u."""
    # Create a bookmark in source repo
    run_command(["sl", "bookmark", "feature"], cwd=sl_repo_with_commit)

    # Clone with -b
    target = tmp_path / "clone_target"
    result = run_gitsl(["clone", "-b", "feature", str(sl_repo_with_commit), str(target)],
                       cwd=tmp_path)
    assert result.exit_code == 0
    # Verify the bookmark is active in target
```
  </action>
  <verify>
Run: `pytest tests/test_clone_flags.py -v --collect-only` - verify test collection
Run: `pytest tests/test_clone_flags.py -v` - all tests pass
  </verify>
  <done>
tests/test_clone_flags.py covers all 9 CLON requirements:
- CLON-01: -b/--branch translation tests
- CLON-02: --depth warning test
- CLON-03: --single-branch warning test
- CLON-04: -o/--origin warning test
- CLON-05: -n/--no-checkout translation tests
- CLON-06: --recursive warning test
- CLON-07: --no-tags warning test
- CLON-08: -q/--quiet pass-through test
- CLON-09: -v/--verbose pass-through test
  </done>
</task>

<task type="auto">
  <name>Task 2: Create Rm and Mv Flag Tests</name>
  <files>tests/test_rm_flags.py, tests/test_mv_flags.py</files>
  <action>
**Create tests/test_rm_flags.py:**

```python
"""E2E tests for git rm flags (RM-01 through RM-05)."""

import shutil
from pathlib import Path

import pytest

from conftest import run_gitsl
from helpers.commands import run_command

sl_available = shutil.which("sl") is not None
pytestmark = [
    pytest.mark.skipif(not sl_available, reason="Sapling (sl) not installed"),
    pytest.mark.rm,
]
```

**Test classes for rm:**

1. `TestRmPassThrough`:
   - `test_rm_force_f(sl_repo_with_commit)`: RM-01 - Modify tracked file, `rm -f`, verify file removed and command succeeds
   - `test_rm_quiet_q(sl_repo_with_commit)`: RM-04 - rm with `-q`, verify minimal output

2. `TestRmUnsupported`:
   - `test_rm_cached_warning(sl_repo_with_commit)`: RM-02 - rm with `--cached`, verify warning about staging area
   - `test_rm_dry_run_warning(sl_repo_with_commit)`: RM-03 - rm with `-n`, verify warning

3. `TestRmRecursive`:
   - `test_rm_recursive_filtered(sl_repo_with_commit)`: RM-05 - rm with `-r`, verify command works (flag is filtered, sl is recursive by default)

**Create tests/test_mv_flags.py:**

```python
"""E2E tests for git mv flags (MV-01 through MV-04)."""

import shutil
from pathlib import Path

import pytest

from conftest import run_gitsl

sl_available = shutil.which("sl") is not None
pytestmark = [
    pytest.mark.skipif(not sl_available, reason="Sapling (sl) not installed"),
    pytest.mark.mv,
]
```

**Test classes for mv:**

1. `TestMvPassThrough`:
   - `test_mv_force_f(sl_repo_with_commit)`: MV-01 - Create target file, mv with `-f`, verify overwrite works
   - `test_mv_verbose_v(sl_repo_with_commit)`: MV-03 - mv with `-v`, verify output shows files
   - `test_mv_dry_run_n(sl_repo_with_commit)`: MV-04 - mv with `-n`, verify file not moved but output shown

2. `TestMvUnsupported`:
   - `test_mv_k_warning(sl_repo_with_commit)`: MV-02 - mv with `-k`, verify warning about skip errors
  </action>
  <verify>
Run: `pytest tests/test_rm_flags.py tests/test_mv_flags.py -v --collect-only` - verify test collection
Run: `pytest tests/test_rm_flags.py tests/test_mv_flags.py -v` - all tests pass
  </verify>
  <done>
tests/test_rm_flags.py covers all 5 RM requirements:
- RM-01: -f/--force pass-through
- RM-02: --cached warning
- RM-03: -n/--dry-run warning
- RM-04: -q/--quiet pass-through
- RM-05: -r/--recursive filtering

tests/test_mv_flags.py covers all 4 MV requirements:
- MV-01: -f/--force pass-through
- MV-02: -k warning
- MV-03: -v/--verbose pass-through
- MV-04: -n/--dry-run pass-through
  </done>
</task>

<task type="auto">
  <name>Task 3: Create Clean and Config Flag Tests</name>
  <files>tests/test_clean_flags.py, tests/test_config_flags.py</files>
  <action>
**Create tests/test_clean_flags.py:**

```python
"""E2E tests for git clean flags (CLEN-01 through CLEN-04)."""

import shutil
from pathlib import Path

import pytest

from conftest import run_gitsl

sl_available = shutil.which("sl") is not None
pytestmark = [
    pytest.mark.skipif(not sl_available, reason="Sapling (sl) not installed"),
    pytest.mark.clean,
]
```

**Test classes for clean:**

1. `TestCleanTranslation`:
   - `test_clean_x_removes_ignored(sl_repo_with_commit)`: CLEN-01 - Create .gitignore, create ignored file, `clean -fx`, verify ignored file removed
   - `test_clean_exclude_pattern_e(sl_repo_with_commit)`: CLEN-03 - Create multiple untracked files, `clean -f -e <pattern>`, verify pattern excluded

2. `TestCleanUnsupported`:
   - `test_clean_X_only_ignored_warning(sl_repo_with_commit)`: CLEN-02 - clean with `-fX`, verify warning about limited support

3. `TestCleanExisting`:
   - `test_clean_force_required(sl_repo_with_commit)`: CLEN-04 - clean without -f, verify error about requireForce
   - `test_clean_dry_run_n(sl_repo_with_commit)`: CLEN-04 - clean with `-n`, verify files listed but not removed
   - `test_clean_directories_d(sl_repo_with_commit)`: CLEN-04 - clean with `-fd`, verify empty directories removed

**Test fixture for ignored files:**
```python
@pytest.fixture
def sl_repo_with_ignored(sl_repo_with_commit: Path) -> Path:
    """Sapling repo with ignored and untracked files."""
    # Create .gitignore (Sapling reads this too)
    gitignore = sl_repo_with_commit / ".gitignore"
    gitignore.write_text("*.log\n")
    run_command(["sl", "add", ".gitignore"], cwd=sl_repo_with_commit)
    run_command(["sl", "commit", "-m", "Add gitignore"], cwd=sl_repo_with_commit)

    # Create ignored file
    (sl_repo_with_commit / "test.log").write_text("ignored content")

    # Create untracked file
    (sl_repo_with_commit / "untracked.txt").write_text("untracked content")

    return sl_repo_with_commit
```

**Create tests/test_config_flags.py:**

```python
"""E2E tests for git config flags (CONF-01 through CONF-08)."""

import shutil
from pathlib import Path

import pytest

from conftest import run_gitsl

sl_available = shutil.which("sl") is not None
pytestmark = [
    pytest.mark.skipif(not sl_available, reason="Sapling (sl) not installed"),
    pytest.mark.config,
]
```

**Test classes for config:**

1. `TestConfigGet`:
   - `test_config_get_key(sl_repo)`: CONF-01 - Set a config value, `config --get key`, verify value returned
   - `test_config_implicit_get(sl_repo)`: CONF-01 - Set config, `config key`, verify value returned (--get is implicit)

2. `TestConfigTranslation`:
   - `test_config_unset_to_delete(sl_repo)`: CONF-02 - Set a value, `config --unset key`, verify key removed
   - `test_config_global_to_user(sl_repo)`: CONF-04 - `config --global key value`, verify sets user config
   - `test_config_show_origin_to_debug(sl_repo)`: CONF-07 - `config --show-origin --list`, verify shows file sources

3. `TestConfigPassThrough`:
   - `test_config_list_l(sl_repo)`: CONF-03 - `config --list`, verify shows all config
   - `test_config_local_scope(sl_repo)`: CONF-05 - `config --local key value`, verify sets local config
   - `test_config_system_scope(sl_repo)`: CONF-06 - `config --system` - may need to skip if no permission, or just verify flag accepted

4. `TestConfigUnsupported`:
   - `test_config_all_warning(sl_repo)`: CONF-08 - `config --all key`, verify warning about multi-valued
  </action>
  <verify>
Run: `pytest tests/test_clean_flags.py tests/test_config_flags.py -v --collect-only` - verify test collection
Run: `pytest tests/test_clean_flags.py tests/test_config_flags.py -v` - all tests pass
  </verify>
  <done>
tests/test_clean_flags.py covers all 4 CLEN requirements:
- CLEN-01: -x removes ignored files
- CLEN-02: -X warning about limited support
- CLEN-03: -e exclude pattern
- CLEN-04: existing -f, -d, -n work correctly

tests/test_config_flags.py covers all 8 CONF requirements:
- CONF-01: --get reads specific key
- CONF-02: --unset removes key (translates to --delete)
- CONF-03: --list/-l shows all config
- CONF-04: --global translates to --user
- CONF-05: --local scope
- CONF-06: --system scope
- CONF-07: --show-origin translates to --debug
- CONF-08: --all warning
  </done>
</task>

</tasks>

<verification>
1. tests/test_clone_flags.py exists with 9+ tests for CLON-01 through CLON-09
2. tests/test_rm_flags.py exists with 5+ tests for RM-01 through RM-05
3. tests/test_mv_flags.py exists with 4+ tests for MV-01 through MV-04
4. tests/test_clean_flags.py exists with 4+ tests for CLEN-01 through CLEN-04
5. tests/test_config_flags.py exists with 8+ tests for CONF-01 through CONF-08
6. All test files follow the pattern from test_grep_flags.py
7. All tests pass: `pytest tests/test_clone_flags.py tests/test_rm_flags.py tests/test_mv_flags.py tests/test_clean_flags.py tests/test_config_flags.py -v`
8. Total of 30 requirements covered across all test files
</verification>

<success_criteria>
- [ ] tests/test_clone_flags.py created with 9+ tests
- [ ] tests/test_rm_flags.py created with 5+ tests
- [ ] tests/test_mv_flags.py created with 4+ tests
- [ ] tests/test_clean_flags.py created with 4+ tests
- [ ] tests/test_config_flags.py created with 8+ tests
- [ ] All tests follow established pattern (pytestmark, class structure, docstrings)
- [ ] All tests pass when run with pytest
- [ ] Test coverage includes translation verification, warning verification, and behavior verification
</success_criteria>

<output>
After completion, create `.planning/phases/28-clone-rm-mv-clean-config-flags/28-02-SUMMARY.md`
</output>
