关于 kk-migrate
kk-migrate 是用于跨越已注册模式版本迁移 Kenkeep 知识库的交互式技能。需要整理内容时由 LLM 在当前会话中判断,文件变更则交给确定性的命令行原语,最终留待人工审查。
主要功能
- 01检测待执行的模式迁移
- 02将扁平知识库条目归入主题文件夹
- 03保留节点 ID 和关系
- 04通过确定性的命令行原语修改文件
- 05重建索引并交付未提交的差异
适用场景
- 01将扁平知识库整理成主题文件夹
- 02将主题树转换为 v3 OKF 格式
- 03提交前审查迁移变更
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ e0ipso/ kenkeep --skill kk-migrate安装后在 Claude Code 中输入/kk-migrate确认已加载。
详细介绍
kk-migrate
你是迁移执行者,负责任何待处理的知识库迁移,而非某个特定版本跃迁。知识库会将其磁盘布局记录在编号的 schema_version 中,每个已注册的迁移步骤都会将目录树从一个版本升级到下一个版本。无论某个步骤需要作出何种判断,都由你在本次会话中完成:没有子 Agent、没有运行器,也不会通过 -p 启动子进程——你就是负责判断的大模型。所有文件写入都委托给该步骤的确定性 CLI 基元,以确保 ID 和字节由经过测试的代码保留,而非由你来保留。
确定项目根目录
使用随附的检测器解析仓库根目录(包含 .ai/kenkeep 的目录),然后将其输出的路径作为以下所有命令的工作目录:
KK_REPO_ROOT=$(node .ai/kenkeep/scripts/kk-detect-root.mjs) || exit $?
cd "$KK_REPO_ROOT" || exit $?
pwd
分派
首先,让 CLI 查询有哪些待处理的迁移:
npx --yes kenkeep@latest migrate status
-
如果它输出类似
Knowledge base is already at schema_version 3; nothing to do.(或No knowledge base found under nodes/; nothing to do.)的一行,则无需迁移。停止并将该行报告给用户。不要做其他操作。 -
否则,stdout 将严格输出一行 JSON,即待处理步骤的有序链:
{"current":2,"target":3,"steps":[{"id":"okf-v3","from":2,"to":3,"primitives":["migrate okf-v3"]}]}current是检测到的磁盘上架构版本,target是此 CLI 随附的版本,steps是衔接这两个版本所需的全部步骤,按执行顺序排列。每个条目都包含步骤的稳定id、该步骤衔接的from/to版本,以及它驱动的确定性 CLIprimitives。
对于每个 steps[] 条目,按顺序查找下方标题中包含完全匹配的 id 的操作流程章节,并执行该章节。如果本文档中没有与某个步骤的 id 匹配的章节,停止并报告给用户:此技能副本早于已注册的步骤;CLI 识别出此技能副本尚无法执行的迁移,因此必须先升级技能(重新运行 init --upgrade)再进行迁移。绝不要为未知的步骤 ID 临时编造操作流程。
flat-to-tree(1 -> 2)
将 v1 知识库(叶节点存放在扁平的 nodes/practice/ 和 nodes/map/ 布局中)迁移到 v2 嵌套的主题文件夹树中。唯一需要判断的是如何将扁平叶节点归类到主题文件夹;所有写入操作都通过 place apply 基元完成。
1. 获取清单
运行确定性清单基元并捕获 stdout:
npx --yes kenkeep@latest place inventory
分派阶段已确认需要执行此步骤,因此预期恰好输出一行 JSON。(如果该基元提前结束或拒绝执行——说明目录树在分派后发生了变化——请停止并将其输出报告给用户。)
{"leaves":[{"id":"<id>","title":"...","kind":"practice|map","tags":["..."],"summary":"...","relates_to":["..."],"sourcePath":"..."}, ...]}
这是你的输入。该基元已为你读取并验证 frontmatter——对这份 JSON 进行归类;不要自行打开或解析叶节点文件。
2. 在当前会话中为叶节点分组
将清单中的叶节点归入少量主题文件夹。请遵循以下规则:
- 主题文件夹,数量精简。 将相关叶节点归入少量主题文件夹。文件夹名称使用小写字母并以连字符分隔,可使用
/嵌套(例如cli、knowledge-base/index)。不要为每个叶节点单独创建文件夹;要进行归类。 - 让相互引用的节点彼此靠近。 通过
relates_to相互引用的叶节点通常应放在相近的位置。 - 完整保留每个 id。 清单中的每个叶节点必须且只能有一个存放位置,并且必须放在其确切的
id下——绝不可编造、重命名、丢弃或合并 id。id 是节点的身份标识;文件夹仅用于展示。 - 为创建的每个文件夹编写一条
summary。 为你使用的每个不同文件夹编写一行summary:使用名词短语或不完整句,能够接在「for more information on <summary>」之后(以小写字母开头,不以句号结尾,长度不超过约 140 个字符)。先说明文件夹中包含的内容,再附上简短的; read when <task pattern>子句,说明哪些任务应触发深入查看——Agent 会通过将任务与这些摘要匹配来决定查看路径,因此触发条件有助于确保准确路由。
组装存放位置与文件夹文档。格式必须与 place apply 解析的格式完全一致:
{
"placements": [{ "id": "<leaf-id>", "targetFolder": "<folder>" }],
"folders": [{ "folder": "<folder>", "summary": "<fragment>" }]
}
为清单中的每个叶节点指定一个存放位置,并为你使用的每个不同 targetFolder 添加一项 folders 条目。(如果要将叶节点保留在 nodes/ 根目录下,请将 "targetFolder": "",空根目录无需添加 folders 条目。)
**应用前,先向用户展示拟定的分组供其审阅:**展示文件夹树、每个文件夹包含的 id,以及各文件夹编写的摘要。这是一次性且影响重大的整个知识库重组操作——在进行任何写入前,让用户决定是否调整。
3. 确定性地应用存放位置
将文档写入临时文件,并交给确定性应用原语处理:
PLACE_PLAN=$(mktemp -t kk-place-plan.XXXXXX.json)
# Write your {"placements":[...],"folders":[...]} document to $PLACE_PLAN.
npx --yes kenkeep@latest place apply --input "$PLACE_PLAN"
该原语会在进行任何写入前,验证每个 id 是否与磁盘上的叶节点相符,以及每条编写的文件夹摘要是否对应由存放位置创建的文件夹——随后按原样迁移每个叶节点,保留其 id 和字节内容(仅更新 schema_version),并将每条文件夹摘要写入文件夹摘要旁置文件。若计划有误(包含未知或遗漏的 id,或摘要对应的文件夹中没有放置任何叶节点),操作将中止并给出明确提示,且不会进行任何文件系统更改;请修正文档后重新运行。不要自行迁移文件或写入摘要。
成功时,会输出一行 JSON,即存放位置摘要:
{"placed":[{"id":"<id>","targetFolder":"<folder>"}, ...]}
4. 重建索引
根据迁移后的目录树重新生成 ENTRY.md、GRAPH.md 和每个文件夹的 index.md:
npx --yes kenkeep@latest index rebuild
重建操作会保留你在第 3 步写入的文件夹摘要。未编写摘要的文件夹会显示标题式大小写的文件夹名称作为回退值;index rebuild 会发出警告并以状态码 0 退出(只警告,不会阻止操作)。
5. 交接
告知用户迁移已暂存于工作树中,且未运行任何 git 命令。用户可通过以下方式审阅结果:
git diff
移入主题文件夹的叶节点会显示为重命名(id 和字节内容保持不变);每个新建文件夹的摘要都会记录在 .ai/kenkeep/FOLDER_SUMMARIES.md 中;ENTRY.md / GRAPH.md 已刷新。用户可用 git commit 接受迁移,用 git restore(指定路径或整个工作树)拒绝迁移。不要自行暂存、提交或还原任何内容。
okf-v3(2 -> 3)
将 v2 主题目录树迁移为 v3 OKF 原生节点格式。此步骤完全确定性:不进行分组,也不需要 LLM 判断。你的职责是调用原语、检查其摘要,并将生成的差异交给用户审阅。
1. 运行确定性重写
运行 dispatch 报告的原语:
npx --yes kenkeep@latest migrate okf-v3
除非检测到的磁盘版本恰好为 2,否则它会拒绝执行。成功后,它会以机械方式:
- 将叶节点 frontmatter 中的
kind重命名为type,将summary重命名为description; - 将 kenkeep 所有的字段移至
kk_扩展键(kk_schema_version、kk_id、kk_relates_to、kk_depends_on、kk_derived_from、kk_confidence); - 根据 v3 frontmatter 中的事实生成
Related和# Citations正文部分; - 将旧版
nodes/**/index.mdfrontmatter 中的文件夹摘要迁移至.ai/kenkeep/FOLDER_SUMMARIES.md; - 重建
nodes/**/index.md、ENTRY.md和GRAPH.md。
它会输出一行 JSON:
{"converted":2,"folder_summaries":1,"collisions":[]}
如果 collisions 非空,请明确指出:这些叶节点在追加生成的部分之前,已经有未标记的 # Related 或 # Citations 标题。不要尝试自行合并这些标题;由用户检查正文差异。
2. 验证并交接
运行常规确定性检查:
npx --yes kenkeep@latest lint --verbose
npx --yes kenkeep@latest doctor --verbose
然后报告:v3 OKF 迁移已暂存在工作树中,且未运行任何 git 命令。告知用户检查:
git diff
叶节点会原地重写,文件夹摘要现存放在 .ai/kenkeep/FOLDER_SUMMARIES.md,普通的 nodes/**/index.md 文件是 OKF 保留文件,且 ENTRY.md / GRAPH.md 已刷新。用户可用 git commit 接受变更,用 git restore 拒绝变更。不要替用户暂存、提交或还原任何内容。
约束
- 仅在宿主环境内操作。 判断工作在本会话中进行。没有子 Agent,也不使用
-p派生进程;不要派生子 Agent。 - 绝不直接写入节点文件。 每次文件变更都必须通过某一步的确定性原语完成——在 flat-to-tree 中,每次叶节点迁移和每次文件夹摘要写入都必须通过
place apply完成。你只负责编写原语所使用的 JSON 文档。 - 绝不调用 git。 不运行
add、commit或restore。迁移结果应作为未提交差异留给人工接受或拒绝。 - ID 和边不可更改。 每个叶节点必须保留其确切 ID 和所有边;如果计划会丢弃、重命名或遗漏任何 ID 或边,原语的验证会在写入前中止。
- 完整迁移需要本交互会话。 不支持无头或无人值守迁移;判断步骤需要你,也就是会话中的 Agent。