feat: rename skills/skiff to pouch and move ACK state under .pouch
Use ~/.pouch, the pouch CLI, and .pouch.yaml as the SSOT container. Keep the inner skills/ packages, and store ACK project state in .pouch/ack instead of docs/ack.
This commit is contained in:
@@ -9,7 +9,7 @@ import unittest
|
||||
from pathlib import Path
|
||||
from unittest.mock import patch
|
||||
|
||||
from skiff import cli
|
||||
from pouch import cli
|
||||
|
||||
|
||||
REPO_ROOT = Path(__file__).resolve().parents[1]
|
||||
@@ -19,7 +19,7 @@ class CreateWorkflowTests(unittest.TestCase):
|
||||
def setUp(self) -> None:
|
||||
self.temp_dir = tempfile.TemporaryDirectory()
|
||||
self.home = Path(self.temp_dir.name)
|
||||
self.skills_home = self.home / ".skills"
|
||||
self.skills_home = self.home / ".pouch"
|
||||
template = self.skills_home / "skills" / "_template"
|
||||
template.mkdir(parents=True)
|
||||
template.joinpath("SKILL.md").write_text(
|
||||
@@ -35,28 +35,28 @@ class CreateWorkflowTests(unittest.TestCase):
|
||||
"给出一条可以直接交给 Agent 的示例请求。\n",
|
||||
encoding="utf-8",
|
||||
)
|
||||
project_skill = self.skills_home / "skills" / "skiff"
|
||||
project_skill = self.skills_home / "skills" / "pouch"
|
||||
project_skill.mkdir()
|
||||
project_skill.joinpath("SKILL.md").write_text(
|
||||
"---\nname: skiff\ndescription: >-\n"
|
||||
"---\nname: pouch\ndescription: >-\n"
|
||||
" 创建和维护自研 skill。用于创建、安装、反馈或更新 skill 时。\n"
|
||||
"---\n\n# skiff\n\n## 步骤\n\n1. 维护 skill。\n",
|
||||
"---\n\n# pouch\n\n## 步骤\n\n1. 维护 skill。\n",
|
||||
encoding="utf-8",
|
||||
)
|
||||
project_skill.joinpath("README.md").write_text(
|
||||
"# skiff\n\n供人类使用的 skiff 说明。\n",
|
||||
"# pouch\n\n供人类使用的 pouch 说明。\n",
|
||||
encoding="utf-8",
|
||||
)
|
||||
|
||||
def tearDown(self) -> None:
|
||||
self.temp_dir.cleanup()
|
||||
|
||||
def run_skiff(self, *args: str) -> subprocess.CompletedProcess[str]:
|
||||
def run_pouch(self, *args: str) -> subprocess.CompletedProcess[str]:
|
||||
env = os.environ.copy()
|
||||
env["HOME"] = str(self.home)
|
||||
env["PYTHONPATH"] = str(REPO_ROOT)
|
||||
return subprocess.run(
|
||||
[sys.executable, "-m", "skiff", *args],
|
||||
[sys.executable, "-m", "pouch", *args],
|
||||
cwd=REPO_ROOT,
|
||||
env=env,
|
||||
text=True,
|
||||
@@ -65,25 +65,25 @@ class CreateWorkflowTests(unittest.TestCase):
|
||||
)
|
||||
|
||||
def test_setup_command_is_not_exposed(self) -> None:
|
||||
help_result = self.run_skiff("--help")
|
||||
setup_result = self.run_skiff("setup", str(self.skills_home))
|
||||
help_result = self.run_pouch("--help")
|
||||
setup_result = self.run_pouch("setup", str(self.skills_home))
|
||||
|
||||
self.assertEqual(help_result.returncode, 0, help_result.stderr)
|
||||
self.assertNotIn("setup", help_result.stdout)
|
||||
self.assertNotEqual(setup_result.returncode, 0)
|
||||
|
||||
def test_bootstrap_installs_project_skill_globally_for_all_agents(self) -> None:
|
||||
first = self.run_skiff("bootstrap")
|
||||
second = self.run_skiff("bootstrap")
|
||||
first = self.run_pouch("bootstrap")
|
||||
second = self.run_pouch("bootstrap")
|
||||
|
||||
self.assertEqual(first.returncode, 0, first.stderr)
|
||||
self.assertEqual(second.returncode, 0, second.stderr)
|
||||
expected = (self.skills_home / "skills" / "skiff").resolve()
|
||||
expected = (self.skills_home / "skills" / "pouch").resolve()
|
||||
for relative in (
|
||||
".cursor/skills/skiff",
|
||||
".claude/skills/skiff",
|
||||
".codex/skills/skiff",
|
||||
".agents/skills/skiff",
|
||||
".cursor/skills/pouch",
|
||||
".claude/skills/pouch",
|
||||
".codex/skills/pouch",
|
||||
".agents/skills/pouch",
|
||||
):
|
||||
link = self.home / relative
|
||||
self.assertTrue(link.is_symlink(), relative)
|
||||
@@ -93,8 +93,8 @@ class CreateWorkflowTests(unittest.TestCase):
|
||||
|
||||
def test_update_pulls_skills_home(self) -> None:
|
||||
with (
|
||||
patch.object(cli, "SKILLS_HOME", self.skills_home),
|
||||
patch.object(cli, "ensure_skills_home"),
|
||||
patch.object(cli, "POUCH_HOME", self.skills_home),
|
||||
patch.object(cli, "ensure_pouch_home"),
|
||||
patch.object(cli.subprocess, "run") as run,
|
||||
):
|
||||
cli.cmd_update(argparse.Namespace())
|
||||
@@ -108,7 +108,7 @@ class CreateWorkflowTests(unittest.TestCase):
|
||||
project = self.home / "project"
|
||||
project.mkdir()
|
||||
|
||||
result = self.run_skiff(
|
||||
result = self.run_pouch(
|
||||
"create",
|
||||
"migration-review",
|
||||
"--idea",
|
||||
@@ -128,19 +128,19 @@ class CreateWorkflowTests(unittest.TestCase):
|
||||
self.assertIn("idea: 检查数据库迁移", brief)
|
||||
self.assertIn(f"source_project: {project.resolve()}", brief)
|
||||
self.assertFalse((self.skills_home / "skills" / "migration-review").exists())
|
||||
self.assertIn("请完善 skiff 草稿 migration-review", result.stdout)
|
||||
self.assertIn("请完善 pouch 草稿 migration-review", result.stdout)
|
||||
|
||||
def test_check_rejects_template_placeholders(self) -> None:
|
||||
created = self.run_skiff("create", "migration-review", "--idea", "检查数据库迁移")
|
||||
created = self.run_pouch("create", "migration-review", "--idea", "检查数据库迁移")
|
||||
self.assertEqual(created.returncode, 0, created.stderr)
|
||||
|
||||
result = self.run_skiff("check", "migration-review")
|
||||
result = self.run_pouch("check", "migration-review")
|
||||
|
||||
self.assertNotEqual(result.returncode, 0)
|
||||
self.assertIn("模板占位", result.stderr)
|
||||
|
||||
def test_finalize_moves_valid_draft_and_removes_brief(self) -> None:
|
||||
created = self.run_skiff("create", "migration-review", "--idea", "检查数据库迁移")
|
||||
created = self.run_pouch("create", "migration-review", "--idea", "检查数据库迁移")
|
||||
self.assertEqual(created.returncode, 0, created.stderr)
|
||||
draft = self.skills_home / ".drafts" / "migration-review"
|
||||
draft.joinpath("SKILL.md").write_text(
|
||||
@@ -156,7 +156,7 @@ class CreateWorkflowTests(unittest.TestCase):
|
||||
encoding="utf-8",
|
||||
)
|
||||
|
||||
result = self.run_skiff("finalize", "migration-review")
|
||||
result = self.run_pouch("finalize", "migration-review")
|
||||
|
||||
self.assertEqual(result.returncode, 0, result.stderr)
|
||||
final = self.skills_home / "skills" / "migration-review"
|
||||
@@ -179,7 +179,7 @@ class CreateWorkflowTests(unittest.TestCase):
|
||||
encoding="utf-8",
|
||||
)
|
||||
|
||||
result = self.run_skiff("check", "reference-check")
|
||||
result = self.run_pouch("check", "reference-check")
|
||||
|
||||
self.assertNotEqual(result.returncode, 0)
|
||||
self.assertIn("引用文件不存在", result.stderr)
|
||||
@@ -194,19 +194,19 @@ class CreateWorkflowTests(unittest.TestCase):
|
||||
encoding="utf-8",
|
||||
)
|
||||
|
||||
result = self.run_skiff("check", "missing-readme")
|
||||
result = self.run_pouch("check", "missing-readme")
|
||||
|
||||
self.assertNotEqual(result.returncode, 0)
|
||||
self.assertIn("缺少 README.md", result.stderr)
|
||||
|
||||
def test_finalize_does_not_overwrite_existing_owned_skill(self) -> None:
|
||||
created = self.run_skiff("create", "collision-check", "--idea", "检查名称冲突")
|
||||
created = self.run_pouch("create", "collision-check", "--idea", "检查名称冲突")
|
||||
self.assertEqual(created.returncode, 0, created.stderr)
|
||||
final = self.skills_home / "skills" / "collision-check"
|
||||
final.mkdir()
|
||||
final.joinpath("marker").write_text("keep", encoding="utf-8")
|
||||
|
||||
result = self.run_skiff("finalize", "collision-check")
|
||||
result = self.run_pouch("finalize", "collision-check")
|
||||
|
||||
self.assertNotEqual(result.returncode, 0)
|
||||
self.assertEqual(final.joinpath("marker").read_text(encoding="utf-8"), "keep")
|
||||
|
||||
Reference in New Issue
Block a user