✨ feat(workflow): adopt Matt Pocock ticket workflow
Replace the Superpowers plan pipeline with grill-with-docs, specs, local tickets, and ticket-native execution. BREAKING CHANGE: Remove the legacy Plan CLI, prompt templates, and Superpowers skills.
This commit is contained in:
@@ -16,7 +16,9 @@ LEGACY_WORKFLOW = ROOT / ".gitea" / "workflows" / "update-thirdparty-superpowers
|
||||
UPDATE_SCRIPT = ROOT / ".gitea" / "ci" / "update_thirdparty_skills.sh"
|
||||
SYNC_SCRIPT = ROOT / ".gitea" / "ci" / "sync_thirdparty_skills.sh"
|
||||
SKILLS_MD = ROOT / "SKILLS.md"
|
||||
SUPERPOWERS_LIST = ROOT / "skills" / "thirdparty" / ".sources" / "superpowers.list"
|
||||
MATT_POCOCK_LIST = (
|
||||
ROOT / "skills" / "thirdparty" / ".sources" / "matt-pocock-skills.list"
|
||||
)
|
||||
UI_UX_PRO_MAX_LIST = ROOT / "skills" / "thirdparty" / ".sources" / "ui-ux-pro-max.list"
|
||||
UI_UX_PRO_MAX_DIR = ROOT / "skills" / "thirdparty" / "ui-ux-pro-max"
|
||||
BROOKS_LINT_LIST = ROOT / "skills" / "thirdparty" / ".sources" / "brooks-lint.list"
|
||||
@@ -62,7 +64,7 @@ class ThirdpartySkillsPipelineTests(unittest.TestCase):
|
||||
self.assertEqual(
|
||||
[entry["id"] for entry in data["sources"]],
|
||||
[
|
||||
"superpowers",
|
||||
"matt-pocock-skills",
|
||||
"ui-ux-pro-max",
|
||||
"andrej-karpathy-skills",
|
||||
"brooks-lint",
|
||||
@@ -72,6 +74,62 @@ class ThirdpartySkillsPipelineTests(unittest.TestCase):
|
||||
],
|
||||
)
|
||||
|
||||
def test_matt_pocock_manifest_syncs_stable_skill_groups(self):
|
||||
data = load_manifest()
|
||||
matt = next(
|
||||
item for item in data["sources"] if item["id"] == "matt-pocock-skills"
|
||||
)
|
||||
|
||||
self.assertEqual(
|
||||
matt["upstream_repo"], "https://github.com/mattpocock/skills.git"
|
||||
)
|
||||
self.assertEqual(matt["snapshot_dir"], "matt-pocock-skills")
|
||||
self.assertEqual(matt["sync_mode"], "copy_skill_dirs")
|
||||
self.assertEqual(
|
||||
matt["skills_subdirs"],
|
||||
["skills/engineering", "skills/productivity", "skills/misc"],
|
||||
)
|
||||
self.assertIn("grill-with-docs", matt["include_skill_dirs"])
|
||||
self.assertIn("grilling", matt["include_skill_dirs"])
|
||||
self.assertIn("to-tickets", matt["include_skill_dirs"])
|
||||
|
||||
def test_matt_pocock_source_and_required_workflow_skills_are_materialized(self):
|
||||
self.assertTrue(MATT_POCOCK_LIST.is_file())
|
||||
|
||||
synced = set(MATT_POCOCK_LIST.read_text(encoding="utf-8").splitlines())
|
||||
manifest_skills = set(
|
||||
next(
|
||||
item
|
||||
for item in load_manifest()["sources"]
|
||||
if item["id"] == "matt-pocock-skills"
|
||||
)["include_skill_dirs"]
|
||||
)
|
||||
required = {
|
||||
"setup-matt-pocock-skills",
|
||||
"grill-with-docs",
|
||||
"grilling",
|
||||
"domain-modeling",
|
||||
"to-spec",
|
||||
"to-tickets",
|
||||
"implement",
|
||||
"tdd",
|
||||
"codebase-design",
|
||||
"code-review",
|
||||
"handoff",
|
||||
}
|
||||
|
||||
self.assertEqual(synced, manifest_skills)
|
||||
self.assertTrue(required <= synced)
|
||||
legacy_main_chain = {
|
||||
"using-superpowers",
|
||||
"brainstorming",
|
||||
"writing-plans",
|
||||
"executing-plans",
|
||||
}
|
||||
self.assertTrue(legacy_main_chain.isdisjoint(synced))
|
||||
for name in required:
|
||||
self.assertTrue((ROOT / "skills" / "thirdparty" / name / "SKILL.md").is_file())
|
||||
|
||||
def test_karpathy_manifest_uses_copy_skill_dirs_sync_mode(self):
|
||||
data = load_manifest()
|
||||
karpathy = next(
|
||||
@@ -144,11 +202,6 @@ class ThirdpartySkillsPipelineTests(unittest.TestCase):
|
||||
)
|
||||
self.assertEqual(craft["include_skill_dirs"], ["uncle-bob-craft"])
|
||||
|
||||
def test_superpowers_manifest_prunes_non_superpowers_paths(self):
|
||||
data = load_manifest()
|
||||
superpowers = next(item for item in data["sources"] if item["id"] == "superpowers")
|
||||
self.assertEqual(superpowers["remove_paths"], ["skills/ui-ux-pro-max"])
|
||||
|
||||
def test_workflow_inlines_update_and_sync_in_single_serial_job(self):
|
||||
text = WORKFLOW.read_text(encoding="utf-8")
|
||||
self.assertFalse(LEGACY_WORKFLOW.exists())
|
||||
@@ -201,14 +254,41 @@ class ThirdpartySkillsPipelineTests(unittest.TestCase):
|
||||
self.assertIn("skills/thirdparty/", text)
|
||||
self.assertNotIn("Third-party Skills (superpowers)", text)
|
||||
|
||||
def test_superpowers_and_ui_ux_pro_max_source_lists_exist(self):
|
||||
self.assertTrue(SUPERPOWERS_LIST.is_file())
|
||||
def test_non_legacy_thirdparty_source_lists_exist(self):
|
||||
self.assertTrue(UI_UX_PRO_MAX_LIST.is_file())
|
||||
self.assertTrue(CODEBASE_RECON_LIST.is_file())
|
||||
self.assertIn("using-superpowers", SUPERPOWERS_LIST.read_text(encoding="utf-8"))
|
||||
self.assertIn("ui-ux-pro-max", UI_UX_PRO_MAX_LIST.read_text(encoding="utf-8"))
|
||||
self.assertIn("pathfinding", CODEBASE_RECON_LIST.read_text(encoding="utf-8"))
|
||||
|
||||
def test_superpowers_source_and_vendored_skills_are_absent(self):
|
||||
data = load_manifest()
|
||||
self.assertNotIn("superpowers", {item["id"] for item in data["sources"]})
|
||||
source_list = (
|
||||
ROOT / "skills" / "thirdparty" / ".sources" / "superpowers.list"
|
||||
)
|
||||
self.assertFalse(source_list.exists())
|
||||
legacy_skill_dirs = {
|
||||
"brainstorming",
|
||||
"dispatching-parallel-agents",
|
||||
"executing-plans",
|
||||
"finishing-a-development-branch",
|
||||
"receiving-code-review",
|
||||
"requesting-code-review",
|
||||
"subagent-driven-development",
|
||||
"systematic-debugging",
|
||||
"test-driven-development",
|
||||
"using-git-worktrees",
|
||||
"using-superpowers",
|
||||
"verification-before-completion",
|
||||
"writing-plans",
|
||||
"writing-skills",
|
||||
}
|
||||
thirdparty_root = ROOT / "skills" / "thirdparty"
|
||||
self.assertEqual(
|
||||
{name for name in legacy_skill_dirs if (thirdparty_root / name).exists()},
|
||||
set(),
|
||||
)
|
||||
|
||||
def test_codebase_recon_pathfinding_dependency_is_synced(self):
|
||||
self.assertTrue((PATHFINDING_DIR / "SKILL.md").is_file())
|
||||
self.assertTrue(
|
||||
@@ -251,7 +331,15 @@ class ThirdpartySkillsPipelineTests(unittest.TestCase):
|
||||
mirror = tmp_root / "origin.git"
|
||||
work = tmp_root / "work"
|
||||
|
||||
clone_mirror = run_command("git", "clone", "--mirror", str(ROOT), str(mirror))
|
||||
clone_mirror = run_command(
|
||||
"git",
|
||||
"-c",
|
||||
f"safe.directory={(ROOT / '.git').as_posix()}",
|
||||
"clone",
|
||||
"--mirror",
|
||||
str(ROOT),
|
||||
str(mirror),
|
||||
)
|
||||
self.assertEqual(clone_mirror.returncode, 0, msg=clone_mirror.stderr)
|
||||
|
||||
main_ref = run_command(
|
||||
|
||||
Reference in New Issue
Block a user