import platform import subprocess import sys import tempfile import unittest from pathlib import Path ROOT = Path(__file__).resolve().parents[1] SCRIPT = ROOT / "scripts" / "main_loop.py" def run_cli(*args, cwd=None): return subprocess.run( [sys.executable, str(SCRIPT), *args], capture_output=True, text=True, cwd=cwd, ) class MainLoopCliTests(unittest.TestCase): def _current_env(self) -> str: system = platform.system().lower() mapping = {"windows": "windows", "linux": "linux", "darwin": "darwin"} if system not in mapping: self.skipTest(f"Unsupported environment: {system}") return mapping[system] def test_claim_seeds_progress_and_marks_first_plan_in_progress(self): with tempfile.TemporaryDirectory() as tmp_dir: root = Path(tmp_dir) plans_dir = root / "docs" / "plans" plans_dir.mkdir(parents=True) (plans_dir / "2026-01-01-old.md").write_text("old", encoding="utf-8") (plans_dir / "2026-01-02-new.md").write_text("new", encoding="utf-8") result = run_cli( "claim", "-plans", "docs/plans", "-progress", "memory-bank/progress.md", cwd=root, ) self.assertEqual(result.returncode, 0, msg=result.stderr) self.assertEqual(result.stdout.strip(), "PLAN=docs/plans/2026-01-01-old.md") progress = root / "memory-bank" / "progress.md" text = progress.read_text(encoding="utf-8") self.assertIn("", text) self.assertIn("", text) self.assertIn("`2026-01-01-old.md` in-progress", text) self.assertIn("`2026-01-02-new.md` pending", text) def test_claim_returns_existing_in_progress_before_pending(self): with tempfile.TemporaryDirectory() as tmp_dir: root = Path(tmp_dir) plans_dir = root / "docs" / "plans" plans_dir.mkdir(parents=True) (plans_dir / "2026-01-01-a.md").write_text("a", encoding="utf-8") (plans_dir / "2026-01-02-b.md").write_text("b", encoding="utf-8") progress = root / "memory-bank" / "progress.md" progress.parent.mkdir(parents=True) progress.write_text( "\n".join( [ "# Plan 状态", "", "", "- [ ] `2026-01-02-b.md` pending", "- [ ] `2026-01-01-a.md` in-progress", "", "", ] ), encoding="utf-8", ) result = run_cli( "claim", "-plans", "docs/plans", "-progress", "memory-bank/progress.md", cwd=root, ) self.assertEqual(result.returncode, 0, msg=result.stderr) self.assertEqual(result.stdout.strip(), "PLAN=docs/plans/2026-01-01-a.md") def test_claim_resumes_env_blocked_plan_and_preserves_note(self): with tempfile.TemporaryDirectory() as tmp_dir: root = Path(tmp_dir) plans_dir = root / "docs" / "plans" plans_dir.mkdir(parents=True) (plans_dir / "2026-01-05-env.md").write_text("env", encoding="utf-8") progress = root / "memory-bank" / "progress.md" progress.parent.mkdir(parents=True) env = self._current_env() note = f"env:{env}:Task1,Task3" progress.write_text( "\n".join( [ "# Plan 状态", "", "", f"- [ ] `2026-01-05-env.md` blocked: {note}", "", "", ] ), encoding="utf-8", ) result = run_cli( "claim", "-plans", "docs/plans", "-progress", "memory-bank/progress.md", cwd=root, ) self.assertEqual(result.returncode, 0, msg=result.stderr) self.assertEqual( result.stdout.strip(), "\n".join( [ "PLAN=docs/plans/2026-01-05-env.md", f"NOTE={note}", ] ), ) text = progress.read_text(encoding="utf-8") self.assertIn(f"`2026-01-05-env.md` in-progress: {note}", text) def test_finish_updates_line(self): with tempfile.TemporaryDirectory() as tmp_dir: root = Path(tmp_dir) progress = root / "memory-bank" / "progress.md" progress.parent.mkdir(parents=True) progress.write_text( "\n".join( [ "# Plan 状态", "", "", "- [ ] `2026-01-03-demo.md` in-progress", "", "", ] ), encoding="utf-8", ) result = run_cli( "finish", "-plan", "docs/plans/2026-01-03-demo.md", "-status", "done", "-progress", "memory-bank/progress.md", cwd=root, ) self.assertEqual(result.returncode, 0, msg=result.stderr) text = progress.read_text(encoding="utf-8") self.assertIn("- [x] `2026-01-03-demo.md` done", text) self.assertEqual(text.count("2026-01-03-demo.md"), 1) if __name__ == "__main__": unittest.main()