🐛 fix(templates): enforce main loop progress tracking
Update Third-party Superpowers / Update thirdparty/skill snapshot (push) Successful in 1m20s

replace the old select/record progress flow with a single main_loop claim/finish CLI.

route template execution through main_loop only, remove the legacy plan_progress entry points, and update tests to enforce the new behavior.
This commit is contained in:
csh
2026-03-12 17:47:33 +08:00
parent 51373d7469
commit 7b84daf3bd
7 changed files with 198 additions and 159 deletions
+1 -1
View File
@@ -14,7 +14,7 @@ tests/
├── test_no_backup_flags.py # no_backup 行为测试
├── test_sync_directory_actions.py # sync_memory_bank/sync_prompts 行为测试
├── test_vendor_snapshot_templates.py # vendor 快照模板完整性测试
├── test_plan_progress_cli.py # plan_progress CLI 测试
├── test_main_loop_cli.py # main_loop CLI 测试
├── test_superpowers_list_sync.py # superpowers 列表一致性测试
├── test_superpowers_workflows.py # superpowers 工作流配置校验
├── test_sync_templates_placeholders.py # 占位符替换测试(sync_rules/sync_standards
@@ -1,12 +1,12 @@
import platform
import subprocess
import sys
import tempfile
import unittest
import platform
from pathlib import Path
ROOT = Path(__file__).resolve().parents[1]
SCRIPT = ROOT / "scripts" / "plan_progress.py"
SCRIPT = ROOT / "scripts" / "main_loop.py"
def run_cli(*args, cwd=None):
@@ -18,7 +18,7 @@ def run_cli(*args, cwd=None):
)
class PlanProgressCliTests(unittest.TestCase):
class MainLoopCliTests(unittest.TestCase):
def _current_env(self) -> str:
system = platform.system().lower()
mapping = {"windows": "windows", "linux": "linux", "darwin": "darwin"}
@@ -26,7 +26,7 @@ class PlanProgressCliTests(unittest.TestCase):
self.skipTest(f"Unsupported environment: {system}")
return mapping[system]
def test_select_seeds_progress_when_missing(self):
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"
@@ -35,7 +35,7 @@ class PlanProgressCliTests(unittest.TestCase):
(plans_dir / "2026-01-02-new.md").write_text("new", encoding="utf-8")
result = run_cli(
"select",
"claim",
"-plans",
"docs/plans",
"-progress",
@@ -44,16 +44,16 @@ class PlanProgressCliTests(unittest.TestCase):
)
self.assertEqual(result.returncode, 0, msg=result.stderr)
self.assertEqual(result.stdout.strip(), "docs/plans/2026-01-01-old.md")
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("<!-- plan-status:start -->", text)
self.assertIn("<!-- plan-status:end -->", text)
self.assertIn("`2026-01-01-old.md` pending", text)
self.assertIn("`2026-01-01-old.md` in-progress", text)
self.assertIn("`2026-01-02-new.md` pending", text)
def test_select_returns_first_pending_in_order(self):
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"
@@ -70,7 +70,7 @@ class PlanProgressCliTests(unittest.TestCase):
"",
"<!-- plan-status:start -->",
"- [ ] `2026-01-02-b.md` pending",
"- [ ] `2026-01-01-a.md` pending",
"- [ ] `2026-01-01-a.md` in-progress",
"<!-- plan-status:end -->",
"",
]
@@ -79,7 +79,7 @@ class PlanProgressCliTests(unittest.TestCase):
)
result = run_cli(
"select",
"claim",
"-plans",
"docs/plans",
"-progress",
@@ -88,9 +88,9 @@ class PlanProgressCliTests(unittest.TestCase):
)
self.assertEqual(result.returncode, 0, msg=result.stderr)
self.assertEqual(result.stdout.strip(), "docs/plans/2026-01-02-b.md")
self.assertEqual(result.stdout.strip(), "PLAN=docs/plans/2026-01-01-a.md")
def test_select_returns_env_blocked_plan_without_flag(self):
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"
@@ -100,13 +100,14 @@ class PlanProgressCliTests(unittest.TestCase):
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 状态",
"",
"<!-- plan-status:start -->",
f"- [ ] `2026-01-05-env.md` blocked: env:{env}:Task1",
f"- [ ] `2026-01-05-env.md` blocked: {note}",
"<!-- plan-status:end -->",
"",
]
@@ -115,7 +116,7 @@ class PlanProgressCliTests(unittest.TestCase):
)
result = run_cli(
"select",
"claim",
"-plans",
"docs/plans",
"-progress",
@@ -124,9 +125,20 @@ class PlanProgressCliTests(unittest.TestCase):
)
self.assertEqual(result.returncode, 0, msg=result.stderr)
self.assertEqual(result.stdout.strip(), "docs/plans/2026-01-05-env.md")
self.assertEqual(
result.stdout.strip(),
"\n".join(
[
"PLAN=docs/plans/2026-01-05-env.md",
f"NOTE={note}",
]
),
)
def test_record_updates_line(self):
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"
@@ -137,7 +149,7 @@ class PlanProgressCliTests(unittest.TestCase):
"# Plan 状态",
"",
"<!-- plan-status:start -->",
"- [ ] `2026-01-03-demo.md` pending",
"- [ ] `2026-01-03-demo.md` in-progress",
"<!-- plan-status:end -->",
"",
]
@@ -146,7 +158,7 @@ class PlanProgressCliTests(unittest.TestCase):
)
result = run_cli(
"record",
"finish",
"-plan",
"docs/plans/2026-01-03-demo.md",
"-status",
+4 -1
View File
@@ -50,7 +50,10 @@ langs = [\"cpp\", \"tsl\"]
rules_md = Path(tmp_dir) / "AGENT_RULES.md"
rules_text = rules_md.read_text(encoding="utf-8")
self.assertIn("docs/standards/playbook/scripts/plan_progress.py", rules_text)
self.assertIn("docs/standards/playbook/scripts/main_loop.py claim", rules_text)
self.assertNotIn("plan_progress.py", rules_text)
self.assertIn("不得直接使用 `$executing-plans`", rules_text)
self.assertIn("不得直接使用 `$subagent-driven-development`", rules_text)
self.assertNotIn("{{PLAYBOOK_SCRIPTS}}", rules_text)
def test_sync_standards_rewrites_typescript_docs_prefix_for_vendored_playbook(self):