feat(knowledge): 新增分层项目交接 Skill

This commit is contained in:
zhiye.sun
2026-08-25 13:56:50 +08:00
parent 27de7f3000
commit ac189b8395
13 changed files with 222 additions and 5 deletions
+2 -1
View File
@@ -57,7 +57,7 @@
2. `doc/docx-to-md`:多来源合并、脚本、依赖和生成物样本,已完成。
3. `git/commit-msg`:只读 Git 状态分析样本,已完成。
4. `git/branch`:修改仓库状态和二次授权边界样本,已完成。
5. `knowledge/handoff`:模板化文档与项目上下文样本。
5. `knowledge/handoff`:模板化文档与项目上下文样本,已完成。
6. `skill/guidance`:大型参考资料、索引和渐进式加载样本。
7. `skill/migrate`:脚本、检查、同步和状态追踪组成的复合工作流样本。
@@ -228,5 +228,6 @@ plan-change
- [x] 迁移并验证脚本型特殊样本 `doc/docx-to-md`。
- [x] 迁移并验证只读 Git 特殊样本 `git/commit-msg`。
- [x] 迁移并验证有副作用 Git 特殊样本 `git/branch`。
- [x] 迁移并验证模板化交接特殊样本 `knowledge/handoff`。
- [ ] 完成其余特殊样本并总结批量迁移规则。
- [ ] 按插件和风险类型推进同质批量迁移。
+4 -1
View File
@@ -280,7 +280,10 @@
"source-b:f58c6cd52bc983e8": {
"sourcePathHash": "f58c6cd52bc983e87d265308ade0da8d89bd74d5d4f1e96fc463ef299a9fe94a",
"sourceSha256": "98392eb0fe65dab6877495e6863a6722cd2777f5767dfd95b3a829ed7798a5e7",
"status": "pending"
"status": "migrated",
"target": "plugins/knowledge/skills/handoff",
"targetVersion": "0.1.0",
"reviewedAt": "2026-08-25"
},
"source-b:258ee10299925494": {
"sourcePathHash": "258ee1029992549420c8465c8de2d63c1bfaf9334b812d6b79a07a9823b49733",
+76
View File
@@ -0,0 +1,76 @@
import subprocess
import tempfile
import unittest
from pathlib import Path
class LocalStateTest(unittest.TestCase):
"""验证 `.craftkit/` 能同时承载共享资料和本地状态。"""
def run_git(self, root: Path, *args: str) -> subprocess.CompletedProcess[str]:
"""在隔离仓库执行 Git,并保留输出供断言使用。"""
return subprocess.run(
["git", "-C", str(root), *args],
check=False,
capture_output=True,
text=True,
encoding="utf-8",
)
def test_nested_gitignore_separates_shared_and_local_content(self) -> None:
"""共享资料应可提交,本地目录和缓存应由嵌套规则排除。"""
with tempfile.TemporaryDirectory() as temp:
root = Path(temp)
initialized = self.run_git(root, "init")
self.assertEqual(initialized.returncode, 0, initialized.stderr)
craftkit = root / ".craftkit"
craftkit.mkdir()
(craftkit / ".gitignore").write_text(
"# Local CraftKit data\n/local/\n/cache/\n",
encoding="utf-8",
)
(craftkit / "README.md").write_text("# 项目资料\n", encoding="utf-8")
shared = craftkit / "standards" / "coding" / "rules.md"
shared.parent.mkdir(parents=True)
shared.write_text("# 编码规范\n", encoding="utf-8")
local = craftkit / "local" / "handoff" / "current.md"
local.parent.mkdir(parents=True)
local.write_text("# 本地交接\n", encoding="utf-8")
cache = craftkit / "cache" / "result.json"
cache.parent.mkdir(parents=True)
cache.write_text("{}\n", encoding="utf-8")
ignored = self.run_git(
root,
"check-ignore",
"--no-index",
"-v",
".craftkit/local/handoff/current.md",
)
self.assertEqual(ignored.returncode, 0, ignored.stderr)
self.assertIn(".craftkit/.gitignore", ignored.stdout.replace("\\", "/"))
cache_ignored = self.run_git(
root,
"check-ignore",
"--no-index",
".craftkit/cache/result.json",
)
self.assertEqual(cache_ignored.returncode, 0, cache_ignored.stderr)
status = self.run_git(root, "status", "--short", "--untracked-files=all")
self.assertEqual(status.returncode, 0, status.stderr)
normalized = status.stdout.replace("\\", "/")
self.assertIn(".craftkit/.gitignore", normalized)
self.assertIn(".craftkit/README.md", normalized)
self.assertIn(".craftkit/standards/coding/rules.md", normalized)
self.assertNotIn(".craftkit/local", normalized)
self.assertNotIn(".craftkit/cache", normalized)
self.assertFalse((root / ".gitignore").exists())
if __name__ == "__main__":
unittest.main()