---
phase: 09-unsupported-command-handling
plan: 01
type: execute
wave: 1
depends_on: []
files_modified:
  - gitsl.py
  - tests/test_unsupported.py
autonomous: true

must_haves:
  truths:
    - "Unsupported commands print informative message to stderr"
    - "Unsupported commands exit with code 0"
    - "Unsupported commands produce empty stdout"
    - "Message includes the full original git command with arguments"
  artifacts:
    - path: "gitsl.py"
      provides: "Unsupported command fallback handler"
      contains: "unsupported command"
    - path: "tests/test_unsupported.py"
      provides: "E2E tests for unsupported command behavior"
      min_lines: 30
  key_links:
    - from: "gitsl.py"
      to: "shlex.join"
      via: "command reconstruction"
      pattern: "shlex\\.join"
    - from: "tests/test_unsupported.py"
      to: "conftest.run_gitsl"
      via: "test helper import"
      pattern: "run_gitsl"
---

<objective>
Implement graceful handling for unsupported git commands by replacing the `[STUB]` fallback with a proper error message.

Purpose: Unsupported commands should inform users while not breaking calling tools that expect exit code 0 on success.

Output: Updated gitsl.py fallback section and E2E tests verifying the behavior.
</objective>

<context>
@.planning/PROJECT.md
@.planning/ROADMAP.md
@.planning/phases/09-unsupported-command-handling/09-RESEARCH.md
@gitsl.py
@tests/conftest.py
</context>

<tasks>

<task type="auto">
  <name>Task 1: Replace STUB fallback with proper unsupported command message</name>
  <files>gitsl.py</files>
  <action>
  Modify gitsl.py to:

  1. Add `import shlex` at the top (add to existing imports)

  2. Replace the fallback section (lines 80-82) with:
     ```python
     # Unsupported command handling (UNSUP-01, UNSUP-02)
     if parsed.args:
         original_command = f"git {parsed.command} {shlex.join(parsed.args)}"
     else:
         original_command = f"git {parsed.command}"

     print(f"gitsl: unsupported command: {original_command}", file=sys.stderr)
     return 0
     ```

  Key requirements:
  - Message format: `gitsl: unsupported command: git <command> [args]`
  - Use shlex.join() for args to handle spaces and special chars correctly
  - Print to stderr (file=sys.stderr) - NOT stdout
  - Return 0 (exit code) - NOT 1 or other non-zero
  </action>
  <verify>
  Run manually:
  ```bash
  cd /Users/vmakaev/NonWork/gitsl
  python gitsl.py push origin main 2>&1
  # Should output: gitsl: unsupported command: git push origin main

  python gitsl.py push origin main; echo "Exit: $?"
  # Should show: Exit: 0

  python gitsl.py push 2>/dev/null
  # Should output nothing (message goes to stderr)
  ```
  </verify>
  <done>
  - `gitsl push origin main` prints "gitsl: unsupported command: git push origin main" to stderr
  - `gitsl push` prints "gitsl: unsupported command: git push" to stderr
  - Exit code is 0 for any unsupported command
  - Stdout is empty (message only on stderr)
  </done>
</task>

<task type="auto">
  <name>Task 2: Add E2E tests for unsupported commands</name>
  <files>tests/test_unsupported.py</files>
  <action>
  Create tests/test_unsupported.py with E2E tests for unsupported command behavior:

  ```python
  """
  E2E tests for unsupported command handling (UNSUP-01, UNSUP-02).
  """

  from pathlib import Path

  from conftest import run_gitsl


  class TestUnsupportedCommands:
      """Tests for unsupported command handling."""

      def test_push_exits_zero(self, sl_repo: Path):
          """UNSUP-02: Unsupported commands exit with code 0."""
          result = run_gitsl(["push"], cwd=sl_repo)
          assert result.exit_code == 0

      def test_push_message_on_stderr(self, sl_repo: Path):
          """UNSUP-01: Unsupported commands print original command to stderr."""
          result = run_gitsl(["push"], cwd=sl_repo)
          assert "gitsl: unsupported command: git push" in result.stderr

      def test_push_with_args_includes_full_command(self, sl_repo: Path):
          """Message includes all arguments."""
          result = run_gitsl(["push", "origin", "main"], cwd=sl_repo)
          assert "git push origin main" in result.stderr

      def test_push_stdout_empty(self, sl_repo: Path):
          """Unsupported commands don't pollute stdout."""
          result = run_gitsl(["push"], cwd=sl_repo)
          assert result.stdout == ""

      def test_rebase_unsupported(self, sl_repo: Path):
          """Another unsupported command works the same way."""
          result = run_gitsl(["rebase", "main"], cwd=sl_repo)
          assert result.exit_code == 0
          assert "git rebase main" in result.stderr
          assert result.stdout == ""

      def test_fetch_unsupported(self, sl_repo: Path):
          """fetch is also unsupported."""
          result = run_gitsl(["fetch", "--all"], cwd=sl_repo)
          assert result.exit_code == 0
          assert "git fetch --all" in result.stderr

      def test_checkout_unsupported(self, sl_repo: Path):
          """checkout is unsupported."""
          result = run_gitsl(["checkout", "-b", "feature"], cwd=sl_repo)
          assert result.exit_code == 0
          assert "git checkout -b feature" in result.stderr
  ```

  Test coverage:
  - UNSUP-02: Exit code is 0
  - UNSUP-01: Original command printed to stderr
  - Arguments are included in message
  - Stdout is empty
  - Multiple unsupported commands work consistently (push, rebase, fetch, checkout)
  </action>
  <verify>
  Run the tests:
  ```bash
  cd /Users/vmakaev/NonWork/gitsl
  python -m pytest tests/test_unsupported.py -v
  # All tests should pass
  ```
  </verify>
  <done>
  - All tests in test_unsupported.py pass
  - Tests cover both requirements (UNSUP-01, UNSUP-02)
  - Tests verify multiple unsupported commands for consistency
  </done>
</task>

</tasks>

<verification>
Run the full test suite to ensure no regressions:

```bash
cd /Users/vmakaev/NonWork/gitsl
python -m pytest tests/ -v
```

All existing tests plus new unsupported command tests should pass.

Manual verification:
```bash
# Test various unsupported commands
python gitsl.py push 2>&1 | head -1
python gitsl.py pull origin main 2>&1 | head -1
python gitsl.py rebase -i HEAD~3 2>&1 | head -1

# Verify exit codes
python gitsl.py push; echo $?  # Should be 0
python gitsl.py unknown-cmd; echo $?  # Should be 0
```
</verification>

<success_criteria>
1. `gitsl push` exits with code 0 (UNSUP-02)
2. `gitsl push origin main` prints "gitsl: unsupported command: git push origin main" to stderr (UNSUP-01)
3. Unsupported commands produce empty stdout
4. All tests in tests/test_unsupported.py pass
5. Existing test suite still passes (no regressions)
</success_criteria>

<output>
After completion, create `.planning/phases/09-unsupported-command-handling/09-01-SUMMARY.md`
</output>
