🐛 fix(playbook): address reported repo issues
normalize Windows path-like TOML config values, regenerate .agents/index.md on sync, keep the SKILLS.md superpowers section route-only, and ignore generated Python cache dirs. add regression coverage for load_config() and the standards sync behavior touched by these fixes.
This commit is contained in:
@@ -101,6 +101,46 @@ langs = ["tsl"]
|
||||
self.assertEqual(result.returncode, 0)
|
||||
self.assertTrue(agents_index.is_file())
|
||||
|
||||
def test_sync_standards_updates_agents_index_when_langs_expand(self):
|
||||
with tempfile.TemporaryDirectory() as tmp_dir:
|
||||
root = Path(tmp_dir)
|
||||
|
||||
first_config = root / "playbook-first.toml"
|
||||
first_config.write_text(
|
||||
f"""
|
||||
[playbook]
|
||||
project_root = "{tmp_dir}"
|
||||
|
||||
[sync_standards]
|
||||
langs = ["tsl"]
|
||||
no_backup = true
|
||||
""",
|
||||
encoding="utf-8",
|
||||
)
|
||||
|
||||
first_result = run_cli("-config", str(first_config))
|
||||
self.assertEqual(first_result.returncode, 0)
|
||||
|
||||
second_config = root / "playbook-second.toml"
|
||||
second_config.write_text(
|
||||
f"""
|
||||
[playbook]
|
||||
project_root = "{tmp_dir}"
|
||||
|
||||
[sync_standards]
|
||||
langs = ["tsl", "cpp"]
|
||||
no_backup = true
|
||||
""",
|
||||
encoding="utf-8",
|
||||
)
|
||||
|
||||
second_result = run_cli("-config", str(second_config))
|
||||
self.assertEqual(second_result.returncode, 0)
|
||||
|
||||
agents_index = (root / ".agents" / "index.md").read_text(encoding="utf-8")
|
||||
self.assertIn("`.agents/tsl/index.md`", agents_index)
|
||||
self.assertIn("`.agents/cpp/index.md`", agents_index)
|
||||
|
||||
def test_sync_standards_agents_block_has_blank_lines(self):
|
||||
with tempfile.TemporaryDirectory() as tmp_dir:
|
||||
config_body = f"""
|
||||
|
||||
@@ -4,6 +4,7 @@ from pathlib import Path
|
||||
ROOT = Path(__file__).resolve().parents[1]
|
||||
SKILLS_MD = ROOT / "SKILLS.md"
|
||||
SOURCES_LIST = ROOT / "codex" / "skills" / ".sources" / "superpowers.list"
|
||||
SOURCE_REF = "来源:`codex/skills/.sources/superpowers.list`(第三方来源清单)。"
|
||||
|
||||
|
||||
def read_sources_list() -> list[str]:
|
||||
@@ -14,28 +15,20 @@ def read_sources_list() -> list[str]:
|
||||
]
|
||||
|
||||
|
||||
def read_skills_md_list() -> list[str]:
|
||||
lines = SKILLS_MD.read_text(encoding="utf-8").splitlines()
|
||||
start = "<!-- superpowers:skills:start -->"
|
||||
end = "<!-- superpowers:skills:end -->"
|
||||
try:
|
||||
start_idx = lines.index(start) + 1
|
||||
end_idx = lines.index(end)
|
||||
except ValueError as exc:
|
||||
raise AssertionError("superpowers markers missing in SKILLS.md") from exc
|
||||
|
||||
items = []
|
||||
for line in lines[start_idx:end_idx]:
|
||||
stripped = line.strip()
|
||||
if not stripped.startswith("-"):
|
||||
continue
|
||||
items.append(stripped.lstrip("- ").strip())
|
||||
return items
|
||||
def read_skills_md() -> str:
|
||||
return SKILLS_MD.read_text(encoding="utf-8")
|
||||
|
||||
|
||||
class SuperpowersListSyncTests(unittest.TestCase):
|
||||
def test_superpowers_list_matches_skills_md(self):
|
||||
self.assertEqual(read_sources_list(), read_skills_md_list())
|
||||
def test_superpowers_section_routes_to_source_list(self):
|
||||
self.assertTrue(read_sources_list())
|
||||
|
||||
text = read_skills_md()
|
||||
|
||||
self.assertIn(SOURCE_REF, text)
|
||||
self.assertEqual(text.count("Third-party Skills (superpowers)"), 1)
|
||||
self.assertNotIn("<!-- superpowers:skills:start -->", text)
|
||||
self.assertNotIn("<!-- superpowers:skills:end -->", text)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
import tempfile
|
||||
import unittest
|
||||
from pathlib import Path
|
||||
|
||||
from scripts import playbook
|
||||
|
||||
@@ -18,6 +20,44 @@ key = 1
|
||||
with self.assertRaises(ValueError):
|
||||
playbook.loads_toml_minimal(raw)
|
||||
|
||||
def test_load_config_preserves_windows_users_path_in_basic_string(self):
|
||||
with tempfile.TemporaryDirectory() as tmp_dir:
|
||||
config_path = Path(tmp_dir) / "playbook.toml"
|
||||
config_path.write_text(
|
||||
'[playbook]\nproject_root = "C:\\Users\\demo\\workspace"\n',
|
||||
encoding="utf-8",
|
||||
)
|
||||
|
||||
data = playbook.load_config(config_path)
|
||||
|
||||
self.assertEqual(data["playbook"]["project_root"], r"C:\Users\demo\workspace")
|
||||
|
||||
def test_load_config_preserves_windows_escape_like_segments_for_path_keys(self):
|
||||
with tempfile.TemporaryDirectory() as tmp_dir:
|
||||
config_path = Path(tmp_dir) / "playbook.toml"
|
||||
config_path.write_text(
|
||||
'[playbook]\nproject_root = "C:\\tmp\\notes"\n\n'
|
||||
'[install_skills]\nagents_home = "D:\\new\\tab"\n',
|
||||
encoding="utf-8",
|
||||
)
|
||||
|
||||
data = playbook.load_config(config_path)
|
||||
|
||||
self.assertEqual(data["playbook"]["project_root"], r"C:\tmp\notes")
|
||||
self.assertEqual(data["install_skills"]["agents_home"], r"D:\new\tab")
|
||||
|
||||
def test_load_config_keeps_already_escaped_windows_path(self):
|
||||
with tempfile.TemporaryDirectory() as tmp_dir:
|
||||
config_path = Path(tmp_dir) / "playbook.toml"
|
||||
config_path.write_text(
|
||||
'[playbook]\nproject_root = "C:\\\\Users\\\\demo\\\\workspace"\n',
|
||||
encoding="utf-8",
|
||||
)
|
||||
|
||||
data = playbook.load_config(config_path)
|
||||
|
||||
self.assertEqual(data["playbook"]["project_root"], r"C:\Users\demo\workspace")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
||||
Reference in New Issue
Block a user