---
phase: 11-testing
plan: 01
type: execute
wave: 1
depends_on: []
files_modified:
  - test
  - test.cmd
  - pytest.ini
  - tests/conftest.py
  - tests/test_status.py
  - tests/test_add.py
  - tests/test_commit.py
  - tests/test_diff.py
  - tests/test_init.py
  - tests/test_log.py
  - tests/test_rev_parse.py
  - tests/test_unsupported.py
autonomous: true

must_haves:
  truths:
    - "Running ./test executes all tests and reports results"
    - "Running ./test status runs only status command tests"
    - "Running ./test add runs only add command tests"
    - "Test script creates venv automatically if missing"
    - "Test script installs pytest automatically if missing"
    - "Test script works on MacOS, Linux, and Windows"
  artifacts:
    - path: "test"
      provides: "Cross-platform test runner script"
      min_lines: 80
    - path: "test.cmd"
      provides: "Windows wrapper for test runner"
      min_lines: 2
    - path: "pytest.ini"
      provides: "Marker registration for command filtering"
      contains: "markers ="
  key_links:
    - from: "test"
      to: "pytest.ini"
      via: "pytest reads marker configuration"
      pattern: "markers"
    - from: "test"
      to: ".venv/bin/pytest"
      via: "script invokes venv pytest"
      pattern: "get_venv_pytest"
    - from: "tests/test_*.py"
      to: "pytest.ini"
      via: "markers registered and applied"
      pattern: "@pytest.mark"
---

<objective>
Create cross-platform test runner with command filtering and self-bootstrapping

Purpose: Enable simple `./test` invocation that works on any platform, auto-creates venv, installs dependencies, and supports filtering tests by command name.

Output:
- `test` - Python test runner script with shebang
- `test.cmd` - Windows batch wrapper
- Updated `pytest.ini` with registered markers
- Renamed test files from `test_cmd_*.py` to `test_*.py`
- Markers applied to all test files
</objective>

<context>
@.planning/PROJECT.md
@.planning/ROADMAP.md
@.planning/phases/11-testing/11-CONTEXT.md
@.planning/phases/11-testing/11-RESEARCH.md
@pytest.ini
@tests/conftest.py
</context>

<tasks>

<task type="auto">
  <name>Task 1: Create test runner script and Windows wrapper</name>
  <files>test, test.cmd</files>
  <action>
Create `test` Python script at project root with:

1. Shebang: `#!/usr/bin/env python3`
2. Cross-platform venv paths (Scripts/python.exe on Windows, bin/python on Unix)
3. Self-bootstrapping:
   - Check for sl binary upfront with `shutil.which("sl")`, print warning if missing
   - Create `.venv` using `venv.create()` if not present
   - Install pytest if not found in venv
4. Argument parsing:
   - `./test` runs all tests
   - `./test <command>` runs tests marked with that command (e.g., `./test status`)
   - `--report <file>` generates JUnit XML output
   - Pass through other args to pytest
5. Invoke venv pytest directly (no activation needed)
6. Use marker expression: `-m "{command} or always"` for filtering
7. Return pytest exit code

Create `test.cmd` Windows wrapper:
```batch
@echo off
python "%~dp0test" %*
```

Make `test` executable: `chmod +x test`
  </action>
  <verify>
Run `./test --help` to verify script runs (may show pytest help or usage).
Run `python test --help` on any platform.
  </verify>
  <done>
- `./test` script exists and is executable
- `test.cmd` Windows wrapper exists
- Script creates venv when run (or uses existing)
- Script installs pytest into venv
  </done>
</task>

<task type="auto">
  <name>Task 2: Update pytest.ini and register markers</name>
  <files>pytest.ini, tests/conftest.py</files>
  <action>
Update `pytest.ini` to register all command markers:

```ini
[pytest]
pythonpath = tests
testpaths = tests
markers =
    add: tests for git add command
    commit: tests for git commit command
    diff: tests for git diff command
    init: tests for git init command
    log: tests for git log command
    rev_parse: tests for git rev-parse command
    status: tests for git status command
    unsupported: tests for unsupported commands
    execution: tests for execution pipeline
    harness: tests for test harness utilities
    always: tests that run regardless of filter
```

In `tests/conftest.py`, add `run_gitsl` to module exports if not already importable. Ensure fixtures work with renamed test files.
  </action>
  <verify>
Run `./test` and verify no "PytestUnknownMarkWarning" warnings appear.
  </verify>
  <done>
- pytest.ini has markers section with all command markers registered
- No pytest warnings about unknown markers
  </done>
</task>

<task type="auto">
  <name>Task 3: Rename test files and apply markers</name>
  <files>tests/test_status.py, tests/test_add.py, tests/test_commit.py, tests/test_diff.py, tests/test_init.py, tests/test_log.py, tests/test_rev_parse.py, tests/test_unsupported.py</files>
  <action>
Rename test files (use git mv for history):
- `test_cmd_add.py` -> `test_add.py`
- `test_cmd_commit.py` -> `test_commit.py`
- `test_cmd_diff.py` -> `test_diff.py`
- `test_cmd_init.py` -> `test_init.py`
- `test_cmd_log.py` -> `test_log.py`
- `test_cmd_rev_parse.py` -> `test_rev_parse.py`
- `test_status_porcelain.py` -> `test_status.py`

For each renamed file, update the `pytestmark` line to include both the skip marker AND the command marker:
```python
pytestmark = [
    pytest.mark.skipif(not sl_available, reason="Sapling (sl) not installed"),
    pytest.mark.add,  # Use appropriate command name
]
```

For `test_execution.py`, add `pytest.mark.execution`.
For `test_harness.py`, add `pytest.mark.harness` or `pytest.mark.always` if tests should always run.
For `test_unsupported.py`, ensure proper marker is applied.
  </action>
  <verify>
Run `./test status` and verify only status tests run.
Run `./test add` and verify only add tests run.
Run `./test` and verify all tests run.
  </verify>
  <done>
- All test files renamed to `test_<command>.py` convention
- Each test file has appropriate command marker
- `./test status` runs only status tests
- `./test add` runs only add tests
- `./test` runs all tests
  </done>
</task>

</tasks>

<verification>
1. `./test` runs and creates venv if missing
2. `./test` runs all tests successfully
3. `./test status` runs only status tests (check test count)
4. `./test add` runs only add tests (check test count)
5. `./test --report results.xml` creates JUnit XML file
6. No pytest warnings about unknown markers
7. On Windows: `test.cmd` invokes Python correctly
</verification>

<success_criteria>
- TEST-01 SATISFIED: `./test` script runs all tests
- TEST-02 SATISFIED: `./test <command>` runs tests for specific command only
- TEST-03 SATISFIED: Test script works on MacOS, Linux, Windows (Python-based, Windows wrapper)
</success_criteria>

<output>
After completion, create `.planning/phases/11-testing/11-01-SUMMARY.md`
</output>
