♻️ refactor(skills): rename repo skills source dir
move the repository skills source from `codex/skills` to `skills`. update vendor/install_skills paths, thirdparty sync pipeline, docs, and regression tests, including deployment-route e2e coverage.
This commit is contained in:
parent
f049dfbe10
commit
2c5050de09
|
|
@ -36,7 +36,7 @@ for entry in data["sources"]:
|
|||
PY
|
||||
}
|
||||
|
||||
render_codex_skill() {
|
||||
render_skill() {
|
||||
local snapshot_root="$1"
|
||||
local output_dir="$2"
|
||||
local platform_config_rel="$3"
|
||||
|
|
@ -101,8 +101,8 @@ PY
|
|||
|
||||
tracked_skill_exists() {
|
||||
local name="$1"
|
||||
# conflict only if a first-party SKILL.md exists directly under codex/skills/<name>/
|
||||
[ -f "codex/skills/$name/SKILL.md" ]
|
||||
# conflict only if a first-party SKILL.md exists directly under skills/<name>/
|
||||
[ -f "skills/$name/SKILL.md" ]
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -122,7 +122,7 @@ trap cleanup EXIT
|
|||
|
||||
git checkout -B "$TARGET_BRANCH" "origin/$TARGET_BRANCH"
|
||||
|
||||
mkdir -p "codex/skills/thirdparty/.sources"
|
||||
mkdir -p "skills/thirdparty/.sources"
|
||||
|
||||
sources_file="$tmp_dir/sources.tsv"
|
||||
if ! emit_sources_tsv > "$sources_file"; then
|
||||
|
|
@ -136,7 +136,7 @@ while IFS=$'\x1f' read -r source_id snapshot_dir sync_mode source_list skills_su
|
|||
if [ -f "$source_list" ]; then
|
||||
while IFS= read -r name; do
|
||||
[ -n "$name" ] || continue
|
||||
rm -rf "codex/skills/$name"
|
||||
rm -rf "skills/$name"
|
||||
done < "$source_list"
|
||||
fi
|
||||
done < "$sources_file"
|
||||
|
|
@ -169,13 +169,13 @@ while IFS=$'\x1f' read -r source_id snapshot_dir sync_mode source_list skills_su
|
|||
exit 1
|
||||
fi
|
||||
|
||||
rm -rf "codex/skills/thirdparty/$name"
|
||||
cp -R "$dir" "codex/skills/thirdparty/$name"
|
||||
rm -rf "skills/thirdparty/$name"
|
||||
cp -R "$dir" "skills/thirdparty/$name"
|
||||
names+=("$name")
|
||||
owners["$name"]="$source_id"
|
||||
done
|
||||
;;
|
||||
render_codex_skill)
|
||||
render_skill)
|
||||
name="$output_name"
|
||||
if [ -n "${owners[$name]:-}" ] && [ "${owners[$name]}" != "$source_id" ]; then
|
||||
echo "ERROR: duplicate third-party skill name: $name" >&2
|
||||
|
|
@ -186,7 +186,7 @@ while IFS=$'\x1f' read -r source_id snapshot_dir sync_mode source_list skills_su
|
|||
exit 1
|
||||
fi
|
||||
|
||||
render_codex_skill "$snapshot_root" "codex/skills/thirdparty/$name" "$platform_config" "$template_root" "$data_dir" "$scripts_dir"
|
||||
render_skill "$snapshot_root" "skills/thirdparty/$name" "$platform_config" "$template_root" "$data_dir" "$scripts_dir"
|
||||
names+=("$name")
|
||||
owners["$name"]="$source_id"
|
||||
;;
|
||||
|
|
@ -199,7 +199,7 @@ while IFS=$'\x1f' read -r source_id snapshot_dir sync_mode source_list skills_su
|
|||
printf "%s\n" "${names[@]}" | sort > "$source_list"
|
||||
done < "$sources_file"
|
||||
|
||||
git add codex/skills
|
||||
git add skills
|
||||
|
||||
if git diff --cached --quiet; then
|
||||
echo "No third-party skills to sync."
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
"upstream_ref": "main",
|
||||
"snapshot_dir": "superpowers",
|
||||
"sync_mode": "copy_skill_dirs",
|
||||
"source_list": "codex/skills/thirdparty/.sources/superpowers.list",
|
||||
"source_list": "skills/thirdparty/.sources/superpowers.list",
|
||||
"skills_subdir": "skills",
|
||||
"remove_paths": ["skills/ui-ux-pro-max"]
|
||||
},
|
||||
|
|
@ -15,8 +15,8 @@
|
|||
"upstream_repo": "https://github.com/nextlevelbuilder/ui-ux-pro-max-skill.git",
|
||||
"upstream_ref": "main",
|
||||
"snapshot_dir": "ui-ux-pro-max",
|
||||
"sync_mode": "render_codex_skill",
|
||||
"source_list": "codex/skills/thirdparty/.sources/ui-ux-pro-max.list",
|
||||
"sync_mode": "render_skill",
|
||||
"source_list": "skills/thirdparty/.sources/ui-ux-pro-max.list",
|
||||
"output_name": "ui-ux-pro-max",
|
||||
"platform_config": "src/ui-ux-pro-max/templates/platforms/codex.json",
|
||||
"template_root": "src/ui-ux-pro-max/templates",
|
||||
|
|
@ -29,7 +29,7 @@
|
|||
"upstream_ref": "main",
|
||||
"snapshot_dir": "andrej-karpathy-skills",
|
||||
"sync_mode": "copy_skill_dirs",
|
||||
"source_list": "codex/skills/thirdparty/.sources/andrej-karpathy-skills.list",
|
||||
"source_list": "skills/thirdparty/.sources/andrej-karpathy-skills.list",
|
||||
"skills_subdir": "skills"
|
||||
}
|
||||
]
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
node_modules
|
||||
tmp
|
||||
reports
|
||||
codex/skills/thirdparty
|
||||
skills/thirdparty
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
codex/skills/**
|
||||
skills/**
|
||||
|
|
|
|||
|
|
@ -116,7 +116,7 @@ Layer 1: rulesets/ (≤50 行/语言,模板源)
|
|||
├─ 核心约束与安全红线
|
||||
└─ 指向 Skills 和 docs
|
||||
|
||||
Layer 2: codex/skills/ (按需加载,$skill-name 触发)
|
||||
Layer 2: skills/ (按需加载,$skill-name 触发)
|
||||
├─ commit-message: 提交信息规范
|
||||
├─ style-cleanup: 代码风格整理
|
||||
├─ bulk-refactor-workflow: 批量重构流程
|
||||
|
|
@ -158,7 +158,7 @@ Layer 3: docs/ (权威静态文档)
|
|||
|
||||
## SKILLS(Codex CLI / Claude Code)
|
||||
|
||||
本仓库内置一组 AI agent skills(见 `codex/skills/`),支持 Codex CLI 和 Claude Code,用于按需加载的工作流与知识库。
|
||||
本仓库内置一组 AI agent skills(见 `skills/`),支持 Codex CLI 和 Claude Code,用于按需加载的工作流与知识库。
|
||||
|
||||
TSL 相关问题直接查阅 `rulesets/tsl/index.md` 与 `docs/tsl/`。
|
||||
|
||||
|
|
|
|||
10
SKILLS.md
10
SKILLS.md
|
|
@ -10,7 +10,7 @@
|
|||
| Codex CLI | `~/.agents/skills/` |
|
||||
| Claude Code | `~/.claude/skills/` |
|
||||
|
||||
> 提示:本仓库将 skills 以可分发的形式放在 `codex/skills/`,并提供脚本一键安装到对应平台目录。
|
||||
> 提示:本仓库将 skills 以可分发的形式放在 `skills/`,并提供脚本一键安装到对应平台目录。
|
||||
|
||||
---
|
||||
|
||||
|
|
@ -40,7 +40,7 @@ skills = true
|
|||
本 Playbook 以“可分发、可安装”的方式提供 skills:
|
||||
|
||||
```txt
|
||||
codex/skills/
|
||||
skills/
|
||||
<skill-name>/ # 本仓库自维护
|
||||
SKILL.md
|
||||
references/ # 可选:拆分参考文档
|
||||
|
|
@ -164,7 +164,7 @@ python <deploy_root>/scripts/playbook.py -config playbook.toml
|
|||
|
||||
## 8. 本 Playbook 原生 skills
|
||||
|
||||
位于 `codex/skills/`(Playbook 自维护部分),当前共 3 个。
|
||||
位于 `skills/`(Playbook 自维护部分),当前共 3 个。
|
||||
第三方 skills 来源见第 9 节。
|
||||
|
||||
### 语言特定 Skills
|
||||
|
|
@ -181,7 +181,7 @@ python <deploy_root>/scripts/playbook.py -config playbook.toml
|
|||
|
||||
## 9. Third-party Skills
|
||||
|
||||
来源:`codex/skills/thirdparty/.sources/`(第三方来源清单目录)。
|
||||
来源:`skills/thirdparty/.sources/`(第三方来源清单目录)。
|
||||
|
||||
- `superpowers.list`
|
||||
- `ui-ux-pro-max.list`
|
||||
|
|
@ -190,7 +190,7 @@ python <deploy_root>/scripts/playbook.py -config playbook.toml
|
|||
部署链路:
|
||||
|
||||
- `thirdparty/skill` 分支保存上游快照 `andrej-karpathy-skills/`
|
||||
- 自动同步后,`skills/karpathy-guidelines/` 会落到 `codex/skills/karpathy-guidelines/`
|
||||
- 自动同步后,`karpathy-guidelines/` 会落到仓库内 `skills/thirdparty/karpathy-guidelines/`
|
||||
- 运行 `[install_skills]` 时,再复制到目标平台 skills 目录(`~/.agents/skills/` 或 `~/.claude/skills/`)
|
||||
- 该 skill 本身不依赖 Playbook 文档路径重写,也不需要像 `ui-ux-pro-max` 那样额外渲染
|
||||
|
||||
|
|
|
|||
|
|
@ -477,7 +477,7 @@ def vendor_action(config: dict, context: dict) -> int:
|
|||
copy2(gitattributes_src, dest_prefix / ".gitattributes")
|
||||
|
||||
copytree(PLAYBOOK_ROOT / "scripts", dest_prefix / "scripts")
|
||||
copytree(PLAYBOOK_ROOT / "codex", dest_prefix / "codex")
|
||||
copytree(PLAYBOOK_ROOT / "skills", dest_prefix / "skills")
|
||||
copy2(PLAYBOOK_ROOT / "SKILLS.md", dest_prefix / "SKILLS.md")
|
||||
|
||||
common_docs = PLAYBOOK_ROOT / "docs/common"
|
||||
|
|
@ -1253,7 +1253,7 @@ def install_skills_action(config: dict, context: dict) -> int:
|
|||
if not agents_home.is_absolute():
|
||||
agents_home = (context["project_root"] / agents_home).resolve()
|
||||
|
||||
skills_src_root = PLAYBOOK_ROOT / "codex/skills"
|
||||
skills_src_root = PLAYBOOK_ROOT / "skills"
|
||||
skills_thirdparty_root = skills_src_root / "thirdparty"
|
||||
if not skills_src_root.is_dir():
|
||||
print(f"ERROR: skills source not found: {skills_src_root}", file=sys.stderr)
|
||||
|
|
|
|||
|
Can't render this file because it contains an unexpected character in line 10 and column 56.
|
|
Can't render this file because it contains an unexpected character in line 13 and column 56.
|
|
Can't render this file because it is too large.
|
|
Can't render this file because it contains an unexpected character in line 2 and column 134.
|
|
Can't render this file because it contains an unexpected character in line 2 and column 209.
|
|
Can't render this file because it contains an unexpected character in line 6 and column 94.
|
|
Can't render this file because it contains an unexpected character in line 8 and column 193.
|
|
Can't render this file because it contains an unexpected character in line 4 and column 188.
|
|
|
@ -325,7 +325,7 @@ python scripts/playbook.py -config playbook.toml
|
|||
```text
|
||||
playbook/
|
||||
├── rulesets/ # 语言级硬规则 → 部署到 .agents/
|
||||
├── codex/skills/ # 按需加载的技能(thirdparty/ 为第三方同步)
|
||||
├── skills/ # 按需加载的技能(thirdparty/ 为第三方同步)
|
||||
├── docs/ # 权威静态文档
|
||||
├── templates/ # 本目录:项目架构模板 → 部署到 memory-bank/ 等
|
||||
└── scripts/
|
||||
|
|
|
|||
|
|
@ -397,6 +397,9 @@ skills = ["brainstorming"]
|
|||
manifest_src = ROOT / ".gitea" / "ci" / "thirdparty_skills.json"
|
||||
manifest_dst = repo / ".gitea" / "ci" / "thirdparty_skills.json"
|
||||
manifest_dst.write_text(manifest_src.read_text(encoding="utf-8"), encoding="utf-8")
|
||||
sync_src = ROOT / ".gitea" / "ci" / "sync_thirdparty_skills.sh"
|
||||
sync_dst = repo / ".gitea" / "ci" / "sync_thirdparty_skills.sh"
|
||||
sync_dst.write_text(sync_src.read_text(encoding="utf-8"), encoding="utf-8")
|
||||
|
||||
sync_result = subprocess.run(
|
||||
["bash", ".gitea/ci/sync_thirdparty_skills.sh"],
|
||||
|
|
|
|||
|
|
@ -0,0 +1,185 @@
|
|||
import shutil
|
||||
import subprocess
|
||||
import sys
|
||||
import tempfile
|
||||
import unittest
|
||||
from pathlib import Path
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[1]
|
||||
DEFAULT_DEPLOY_ROOT = Path("docs/standards/playbook")
|
||||
CUSTOM_DEPLOY_ROOT = Path("custom/playbook")
|
||||
REPO_COPY_IGNORE = shutil.ignore_patterns(
|
||||
".git",
|
||||
".venv",
|
||||
"node_modules",
|
||||
"__pycache__",
|
||||
".pytest_cache",
|
||||
".mypy_cache",
|
||||
".ruff_cache",
|
||||
)
|
||||
|
||||
|
||||
def run_script(
|
||||
script: Path, *args: str, cwd: Path | None = None
|
||||
) -> subprocess.CompletedProcess[str]:
|
||||
return subprocess.run(
|
||||
[sys.executable, str(script), *args],
|
||||
capture_output=True,
|
||||
text=True,
|
||||
cwd=cwd,
|
||||
)
|
||||
|
||||
|
||||
def write_config(root: Path, name: str, body: str) -> Path:
|
||||
config_path = root / name
|
||||
config_path.write_text(body.strip() + "\n", encoding="utf-8")
|
||||
return config_path
|
||||
|
||||
|
||||
def copy_repo(target: Path) -> Path:
|
||||
shutil.copytree(ROOT, target, ignore=REPO_COPY_IGNORE)
|
||||
return target
|
||||
|
||||
|
||||
class DeploymentRoutesE2ETests(unittest.TestCase):
|
||||
def assert_core_project_files(self, project_root: Path) -> None:
|
||||
expected = [
|
||||
"AGENTS.md",
|
||||
"AGENT_RULES.md",
|
||||
"AGENT_RULES.local.md",
|
||||
"memory-bank/progress.md",
|
||||
"docs/prompts/system/agent-behavior.md",
|
||||
".agents/index.md",
|
||||
".agents/tsl/index.md",
|
||||
".agents/markdown/index.md",
|
||||
".gitattributes",
|
||||
]
|
||||
for rel in expected:
|
||||
with self.subTest(path=rel):
|
||||
self.assertTrue((project_root / rel).exists(), f"missing: {rel}")
|
||||
|
||||
def assert_docs_prefix(self, project_root: Path, docs_prefix: str) -> None:
|
||||
agents_index = (project_root / ".agents" / "index.md").read_text(encoding="utf-8")
|
||||
self.assertIn("`.agents/tsl/index.md`", agents_index)
|
||||
self.assertIn("`.agents/markdown/index.md`", agents_index)
|
||||
self.assertIn(f"- {docs_prefix}", agents_index)
|
||||
|
||||
tsl_index = (project_root / ".agents" / "tsl" / "index.md").read_text(
|
||||
encoding="utf-8"
|
||||
)
|
||||
self.assertIn(f"`{docs_prefix}/tsl/index.md`", tsl_index)
|
||||
self.assertNotIn("`docs/tsl/index.md`", tsl_index)
|
||||
|
||||
def test_subtree_style_deployment_syncs_project_files(self):
|
||||
with tempfile.TemporaryDirectory() as tmp_dir:
|
||||
tmp_root = Path(tmp_dir)
|
||||
project_root = tmp_root / "project"
|
||||
playbook_root = project_root / DEFAULT_DEPLOY_ROOT
|
||||
project_root.mkdir()
|
||||
copy_repo(playbook_root)
|
||||
|
||||
config_path = write_config(
|
||||
project_root,
|
||||
"playbook.toml",
|
||||
"""
|
||||
[playbook]
|
||||
project_root = "."
|
||||
|
||||
[sync_rules]
|
||||
no_backup = true
|
||||
|
||||
[sync_memory_bank]
|
||||
project_name = "Demo"
|
||||
|
||||
[sync_prompts]
|
||||
no_backup = true
|
||||
|
||||
[sync_standards]
|
||||
langs = ["tsl", "markdown"]
|
||||
no_backup = true
|
||||
""",
|
||||
)
|
||||
|
||||
result = run_script(
|
||||
playbook_root / "scripts" / "playbook.py",
|
||||
"-config",
|
||||
str(config_path),
|
||||
cwd=project_root,
|
||||
)
|
||||
|
||||
self.assertEqual(result.returncode, 0, msg=result.stdout + result.stderr)
|
||||
self.assert_core_project_files(project_root)
|
||||
self.assert_docs_prefix(project_root, "docs/standards/playbook/docs")
|
||||
|
||||
claude_md = project_root / "CLAUDE.md"
|
||||
self.assertTrue(claude_md.is_file())
|
||||
text = claude_md.read_text(encoding="utf-8")
|
||||
self.assertIn("@AGENTS.md", text)
|
||||
self.assertIn("@AGENT_RULES.md", text)
|
||||
self.assertIn("<!-- playbook:claude:start -->", text)
|
||||
|
||||
def test_external_clone_deployment_vendors_snapshot_and_updates_claude(self):
|
||||
with tempfile.TemporaryDirectory() as tmp_dir:
|
||||
tmp_root = Path(tmp_dir)
|
||||
external_clone = tmp_root / "playbook"
|
||||
project_root = tmp_root / "project"
|
||||
copy_repo(external_clone)
|
||||
project_root.mkdir()
|
||||
|
||||
claude_md = project_root / ".claude" / "CLAUDE.md"
|
||||
claude_md.parent.mkdir()
|
||||
claude_md.write_text("# Existing Claude\n\nKeep this.\n", encoding="utf-8")
|
||||
|
||||
config_path = write_config(
|
||||
project_root,
|
||||
"playbook.toml",
|
||||
f"""
|
||||
[playbook]
|
||||
project_root = "."
|
||||
deploy_root = "{CUSTOM_DEPLOY_ROOT.as_posix()}"
|
||||
|
||||
[vendor]
|
||||
langs = ["tsl", "markdown"]
|
||||
|
||||
[sync_rules]
|
||||
no_backup = true
|
||||
|
||||
[sync_memory_bank]
|
||||
project_name = "Demo"
|
||||
|
||||
[sync_prompts]
|
||||
no_backup = true
|
||||
|
||||
[sync_standards]
|
||||
langs = ["tsl", "markdown"]
|
||||
no_backup = true
|
||||
""",
|
||||
)
|
||||
|
||||
result = run_script(
|
||||
external_clone / "scripts" / "playbook.py",
|
||||
"-config",
|
||||
str(config_path),
|
||||
cwd=project_root,
|
||||
)
|
||||
|
||||
self.assertEqual(result.returncode, 0, msg=result.stdout + result.stderr)
|
||||
|
||||
snapshot_root = project_root / CUSTOM_DEPLOY_ROOT
|
||||
self.assertTrue((snapshot_root / "SOURCE.md").is_file())
|
||||
self.assertTrue((snapshot_root / "scripts" / "playbook.py").is_file())
|
||||
self.assertTrue((snapshot_root / "templates" / "README.md").is_file())
|
||||
|
||||
self.assert_core_project_files(project_root)
|
||||
self.assert_docs_prefix(project_root, "custom/playbook/docs")
|
||||
|
||||
text = claude_md.read_text(encoding="utf-8")
|
||||
self.assertIn("Keep this.", text)
|
||||
self.assertIn("@../AGENTS.md", text)
|
||||
self.assertIn("@../AGENT_RULES.md", text)
|
||||
self.assertEqual(text.count("<!-- playbook:claude:start -->"), 1)
|
||||
self.assertFalse((project_root / "CLAUDE.md").exists())
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
|
@ -14,9 +14,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 / "codex" / "skills" / "thirdparty" / ".sources" / "superpowers.list"
|
||||
UI_UX_PRO_MAX_LIST = ROOT / "codex" / "skills" / "thirdparty" / ".sources" / "ui-ux-pro-max.list"
|
||||
UI_UX_PRO_MAX_DIR = ROOT / "codex" / "skills" / "thirdparty" / "ui-ux-pro-max"
|
||||
SUPERPOWERS_LIST = ROOT / "skills" / "thirdparty" / ".sources" / "superpowers.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"
|
||||
|
||||
|
||||
def load_manifest() -> dict:
|
||||
|
|
@ -58,13 +58,13 @@ class ThirdpartySkillsPipelineTests(unittest.TestCase):
|
|||
self.assertEqual(karpathy["snapshot_dir"], "andrej-karpathy-skills")
|
||||
self.assertEqual(karpathy["skills_subdir"], "skills")
|
||||
self.assertEqual(
|
||||
karpathy["source_list"], "codex/skills/thirdparty/.sources/andrej-karpathy-skills.list"
|
||||
karpathy["source_list"], "skills/thirdparty/.sources/andrej-karpathy-skills.list"
|
||||
)
|
||||
|
||||
def test_ui_ux_pro_max_uses_render_codex_skill_sync_mode(self):
|
||||
def test_ui_ux_pro_max_uses_render_skill_sync_mode(self):
|
||||
data = load_manifest()
|
||||
ui_skill = next(item for item in data["sources"] if item["id"] == "ui-ux-pro-max")
|
||||
self.assertEqual(ui_skill["sync_mode"], "render_codex_skill")
|
||||
self.assertEqual(ui_skill["sync_mode"], "render_skill")
|
||||
self.assertEqual(ui_skill["snapshot_dir"], "ui-ux-pro-max")
|
||||
|
||||
def test_superpowers_manifest_prunes_non_superpowers_paths(self):
|
||||
|
|
@ -105,7 +105,7 @@ class ThirdpartySkillsPipelineTests(unittest.TestCase):
|
|||
def test_skills_doc_points_to_generic_thirdparty_sources(self):
|
||||
text = SKILLS_MD.read_text(encoding="utf-8")
|
||||
self.assertIn("## 9. Third-party Skills", text)
|
||||
self.assertIn("来源:`codex/skills/thirdparty/.sources/`(第三方来源清单目录)。", text)
|
||||
self.assertIn("来源:`skills/thirdparty/.sources/`(第三方来源清单目录)。", text)
|
||||
self.assertNotIn("Third-party Skills (superpowers)", text)
|
||||
|
||||
def test_superpowers_and_ui_ux_pro_max_source_lists_exist(self):
|
||||
|
|
@ -160,6 +160,7 @@ class ThirdpartySkillsPipelineTests(unittest.TestCase):
|
|||
self.assertEqual(set_remote.returncode, 0, msg=set_remote.stderr)
|
||||
|
||||
shutil.copy2(MANIFEST, work / ".gitea" / "ci" / "thirdparty_skills.json")
|
||||
shutil.copy2(SYNC_SCRIPT, work / ".gitea" / "ci" / "sync_thirdparty_skills.sh")
|
||||
|
||||
sync_result = run_command("bash", ".gitea/ci/sync_thirdparty_skills.sh", cwd=work)
|
||||
self.assertEqual(
|
||||
|
|
@ -169,10 +170,10 @@ class ThirdpartySkillsPipelineTests(unittest.TestCase):
|
|||
)
|
||||
|
||||
generated_list = (
|
||||
work / "codex" / "skills" / "thirdparty" / ".sources" / "andrej-karpathy-skills.list"
|
||||
work / "skills" / "thirdparty" / ".sources" / "andrej-karpathy-skills.list"
|
||||
)
|
||||
generated_skill = (
|
||||
work / "codex" / "skills" / "thirdparty" / "karpathy-guidelines" / "SKILL.md"
|
||||
work / "skills" / "thirdparty" / "karpathy-guidelines" / "SKILL.md"
|
||||
)
|
||||
self.assertTrue(generated_list.is_file())
|
||||
self.assertTrue(generated_skill.is_file())
|
||||
|
|
|
|||
|
|
@ -7,7 +7,8 @@ README = ROOT / "README.md"
|
|||
PLAYBOOK_EXAMPLE = ROOT / "playbook.toml.example"
|
||||
SKILLS_DOC = ROOT / "SKILLS.md"
|
||||
TEMPLATES_CI_README = ROOT / "templates" / "ci" / "README.md"
|
||||
REMOVED_TSL_GUIDE = ROOT / "codex" / "skills" / "tsl-guide"
|
||||
TEMPLATES_README = ROOT / "templates" / "README.md"
|
||||
REMOVED_TSL_GUIDE = ROOT / "skills" / "tsl-guide"
|
||||
|
||||
class TslEntrypointsConsistencyTests(unittest.TestCase):
|
||||
def test_ruleset_lists_canonical_tsl_layers(self):
|
||||
|
|
@ -44,6 +45,19 @@ class TslEntrypointsConsistencyTests(unittest.TestCase):
|
|||
self.assertNotIn("vendoring", SKILLS_DOC.read_text(encoding="utf-8"))
|
||||
self.assertNotIn("vendoring", TEMPLATES_CI_README.read_text(encoding="utf-8"))
|
||||
|
||||
def test_repo_docs_use_platform_neutral_skills_source_dir(self):
|
||||
readme_text = README.read_text(encoding="utf-8")
|
||||
skills_text = SKILLS_DOC.read_text(encoding="utf-8")
|
||||
templates_text = TEMPLATES_README.read_text(encoding="utf-8")
|
||||
|
||||
self.assertIn("`skills/`", readme_text)
|
||||
self.assertIn("`skills/`", skills_text)
|
||||
self.assertIn("├── skills/", templates_text)
|
||||
|
||||
self.assertNotIn("`codex/skills/`", readme_text)
|
||||
self.assertNotIn("`codex/skills/`", skills_text)
|
||||
self.assertNotIn("├── codex/skills/", templates_text)
|
||||
|
||||
def test_repo_no_longer_ships_tsl_guide_skill(self):
|
||||
self.assertFalse(REMOVED_TSL_GUIDE.exists())
|
||||
self.assertNotIn("tsl-guide", README.read_text(encoding="utf-8"))
|
||||
|
|
|
|||
|
|
@ -40,6 +40,8 @@ langs = ["tsl"]
|
|||
self.assertTrue((snapshot / "templates/README.md").is_file())
|
||||
self.assertTrue((snapshot / "templates/memory-bank").is_dir())
|
||||
self.assertTrue((snapshot / "templates/prompts").is_dir())
|
||||
self.assertTrue((snapshot / "skills").is_dir())
|
||||
self.assertFalse((snapshot / "codex").exists())
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
|
|
|||
Loading…
Reference in New Issue