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:
2026-08-25 15:20:02 +08:00
parent ee31278947
commit f3cd56b78e
83 changed files with 1265 additions and 1192 deletions
+20 -20
View File
@@ -9,8 +9,8 @@ import unittest
from pathlib import Path
from unittest.mock import patch
from skiff import catalog
from skiff.catalog import catalog_checkout_path, catalog_repo
from pouch import catalog
from pouch.catalog import catalog_checkout_path, catalog_repo
REPO_ROOT = Path(__file__).resolve().parents[1]
@@ -40,7 +40,7 @@ class CatalogCollectionTests(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"
(self.skills_home / "skills").mkdir(parents=True)
self.upstream = self.home / "upstream"
@@ -79,12 +79,12 @@ class CatalogCollectionTests(unittest.TestCase):
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,
@@ -95,16 +95,16 @@ class CatalogCollectionTests(unittest.TestCase):
def test_catalog_repo_expands_home_relative_local_path(self) -> None:
with patch.dict(os.environ, {"HOME": str(self.home)}):
self.assertEqual(
catalog_repo({"repo": "~/.skills"}),
catalog_repo({"repo": "~/.pouch"}),
str(self.skills_home),
)
self.assertEqual(
catalog_checkout_path("skills", {"repo": "~/.skills"}),
catalog_checkout_path("skills", {"repo": "~/.pouch"}),
self.skills_home.resolve(),
)
def test_add_collection_installs_every_discovered_skill(self) -> None:
result = self.run_skiff("add", "test-pack", "-g", "-a", "codex")
result = self.run_pouch("add", "test-pack", "-g", "-a", "codex")
self.assertEqual(result.returncode, 0, result.stderr)
skill_dir = self.home / ".codex" / "skills"
@@ -115,7 +115,7 @@ class CatalogCollectionTests(unittest.TestCase):
self.assertFalse((skill_dir / "test-pack").exists())
def test_add_qualified_collection_skill_installs_only_that_skill(self) -> None:
result = self.run_skiff("add", "test-pack/second-skill", "-g", "-a", "codex")
result = self.run_pouch("add", "test-pack/second-skill", "-g", "-a", "codex")
self.assertEqual(result.returncode, 0, result.stderr)
skill_dir = self.home / ".codex" / "skills"
@@ -124,7 +124,7 @@ class CatalogCollectionTests(unittest.TestCase):
self.assertTrue((skill_dir / "second-skill" / "SKILL.md").is_file())
def test_add_collection_with_catalog_source_installs_all(self) -> None:
result = self.run_skiff(
result = self.run_pouch(
"add",
"test-pack",
"--source",
@@ -140,7 +140,7 @@ class CatalogCollectionTests(unittest.TestCase):
self.assertTrue((skill_dir / "second-skill").is_symlink())
def test_legacy_registry_source_alias_still_installs(self) -> None:
result = self.run_skiff(
result = self.run_pouch(
"add",
"test-pack",
"--source",
@@ -159,7 +159,7 @@ class CatalogCollectionTests(unittest.TestCase):
project = self.home / "project"
project.mkdir()
added = self.run_skiff(
added = self.run_pouch(
"add",
"test-pack/first-skill",
"--project",
@@ -169,8 +169,8 @@ class CatalogCollectionTests(unittest.TestCase):
)
link = project / ".agents" / "skills" / "first-skill"
link.unlink()
shutil.rmtree(self.home / ".local" / "share" / "skills" / "externals")
synced = self.run_skiff(
shutil.rmtree(self.home / ".local" / "share" / "pouch" / "externals")
synced = self.run_pouch(
"sync",
"--project",
str(project),
@@ -179,7 +179,7 @@ class CatalogCollectionTests(unittest.TestCase):
)
self.assertEqual(added.returncode, 0, added.stderr)
self.assertIn('source: "catalog:test-pack"', project.joinpath(".skills.yaml").read_text())
self.assertIn('source: "catalog:test-pack"', project.joinpath(".pouch.yaml").read_text())
self.assertEqual(synced.returncode, 0, synced.stderr)
self.assertTrue(link.is_symlink())
self.assertTrue((link / "SKILL.md").is_file())
@@ -188,15 +188,15 @@ class CatalogCollectionTests(unittest.TestCase):
blocked = self.home / ".codex" / "skills" / "second-skill"
blocked.mkdir(parents=True)
result = self.run_skiff("add", "test-pack", "-g", "-a", "codex")
result = self.run_pouch("add", "test-pack", "-g", "-a", "codex")
self.assertNotEqual(result.returncode, 0)
self.assertFalse((self.home / ".codex" / "skills" / "first-skill").exists())
self.assertTrue(blocked.is_dir())
def test_remove_collection_removes_all_child_links(self) -> None:
installed = self.run_skiff("add", "test-pack", "-g", "-a", "codex")
removed = self.run_skiff("remove", "test-pack", "-g", "-a", "codex")
installed = self.run_pouch("add", "test-pack", "-g", "-a", "codex")
removed = self.run_pouch("remove", "test-pack", "-g", "-a", "codex")
self.assertEqual(installed.returncode, 0, installed.stderr)
self.assertEqual(removed.returncode, 0, removed.stderr)
@@ -205,8 +205,8 @@ class CatalogCollectionTests(unittest.TestCase):
self.assertFalse((skill_dir / "second-skill").exists())
def test_status_expands_collection_children(self) -> None:
installed = self.run_skiff("add", "test-pack", "-g", "-a", "codex")
status = self.run_skiff("status", "-a", "codex")
installed = self.run_pouch("add", "test-pack", "-g", "-a", "codex")
status = self.run_pouch("status", "-a", "codex")
self.assertEqual(installed.returncode, 0, installed.stderr)
self.assertEqual(status.returncode, 0, status.stderr)