---
phase: 17-branch-and-restore
plan: 01
type: execute
wave: 1
depends_on: []
files_modified:
  - cmd_branch.py
  - cmd_restore.py
  - gitsl.py
autonomous: true

must_haves:
  truths:
    - "git branch lists bookmarks"
    - "git branch <name> creates a bookmark"
    - "git branch -d <name> deletes a bookmark"
    - "git branch -D <name> safely deletes bookmark without stripping commits"
    - "git restore <file> discards working tree changes"
    - "git restore . discards all working tree changes"
  artifacts:
    - path: "cmd_branch.py"
      provides: "Branch command handler with -D to -d safety translation"
      exports: ["handle"]
    - path: "cmd_restore.py"
      provides: "Restore command handler translating to sl revert"
      exports: ["handle"]
    - path: "gitsl.py"
      provides: "Dispatch routing for branch and restore"
      contains: "cmd_branch"
  key_links:
    - from: "gitsl.py"
      to: "cmd_branch.handle"
      via: "dispatch on parsed.command == 'branch'"
      pattern: "parsed\\.command == \"branch\""
    - from: "gitsl.py"
      to: "cmd_restore.handle"
      via: "dispatch on parsed.command == 'restore'"
      pattern: "parsed\\.command == \"restore\""
    - from: "cmd_branch.py"
      to: "sl bookmark"
      via: "run_sl call"
      pattern: "run_sl\\(\\[\"bookmark\""
---

<objective>
Create branch and restore command handlers with dispatch routing.

Purpose: Enable users to manage bookmarks (git branch) and restore files (git restore) using familiar git commands translated to Sapling equivalents.

Output: Two command handlers (cmd_branch.py, cmd_restore.py) and updated gitsl.py dispatch.

CRITICAL SAFETY: git branch -D must translate to sl bookmark -d (NOT -D) because sl bookmark -D strips commits, while git branch -D only removes the label.
</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/17-branch-and-restore/17-RESEARCH.md
@cmd_switch.py
@cmd_clean.py
@gitsl.py
@common.py
</context>

<tasks>

<task type="auto">
  <name>Task 1: Create branch and restore command handlers</name>
  <files>cmd_branch.py, cmd_restore.py</files>
  <action>
Create cmd_branch.py with handler for git branch command:

```python
"""Handler for 'git branch' command."""

from common import ParsedCommand, run_sl


def handle(parsed: ParsedCommand) -> int:
    """
    Handle 'git branch' command.

    Translations:
    - git branch              -> sl bookmark (list)
    - git branch <name>       -> sl bookmark <name> (create)
    - git branch -d <name>    -> sl bookmark -d <name> (delete)
    - git branch -D <name>    -> sl bookmark -d <name> (safe delete)

    SAFETY: git branch -D just removes the label. sl bookmark -D strips
    commits. We ALWAYS use -d to preserve commits.
    """
    args = list(parsed.args)

    # CRITICAL: Translate -D to -d to avoid destroying commits
    # git -D: force delete label, commits preserved
    # sl -D: delete label AND strip commits (destructive!)
    args = ['-d' if a == '-D' else a for a in args]

    return run_sl(["bookmark"] + args)
```

Create cmd_restore.py with handler for git restore command:

```python
"""Handler for 'git restore' command."""

from common import ParsedCommand, run_sl


def handle(parsed: ParsedCommand) -> int:
    """
    Handle 'git restore' command.

    Translations:
    - git restore <file>  -> sl revert <file>
    - git restore .       -> sl revert .

    Note: This handles working tree restoration only.
    git restore --staged is out of scope (not in Phase 17 requirements).
    """
    return run_sl(["revert"] + list(parsed.args))
```

Both handlers follow the established cmd_*.py pattern from Phase 15/16.
  </action>
  <verify>
    - Files exist: `ls cmd_branch.py cmd_restore.py`
    - Python syntax: `python -m py_compile cmd_branch.py cmd_restore.py`
    - Import test: `python -c "import cmd_branch; import cmd_restore; print('OK')"`
  </verify>
  <done>
    - cmd_branch.py exists with handle() function that translates -D to -d
    - cmd_restore.py exists with handle() function that passes to sl revert
    - Both files import from common and use run_sl
  </done>
</task>

<task type="auto">
  <name>Task 2: Update gitsl.py dispatch routing</name>
  <files>gitsl.py</files>
  <action>
Add imports at top of gitsl.py (after existing cmd_* imports):

```python
import cmd_branch
import cmd_restore
```

Add dispatch cases in main() function (before the unsupported command handling):

```python
if parsed.command == "branch":
    return cmd_branch.handle(parsed)

if parsed.command == "restore":
    return cmd_restore.handle(parsed)
```

Follow the exact pattern used for switch, clean, and other commands in Phase 16.
  </action>
  <verify>
    - Syntax check: `python -m py_compile gitsl.py`
    - Debug mode test: `GITSL_DEBUG=1 python gitsl.py branch` should show parsed command
    - Debug mode test: `GITSL_DEBUG=1 python gitsl.py restore` should show parsed command
  </verify>
  <done>
    - gitsl.py imports cmd_branch and cmd_restore
    - Dispatch routes branch and restore commands to handlers
    - Debug mode shows commands are recognized (not unsupported)
  </done>
</task>

</tasks>

<verification>
Run from project root:

```bash
# Verify handlers exist and compile
python -m py_compile cmd_branch.py cmd_restore.py gitsl.py

# Test debug mode (no repo needed)
GITSL_DEBUG=1 python gitsl.py branch
GITSL_DEBUG=1 python gitsl.py branch feature-x
GITSL_DEBUG=1 python gitsl.py branch -d feature-x
GITSL_DEBUG=1 python gitsl.py branch -D feature-x
GITSL_DEBUG=1 python gitsl.py restore README.md
GITSL_DEBUG=1 python gitsl.py restore .
```

All commands should show debug output, not "unsupported command" message.
</verification>

<success_criteria>
1. cmd_branch.py exists with handle() function that translates -D to -d for safety
2. cmd_restore.py exists with handle() function that translates to sl revert
3. gitsl.py imports both handlers and routes commands correctly
4. All files pass Python syntax validation
5. Debug mode confirms commands are recognized
</success_criteria>

<output>
After completion, create `.planning/phases/17-branch-and-restore/17-01-SUMMARY.md`
</output>
