---
phase: 16-flag-translation
plan: 01
type: execute
wave: 1
depends_on: []
files_modified:
  - cmd_clean.py
  - cmd_config.py
  - cmd_switch.py
  - gitsl.py
autonomous: true
user_setup: []

must_haves:
  truths:
    - "git clean without -f or -n is rejected with exit code 128"
    - "git clean -f removes untracked files via sl purge"
    - "git clean -n shows files without removing via sl purge --print"
    - "git config reads and writes config values"
    - "git config --list shows all config"
    - "git switch changes to existing bookmark via sl goto"
    - "git switch -c creates new bookmark via sl bookmark"
  artifacts:
    - path: "cmd_clean.py"
      provides: "Clean command handler with safety validation"
      exports: ["handle"]
    - path: "cmd_config.py"
      provides: "Config command handler with flag translation"
      exports: ["handle"]
    - path: "cmd_switch.py"
      provides: "Switch command handler with intent-based dispatch"
      exports: ["handle"]
    - path: "gitsl.py"
      provides: "Dispatch routing for clean, config, switch"
      contains: "cmd_clean, cmd_config, cmd_switch imports"
  key_links:
    - from: "gitsl.py"
      to: "cmd_clean.handle"
      via: "dispatch on parsed.command == 'clean'"
      pattern: 'if parsed.command == "clean"'
    - from: "gitsl.py"
      to: "cmd_config.handle"
      via: "dispatch on parsed.command == 'config'"
      pattern: 'if parsed.command == "config"'
    - from: "gitsl.py"
      to: "cmd_switch.handle"
      via: "dispatch on parsed.command == 'switch'"
      pattern: 'if parsed.command == "switch"'
---

<objective>
Create command handlers for clean, config, and switch with flag translation logic and dispatch routing.

Purpose: Enable git clean, git config, and git switch commands to work correctly in Sapling repos with proper flag translation and safety validation.

Output: 3 new cmd_*.py handlers + updated gitsl.py dispatch
</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/phases/16-flag-translation/16-RESEARCH.md
@cmd_rm.py (example handler with flag filtering)
@gitsl.py (dispatch structure)
@common.py (ParsedCommand, run_sl)
</context>

<tasks>

<task type="auto">
  <name>Task 1: Create 3 command handler files</name>
  <files>cmd_clean.py, cmd_config.py, cmd_switch.py</files>
  <action>
Create three handler files following the established cmd_*.py pattern from Phase 15:

**cmd_clean.py** (CRITICAL - Safety validation required):
- MUST check for -f/--force or -n/--dry-run before executing
- If neither present: print "fatal: clean.requireForce is true and -f not given: refusing to clean" to stderr, return 128
- Map -n/--dry-run to --print flag for sl purge
- Filter out -f/--force (not needed by sl purge)
- Filter out -d (sl purge handles untracked dir contents by default)
- Call run_sl(["purge"] + translated_args)

**cmd_config.py**:
- git config --list/-l: Filter out the flag, call run_sl(["config"]) with remaining args
- git config <key> <value> (two positional args): Add --local if no scope flag (--global, --local, --system, --user) present
- git config <key> (one positional arg): Pass through directly
- Call run_sl(["config"] + args)

**cmd_switch.py**:
- git switch -c/--create <name>: Extract branch name, call run_sl(["bookmark", name])
- git switch <branch>: Call run_sl(["goto"] + args)

Use the code examples from 16-RESEARCH.md as the implementation reference.
  </action>
  <verify>
All three files exist and are valid Python:
```bash
python3 -m py_compile cmd_clean.py cmd_config.py cmd_switch.py
```
Check safety validation logic in cmd_clean.py contains the exit 128 path.
  </verify>
  <done>
- cmd_clean.py implements safety check (rejects without -f/-n), maps -n to --print, filters -f and -d
- cmd_config.py implements --list translation, --local default for writes
- cmd_switch.py implements -c dispatch to bookmark, default dispatch to goto
  </done>
</task>

<task type="auto">
  <name>Task 2: Update gitsl.py dispatch routing</name>
  <files>gitsl.py</files>
  <action>
Add dispatch for the 3 new commands to gitsl.py:

1. Add imports at top (after existing cmd_* imports):
```python
import cmd_clean
import cmd_config
import cmd_switch
```

2. Add dispatch cases in main() before the "Unsupported command handling" section:
```python
if parsed.command == "clean":
    return cmd_clean.handle(parsed)

if parsed.command == "config":
    return cmd_config.handle(parsed)

if parsed.command == "switch":
    return cmd_switch.handle(parsed)
```

Follow the existing dispatch pattern (if/return, not elif).
  </action>
  <verify>
Test dispatch routing works:
```bash
GITSL_DEBUG=1 python3 gitsl.py clean -f 2>&1 | grep -q "clean" && echo "clean routes"
GITSL_DEBUG=1 python3 gitsl.py config --list 2>&1 | grep -q "config" && echo "config routes"
GITSL_DEBUG=1 python3 gitsl.py switch main 2>&1 | grep -q "switch" && echo "switch routes"
```

Note: Debug mode shows command info but does NOT execute handlers in debug mode. The above verifies parsing works. For actual handler execution, run without GITSL_DEBUG in an sl repo.
  </verify>
  <done>
- gitsl.py imports cmd_clean, cmd_config, cmd_switch
- Dispatch routes clean/config/switch to their handlers
- Commands no longer report "unsupported command"
  </done>
</task>

</tasks>

<verification>
Overall phase verification:

1. Safety check works:
```bash
cd /tmp && sl init test_clean && cd test_clean
python3 /path/to/gitsl.py clean 2>&1 | grep -q "refusing to clean" && echo "Safety check passes"
echo $?  # Should be 128
```

2. Clean with force:
```bash
echo "untracked" > untracked.txt
python3 /path/to/gitsl.py clean -f
ls untracked.txt 2>&1 | grep -q "No such file" && echo "Clean -f works"
```

3. Config operations:
```bash
python3 /path/to/gitsl.py config test.key test-value
python3 /path/to/gitsl.py config test.key | grep -q "test-value" && echo "Config read/write works"
```

4. Switch operations:
```bash
sl bookmark feature
python3 /path/to/gitsl.py switch feature  # Should work (goto)
python3 /path/to/gitsl.py switch -c newbranch  # Should create bookmark
```
</verification>

<success_criteria>
- [ ] cmd_clean.py exists with safety validation (exit 128 without -f/-n)
- [ ] cmd_config.py exists with --list and write scope handling
- [ ] cmd_switch.py exists with -c bookmark dispatch
- [ ] gitsl.py imports and dispatches to all 3 handlers
- [ ] git clean (no flags) returns exit code 128
- [ ] git clean -f executes sl purge
- [ ] git clean -n executes sl purge --print
- [ ] git config --list executes sl config
- [ ] git switch -c <name> executes sl bookmark <name>
- [ ] git switch <name> executes sl goto <name>
</success_criteria>

<output>
After completion, create `.planning/phases/16-flag-translation/16-01-SUMMARY.md`
</output>
