From ac189b83957de99c503dead4cdec1750dc86ebf8 Mon Sep 17 00:00:00 2001 From: "zhiye.sun" Date: Tue, 25 Aug 2026 13:56:50 +0800 Subject: [PATCH] =?UTF-8?q?feat(knowledge):=20=E6=96=B0=E5=A2=9E=E5=88=86?= =?UTF-8?q?=E5=B1=82=E9=A1=B9=E7=9B=AE=E4=BA=A4=E6=8E=A5=20Skill?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- AGENTS.md | 12 +++ README.md | 2 +- migration/MIGRATION_PLAN.md | 3 +- migration/source-lock.json | 5 +- migration/tests/test_local_state.py | 76 +++++++++++++++++++ plugins/git/skills/branch/SKILL.md | 1 + plugins/git/skills/commit-msg/SKILL.md | 4 +- plugins/knowledge/skills/.gitkeep | 1 - plugins/knowledge/skills/handoff/SKILL.md | 58 ++++++++++++++ .../skills/handoff/agents/openai.yaml | 4 + .../skills/handoff/assets/craftkit-gitignore | 3 + .../skills/handoff/assets/craftkit-readme.md | 16 ++++ .../skills/handoff/assets/handoff-template.md | 42 ++++++++++ 13 files changed, 222 insertions(+), 5 deletions(-) create mode 100644 migration/tests/test_local_state.py delete mode 100644 plugins/knowledge/skills/.gitkeep create mode 100644 plugins/knowledge/skills/handoff/SKILL.md create mode 100644 plugins/knowledge/skills/handoff/agents/openai.yaml create mode 100644 plugins/knowledge/skills/handoff/assets/craftkit-gitignore create mode 100644 plugins/knowledge/skills/handoff/assets/craftkit-readme.md create mode 100644 plugins/knowledge/skills/handoff/assets/handoff-template.md diff --git a/AGENTS.md b/AGENTS.md index ce6b670..1c58b02 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -48,6 +48,18 @@ plugins//skills// └─ assets/ # 生成产物需要的素材 ``` +## CraftKit 项目目录 + +- `.craftkit/` 是项目级 Agent 配置、规范、知识和运行状态的统一目录,目录名固定为全小写;不能把整个目录视为本地缓存或整体排除。 +- 可共享内容包括 `project.json`、`agents/`、`standards/`、`knowledge/` 和 `handoff/`,可以根据用户确认正常提交和同步。 +- `agents/` 保存项目对特定 Agent 的补充说明;`standards/` 保存项目开发规范;`knowledge/pitfalls/` 保存经验证且可复用的问题经验;`knowledge/decisions/` 保存重要技术决策。 +- 本地内容统一放入 `local/`,缓存统一放入 `cache/`。`.craftkit/.gitignore` 必须排除 `/local/` 和 `/cache/`,但不得排除整个 `.craftkit/`。 +- 本地交接默认位于 `.craftkit/local/handoff/current.md`;只有用户明确选择共享时才写入 `.craftkit/handoff/current.md`。 +- 只在实际需要时创建目录,不一次生成空的 `agents/`、`standards/`、`knowledge/`、`handoff/`、`local/` 或 `cache/`。 +- Git Skill 默认排除 `.craftkit/local/**` 和 `.craftkit/cache/**`;其他 `.craftkit` 内容按普通项目资产评估,并在提交建议中单独标识为 Agent、规范或知识变更。 +- 如果本地目录已经被 Git 跟踪,或整个 `.craftkit/` 被全局规则、`.git/info/exclude` 或项目规则忽略,应提示冲突并停止自动处理;不得自动修改索引或历史。 +- `.craftkit/` 不得保存凭据、令牌、私钥、个人机器绝对路径或无必要的个人信息。 + ## 迁移与知识产权边界 - 迁移采用“分析能力 → 编写中性规格 → 脱离原文独立实现”的方式,不做目录复制、批量替词或近义改写。 diff --git a/README.md b/README.md index 4980f6a..41d0321 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,7 @@ CraftKit 是一组面向 Codex 插件市场的中性 Skill 工具。项目从通 | `dev` | 软件设计、编码、审查与测试 | 已初始化,暂无 Skill | | `doc` | 文档转换、整理与写作 | 已迁移 `format-md`、`docx-to-md` | | `git` | 分支、提交、变更提取与集成 | 已迁移 `commit-msg`、`branch` | -| `knowledge` | 交接、复盘、经验与工作总结 | 已初始化,暂无 Skill | +| `knowledge` | 交接、复盘、经验与工作总结 | 已迁移 `handoff` | | `skill` | Skill 创建、迁移、检查与同步 | 已初始化,暂无 Skill | ## 目录结构 diff --git a/migration/MIGRATION_PLAN.md b/migration/MIGRATION_PLAN.md index 08768f8..bf033ea 100644 --- a/migration/MIGRATION_PLAN.md +++ b/migration/MIGRATION_PLAN.md @@ -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`。 - [ ] 完成其余特殊样本并总结批量迁移规则。 - [ ] 按插件和风险类型推进同质批量迁移。 diff --git a/migration/source-lock.json b/migration/source-lock.json index b6a1619..7da4018 100644 --- a/migration/source-lock.json +++ b/migration/source-lock.json @@ -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", diff --git a/migration/tests/test_local_state.py b/migration/tests/test_local_state.py new file mode 100644 index 0000000..a6daaa2 --- /dev/null +++ b/migration/tests/test_local_state.py @@ -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() diff --git a/plugins/git/skills/branch/SKILL.md b/plugins/git/skills/branch/SKILL.md index 0dc5e95..cd92cc3 100644 --- a/plugins/git/skills/branch/SKILL.md +++ b/plugins/git/skills/branch/SKILL.md @@ -13,6 +13,7 @@ description: 根据当前仓库约定生成名称,并在用户确认准确命 2. 读取当前仓库适用的 `AGENTS.md`、贡献指南或其他明确的分支约定;没有约定时再参考现有分支命名。 3. 收集分支用途、简短描述和基准引用。不要默认 `main`、`master`、远程名称、版本分支或合并目标。 4. 若工作区不干净,说明现有修改会随切换保留;在用户明确选择继续前不得创建分支,也不得自动暂存、提交、还原或清理。 +5. `.craftkit/local/**` 和 `.craftkit/cache/**` 不视为业务改动;若它们出现在普通状态中,提示检查 `.craftkit/.gitignore`。`.craftkit/agents/**`、`standards/**`、`knowledge/**`、`handoff/**` 和 `project.json` 属于普通项目改动,应与其他未提交内容一起展示。 ## 生成和验证名称 diff --git a/plugins/git/skills/commit-msg/SKILL.md b/plugins/git/skills/commit-msg/SKILL.md index 4e7dc39..791e917 100644 --- a/plugins/git/skills/commit-msg/SKILL.md +++ b/plugins/git/skills/commit-msg/SKILL.md @@ -14,6 +14,8 @@ description: 分析当前 Git 工作区或暂存区的真实变更,生成一 3. 先根据文件名识别敏感路径,例如 `.env`、凭据、令牌、私钥和本地配置。对这些路径只报告风险,不读取或回显差异内容。 4. 对其余相关路径分别读取 staged 或 unstaged diff。差异很大时先看 `--stat`,再按逻辑模块分段检查。 5. 未跟踪文件默认不纳入建议范围;只有用户明确要求评估时,才读取已确认且不敏感的文件。 +6. `.craftkit/local/**` 和 `.craftkit/cache/**` 是本地内容,始终从提交建议、未跟踪文件评估和内容读取中排除。若这些路径已被跟踪,只提示风险,不自动修改索引。 +7. `.craftkit/agents/**`、`standards/**`、`knowledge/**`、`handoff/**` 和 `project.json` 是可共享项目资产,按真实变更正常评估,并与业务代码分组说明其 Agent、规范、知识或交接用途。 ## 形成建议 @@ -22,7 +24,7 @@ description: 分析当前 Git 工作区或暂存区的真实变更,生成一 - 描述应简洁说明本组变更实现的结果,使用用户或仓库约定的语言。 - 互相依赖、共同完成一个目的的文件可归为一组;目的、模块或风险不同的变更应建议拆分。 - staged 与 unstaged 都存在时,明确标注每条建议基于哪一种状态。 -- 不把敏感文件、未确认的未跟踪文件或明显无关的改动列入建议范围。 +- 不把敏感文件、`.craftkit/local/**`、`.craftkit/cache/**`、未确认的未跟踪文件或明显无关的改动列入建议范围。 ## 输出格式 diff --git a/plugins/knowledge/skills/.gitkeep b/plugins/knowledge/skills/.gitkeep deleted file mode 100644 index 8b13789..0000000 --- a/plugins/knowledge/skills/.gitkeep +++ /dev/null @@ -1 +0,0 @@ - diff --git a/plugins/knowledge/skills/handoff/SKILL.md b/plugins/knowledge/skills/handoff/SKILL.md new file mode 100644 index 0000000..19e70fa --- /dev/null +++ b/plugins/knowledge/skills/handoff/SKILL.md @@ -0,0 +1,58 @@ +--- +name: handoff +description: 基于当前任务和项目证据生成可持续更新的本地或共享交接文档,并输出新任务接续提示词。适用于任务暂停、切换会话或交接给他人;普通总结、长期知识库维护或自动提交不应触发本 Skill。 +--- + +# 任务交接 + +把当前任务的真实状态写入 `.craftkit/`,并输出一段可复制到新任务的接续提示词。交接只记录有证据的事实;未知、未测试或未确认的内容必须明确标记。 + +## 选择可见性 + +执行前确认交接范围、下一步目标和可见性: + +- 本地交接是默认选项,写入 `.craftkit/local/handoff/current.md`,不进入 Git。 +- 共享交接只有用户明确选择时使用,写入 `.craftkit/handoff/current.md`,可以作为项目资产提交。 +- 已有目标文件时先读取并更新,不因切换可见性自动移动或复制另一侧文件。 + +## 初始化项目目录 + +首次使用时,只创建 [目录说明模板](assets/craftkit-readme.md) 对应的 `.craftkit/README.md` 和 [排除规则模板](assets/craftkit-gitignore) 对应的 `.craftkit/.gitignore`,以及本次实际需要的交接目录。 + +在 Git 仓库中执行以下检查: + +1. 使用 `git check-ignore --no-index -v .craftkit/README.md` 和 `.craftkit/.gitignore` 检查整个目录是否被项目规则、全局规则或 `.git/info/exclude` 错误排除。发现宽泛排除时停止并说明规则来源,不自动删除用户规则。 +2. 使用 `git ls-files -- .craftkit/local .craftkit/cache` 检查本地目录是否已经被跟踪。存在结果时停止本地写入并提示隐私风险,不自动修改索引。 +3. 初始化或修正 `.craftkit/.gitignore` 前展示内容并取得确认。规则只排除 `/local/` 和 `/cache/`,不得排除父目录。 +4. 初始化后使用 `git check-ignore --no-index -v .craftkit/local/handoff/current.md` 验证本地路径被排除;再检查 `.craftkit/README.md` 未被忽略。 + +非 Git 目录也可以使用相同结构,但应说明没有 Git 机制区分共享与本地内容。 + +## 收集交接证据 + +- 确认本次交接的任务范围、当前状态和下一步目标;下一步不明确时向用户确认,不自行推断。 +- 读取项目内适用的 `AGENTS.md`、`.craftkit/README.md`、相关设计或说明文档,以及本次可见性对应的已有交接文件。 +- 在 Git 仓库中只读检查 `git status --short --branch`、必要的 `git diff --stat`、`git diff --cached --stat` 和与本任务相关的 `git log`。 +- 只把实际执行过的测试和观察到的结果写入“验证”;没有运行的验证写为“未验证”,不以静态检查代替运行结果。 +- 避免记录凭据、令牌、私钥、个人信息和不必要的内部地址。引用项目文件时优先使用相对路径。 + +## 生成和更新文档 + +按 [交接模板](assets/handoff-template.md) 生成文档。目标文件不存在时创建;已存在时先完整读取,再按章节更新: + +- 保留无法确认用途的既有章节和用户内容。 +- 合并重复待办,删除已完成项前必须有当前证据。 +- 被新证据推翻的旧结论应改写并说明依据,不保留互相矛盾的活跃结论。 +- 不整文件覆盖,不自动建立历史归档。只有用户明确要求保留历史时,才在当前可见性对应的 `handoff/history/` 创建带日期的副本。 +- 写入后重新读取关键章节,并运行 `git status --short --ignored`。本地交接必须处于 ignored 状态;共享交接应作为普通项目文件可见。 + +## 接续提示词 + +文档完成后直接输出一段简短提示词,至少包含: + +1. 先读取本次实际交接路径和其中明确引用的项目文件。 +2. 复述任务目标、已完成内容、限制、风险和待办。 +3. 给出下一步计划,并在发生写入或外部操作前遵循项目授权约定。 +4. 内联最多三条最容易重复踩到的风险;其余内容留在交接文档中。 + +最后报告写入路径、可见性和主要更新,不执行 `git add`、`git commit` 或 `git push`。共享交接可由用户后续确认提交;本地交接不得交给其他 Git Skill 提交。 diff --git a/plugins/knowledge/skills/handoff/agents/openai.yaml b/plugins/knowledge/skills/handoff/agents/openai.yaml new file mode 100644 index 0000000..576adce --- /dev/null +++ b/plugins/knowledge/skills/handoff/agents/openai.yaml @@ -0,0 +1,4 @@ +interface: + display_name: "Task Handoff" + short_description: "生成本地任务交接文档和新任务接续提示词" + default_prompt: "使用 $handoff 总结当前任务,先确认交接内容保存在本地还是作为项目共享文件。" diff --git a/plugins/knowledge/skills/handoff/assets/craftkit-gitignore b/plugins/knowledge/skills/handoff/assets/craftkit-gitignore new file mode 100644 index 0000000..5a8d09c --- /dev/null +++ b/plugins/knowledge/skills/handoff/assets/craftkit-gitignore @@ -0,0 +1,3 @@ +# Local CraftKit data +/local/ +/cache/ diff --git a/plugins/knowledge/skills/handoff/assets/craftkit-readme.md b/plugins/knowledge/skills/handoff/assets/craftkit-readme.md new file mode 100644 index 0000000..516c1ef --- /dev/null +++ b/plugins/knowledge/skills/handoff/assets/craftkit-readme.md @@ -0,0 +1,16 @@ +# CraftKit 项目资料 + +本目录保存当前项目供 Agent 使用的配置、开发规范、可复用知识和交接内容。 + +## 目录约定 + +- `project.json`:可共享的项目元数据和默认参数。 +- `agents/`:项目对特定 Agent 的补充指令和示例。 +- `standards/`:项目编码、文档、Git 和测试规范。 +- `knowledge/pitfalls/`:经过验证的可复用问题经验。 +- `knowledge/decisions/`:重要技术决策及其依据。 +- `handoff/`:用户明确选择共享的任务交接。 +- `local/`:仅当前工作副本使用的交接、记忆和运行状态。 +- `cache/`:可重新生成的临时缓存。 + +共享目录可以按项目提交纪律进入 Git;`local/` 和 `cache/` 必须由本目录的 `.gitignore` 排除。不得在本目录保存凭据、令牌、私钥、个人机器绝对路径或无必要的个人信息。 diff --git a/plugins/knowledge/skills/handoff/assets/handoff-template.md b/plugins/knowledge/skills/handoff/assets/handoff-template.md new file mode 100644 index 0000000..1fac796 --- /dev/null +++ b/plugins/knowledge/skills/handoff/assets/handoff-template.md @@ -0,0 +1,42 @@ +# 任务交接 + +## 任务概览 + +- 目标:待确认 +- 当前分支或工作区:待确认 +- 当前状态:待确认 + +## 已完成 + +- 待确认 + +## 关键改动 + +- 待确认 + +## 验证结果 + +- 已验证:待确认 +- 未验证:待确认 + +## 关键结论 + +- 待确认 + +## 风险与限制 + +- 待确认 + +## 待办 + +- 待确认 + +## 下一步任务 + +- 目标:待确认 +- 建议入口:待确认 +- 完成条件:待确认 + +## 接续提示词 + +先读取 `.craftkit/handoff/current.md` 及其中引用的项目文件。复述任务目标、已完成内容、关键限制、风险和待办,然后给出下一步计划;执行写入或外部操作前遵循项目授权约定。