# Clean Install Test Plan > **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. **Goal:** Add an opt-in pytest test that clones the Manual Slop repo to a temp dir, runs `uv sync`, launches `sloppy.py --enable-test-hooks`, and verifies the Hook API responds. Catches "works on my machine" failures by exercising the full install-and-launch path in an isolated environment. **Architecture:** Standard subprocess-based integration test. `git clone` from the user's Gitea server to `tmp_path`. `uv sync` in the cloned dir. Launch the app as a background subprocess. Poll the Hook API endpoint with `requests` until ready. Test a write hook. Clean up the process tree. **Tech Stack:** Python 3.11+, pytest, subprocess, requests, git CLI **Spec:** `docs/superpowers/specs/2026-06-02-clean-install-test-design.md` --- ## Execution Constraints - **No subagents.** Execute as a single agent. - **Pre-edit checkpoint:** `git add .` before any file edit. - **Per-file atomic commits.** - **Commit message format:** `(): `. - **Git note format:** 3-8 line rationale per commit. - **Style baseline:** 1-space indent, no comments, type hints. --- ## File Structure | File | Action | Responsibility | |---|---|---| | `tests/test_clean_install.py` | Create | Opt-in test (RUN_CLEAN_INSTALL_TEST=1) | | `pyproject.toml` | Modify | Add `clean_install` marker | --- ## Task 1: Add the `clean_install` marker to `pyproject.toml` **Files:** - Modify: `pyproject.toml` - [ ] **Step 1.1: Pre-edit checkpoint** ```powershell git -C C:\projects\manual_slop add . ``` - [ ] **Step 1.2: Read current markers section** Use `manual-slop_py_get_code_outline` or grep for `markers` in `pyproject.toml`. - [ ] **Step 1.3: Add the `clean_install` marker** Find the existing markers list (e.g., under `[tool.pytest.ini_options]`) and add: ```toml markers = [ "integration: integration tests requiring live GUI", "strict: tests that require strict mode", "clean_install: clean install verification (opt-in via RUN_CLEAN_INSTALL_TEST=1)", ] ``` If markers aren't already in `pyproject.toml`, add them. If they are, append the new entry. - [ ] **Step 1.4: Commit** ```bash git -C C:\projects\manual_slop add pyproject.toml git -C C:\projects\manual_slop commit -m "test(pytest): add clean_install marker" git -C C:\projects\manual_slop log -1 --format='%H' | ForEach-Object { git -C C:\projects\manual_slop notes add -m "Registers the clean_install marker so tests can be selected with pytest -m clean_install or filtered with -m 'not clean_install'." $_ } ``` --- ## Task 2: Write the clean install test **Files:** - Create: `tests/test_clean_install.py` - [ ] **Step 2.1: Pre-edit checkpoint** ```powershell git -C C:\projects\manual_slop add . ``` - [ ] **Step 2.2: Create the test file** ```python # tests/test_clean_install.py import os import subprocess import sys import time from pathlib import Path import pytest import requests REPO_URL = "https://git.cozyair.dev/ed/manual_slop" STARTUP_TIMEOUT_SECONDS = 30 READINESS_POLL_INTERVAL = 0.5 HOOK_PORT = 8999 @pytest.mark.clean_install def test_clean_install_runs_with_hooks(tmp_path): """Clone the repo, install deps, launch sloppy.py, verify Hook API. Opt-in: set RUN_CLEAN_INSTALL_TEST=1 to enable. Otherwise skipped. Requires network access to the configured REPO_URL. """ if os.environ.get("RUN_CLEAN_INSTALL_TEST") != "1": pytest.skip("Set RUN_CLEAN_INSTALL_TEST=1 to enable") clone_dir = tmp_path / "manual_slop" project_root = Path(__file__).resolve().parent.parent subprocess.run( ["git", "clone", REPO_URL, str(clone_dir)], capture_output=True, text=True, timeout=60, check=True, ) subprocess.run( ["uv", "sync"], cwd=str(clone_dir), capture_output=True, text=True, timeout=180, check=True, ) creationflags = 0 if os.name == "nt": creationflags = subprocess.CREATE_NEW_PROCESS_GROUP process = subprocess.Popen( ["uv", "run", "sloppy.py", "--enable-test-hooks"], cwd=str(clone_dir), stdout=subprocess.PIPE, stderr=subprocess.PIPE, creationflags=creationflags, ) try: start = time.time() ready = False while time.time() - start < STARTUP_TIMEOUT_SECONDS: if process.poll() is not None: stderr_out = process.stderr.read(2000) if process.stderr else b"" pytest.fail(f"Process exited early. stderr: {stderr_out.decode('utf-8', errors='replace')}") try: response = requests.get( f"http://127.0.0.1:{HOOK_PORT}/status", timeout=1.0, ) if response.status_code == 200: payload = response.json() if payload.get("status") in ("running", "ready", "ok"): ready = True break except (requests.ConnectionError, requests.Timeout): pass time.sleep(READINESS_POLL_INTERVAL) assert ready, ( f"Hook server did not respond within {STARTUP_TIMEOUT_SECONDS}s. " f"stderr: {process.stderr.read(2000).decode('utf-8', errors='replace') if process.stderr else 'N/A'}" ) response = requests.get( f"http://127.0.0.1:{HOOK_PORT}/api/gui/mma_status", timeout=5.0, ) assert response.status_code == 200, f"mma_status returned {response.status_code}" data = response.json() assert isinstance(data, dict), f"mma_status returned non-dict: {data!r}" finally: _cleanup_process(process) def _cleanup_process(process: subprocess.Popen) -> None: if os.name == "nt": subprocess.run( ["taskkill", "/F", "/T", "/PID", str(process.pid)], capture_output=True, ) else: process.terminate() try: process.wait(timeout=5) except subprocess.TimeoutExpired: process.kill() ``` - [ ] **Step 2.3: Run the test in skip mode** ```powershell uv run pytest tests/test_clean_install.py -v ``` Expected: SKIPPED (RUN_CLEAN_INSTALL_TEST not set). - [ ] **Step 2.4: Commit** ```bash git -C C:\projects\manual_slop add tests/test_clean_install.py git -C C:\projects\manual_slop commit -m "test(clean-install): add opt-in clone-and-verify pytest test" git -C C:\projects\manual_slop log -1 --format='%H' | ForEach-Object { git -C C:\projects\manual_slop notes add -m "Clones the Gitea repo to tmp_path, runs uv sync, launches sloppy.py --enable-test-hooks, polls :8999/status until ready, then tests /api/gui/mma_status write hook. Robust Windows/Unix process cleanup. Skipped unless RUN_CLEAN_INSTALL_TEST=1." $_ } ``` --- ## Task 3: Phase Completion Verification - [ ] **Step 3.1: Confirm test is properly gated** ```powershell uv run pytest tests/test_clean_install.py -v ``` Expected: 1 skipped. - [ ] **Step 3.2: Manual opt-in run (if network is available)** ```powershell RUN_CLEAN_INSTALL_TEST=1 uv run pytest tests/test_clean_install.py -v ``` Expected: 1 passed (or 1 failed with clear diagnostic if the clone target is unreachable). - [ ] **Step 3.3: Create the checkpoint commit** ```bash git -C C:\projects\manual_slop commit --allow-empty -m "conductor(checkpoint): Clean install test complete" git -C C:\projects\manual_slop log -1 --format='%H' | ForEach-Object { git -C C:\projects\manual_slop notes add -m "Track complete. Opt-in test (RUN_CLEAN_INSTALL_TEST=1) added. Verifies clone + uv sync + launch + hook API. Marked with @pytest.mark.clean_install." $_ } ``` --- ## Self-Review - **Spec coverage:** All design tasks have a plan task. ✓ - **Placeholder scan:** Test code is complete. ✓ - **Type consistency:** `tmp_path`, `process`, `response` used consistently. ✓ - **Robust cleanup:** `_cleanup_process` handles Windows + Unix. ✓