关于 kk-bootstrap
kk-bootstrap 是一项受监督的技能,用于从现有 Markdown 文档中提取可复用的项目知识,并写入 nodes/ 下的节点文件。它引导 LLM 完成文档发现、抽样、起草和用户审核。
主要功能
- 01发现 Markdown 文档
- 02抽样阅读并跟进交叉引用
- 03起草实践与映射节点
- 04写入节点并记录来源
- 05刷新知识索引
适用场景
- 01从项目文档初始化知识库
- 02提取项目规范与组件映射
- 03审核候选知识节点后再接受
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ e0ipso/ kenkeep --skill kk-bootstrap安装后在 Claude Code 中输入/kk-bootstrap确认已加载。
详细介绍
kk-bootstrap
你将基于项目现有文档,对项目知识库进行一次性引导初始化。用户在正常会话中调用了此技能,因此他们正在关注进展;如果你偏离方向,他们可以随时纠正你。
你的任务
浏览项目现有的 Markdown 文档,提取候选知识节点,并将其作为新的节点文件直接写入 nodes/。用户会逐个审核你写入的文件:保留文件即表示接受,删除文件即表示拒绝。你需要根据判断进行探索、抽样和追踪交叉引用,而非穷尽所有内容。这是一次由用户监督的单轮操作;你就是负责提取内容的大模型——没有子 Agent,也没有执行器。
输入
- 用户可以提供一个可选路径参数。若提供,则将其视为文档范围的根目录;若未提供,则默认为仓库根目录(
finddocs原语已通过.gitignore、.kkignore和静态跳过列表筛除非知识类内容,详见步骤 1)。
配置
开始前,读取 .ai/kenkeep/config.yaml(若不存在,则读取 ~/.config/kenkeep/config.yaml),查看用户偏好(标签词汇表、范围提示等),并应用相关设置。
解析项目根目录
使用随附的检测器解析仓库根目录(即包含 .ai/kenkeep 的目录),然后将输出的路径作为以下所有命令的工作目录:
KK_REPO_ROOT=$(node .ai/kenkeep/scripts/kk-detect-root.mjs) || exit $?
cd "$KK_REPO_ROOT" || exit $?
pwd
步骤
1. 查找候选文档
调用 finddocs 原语并包含哈希,以便与之前的引导初始化状态进行去重:
npx --yes kenkeep@latest finddocs --from <scope> --with-hashes
<scope> 是用户提供的路径参数(例如 docs);若要从仓库根目录扫描,则省略 --from。输出每个文件占一行:
+ <relpath>\t<sha256>
该原语已应用 .gitignore、.kkignore 和静态跳过列表(例如 LICENSE、CHANGELOG、CODE_OF_CONDUCT、CONTRIBUTORS、ENTRY.md、GRAPH.md、releases/**/*.md 等文件名);你不会看到这些文件。
统计行数,并在深入阅读任何内容之前,先向用户简要汇报,例如:“CLI 列出了 30 个 Markdown 文件,涵盖 docs/、三个模块 README 和两个顶层概览。我会优先阅读概览,然后抽样查看模块。”根据判断识别入口文档、可能已过时的文档,并根据确定性列表安排抽样顺序,但不要重新生成列表。
如果列表超过约 100 个 Markdown 文件,停止并询问用户。这类情况可能需要用户明确指定范围。
2. 跳过状态文件中已有记录的文档
读取 .ai/kenkeep/.state/bootstrap-state.json(首次运行时该文件可能不存在;此时按空状态处理)。对于每一行 + <relpath>\t<sha>,检查 docs[<relpath>].content_sha256 === <sha> 是否成立。若成立,则该文件在之前的运行中已按此内容哈希处理过;跳过该文件。否则,该文件是新增或已变更,应加入当前工作集。
3. 优先阅读入口文档
完整阅读顶层入口文档(README.md、ARCHITECTURE.md、CONTRIBUTING.md、顶层文档导航页)。它们通常会介绍项目词汇、主要组件名称,以及你需要识别的规范用语。
4. 抽样并追踪交叉引用
不要从头到尾阅读每个文件。抽样阅读有代表性的内容,并追踪文档之间的链接。如果顶层 README 提到“认证设计请参阅 docs/architecture/auth.md”,那就是值得优先追踪的线索。
对于大型参考文档(例如逐个方法列出的 API 清单),浏览章节标题,只阅读说明性文字部分,跳过自动生成的表格。
5. 判断哪些内容值得成为节点
对于每条看起来像项目知识的内容,判断它属于哪种类型:
Practice 候选项——指令式项目指导:
- 约定(“始终使用 X 来处理 Y”)。
- 禁止事项(“不要做 X”)。
- 注意事项(警告、“小心……”)。
- 原因(“我们选择 X 是因为 Y”)。
- 工具/工作流(“使用 X 运行测试”)。
文档中的触发信号:祈使动词(“使用”“执行”“避免”“始终”“绝不”“必须”);原因标记(“因为”“由于”“为避免”);提醒区块(> Note:、> Warning:);明确的“应该做/不应该做”章节。
Map 候选项——说明有哪些内容:
- 命名的功能、模块、服务及其用途。
- 项目特有的词汇。
- 主要系统在文件树中的位置。
文档中的触发信号:命名组件的章节标题(“## Rivermark Cards Module”);定义模式(“X 是我们用于 Y 的服务”);明确的文件路径引用(modules/custom/x/)。
可选的变更相关条款(须有依据)。 如果源文档说明了修改该实体时需要留意的内容——例如要运行的检查、要保持的不变量或限制编辑的相关规则——你可以在 map 正文末尾加上一句简短的“修改此项时,请验证……”。仅当文档提供依据时才添加;不得为了套用模板而臆造注意事项。如果文档未提及编辑该实体的相关内容,则省略此条款。
如果某条内容兼具两种属性(例如“使用 rm_analytics.dispatcher,这是我们用于跟踪事件的服务”),请将其拆分:practice 记录“使用该 dispatcher”;map 记录“该 dispatcher 是什么”。
跳过(仅针对内容判断;文件名模式的跳过规则已由 finddocs 处理):
- 自动生成的 API 参考(方法表、参数清单)。
- 其他有用文档中的模板化段落(标准许可声明、通用 CI 徽章)。
- 非项目特有的一般编程知识(Drupal/React/Django 基础知识)。
- 空泛的 TODO 和“我们最终应该……”之类的内容。
- 共享的知识准入标准排除的所有内容——维护/生命周期操作、项目故事或历史(尤其是计划/工单/议题引用),以及伪装成约定的偶发单一事实——以及六个月保留测试。对每个候选项应用
.ai/kenkeep/.config/prompts/knowledge-admission.md;此处不要重复其内容。
6. 起草每个节点正文,然后通过 node write 持久化
每个候选节点的草稿应包含:一种类型(practice | map)、一个根据标题生成的简短 slug(小写、连字符分隔、ASCII)、1–5 个简短的小写标签、一个祈使式或名词性标题(≤80 个字符)、一个摘要(≤140 个字符),以及由 1–4 个简短段落构成的正文。
置信度校准。 对引导内容,默认使用 confidence: medium。现有文档可能已过时或仍属设想内容;审核者需要在接受前检查每个文件。只有当文档明确说明规则并给出理由,且文档看起来仍在积极维护时,才使用 confidence: high。如果规则是隐含的、文档标记为草稿/已弃用/旧版,或内容含糊不清,则使用 confidence: low。
选择起草路径(探测 + 回退)
开始起草前,生成一个运行 ID 并准备每批次的日志目录——这两个路径都会用到:
RUN_ID=$(uuidgen 2>/dev/null || date -u +"bootstrap-%Y%m%dT%H%M%SZ")
mkdir -p .ai/kenkeep/_logs/bootstrap
LOG_DIR="$(pwd)/.ai/kenkeep/_logs/bootstrap"
探测可用工具面,并依据共享附录 .ai/kenkeep/.config/prompts/sub-agent-delegation.md 选择并行或内联路径(探测定义、每轮最多 5 个并发任务及波次规则、绝对草稿路径,以及已发放/已验证/无效的产物格式)。下面的引导专属细节说明每个单元要起草什么,以及收集器如何持久化这些内容。
并行路径 — 编排器 + 子 Agent 调度 + 收集器
并行处理的单位是一个候选文档(<batchN> 从 1 开始编号)。对于当前批次中的每个文档(每个编排器轮次最多 5 个):
-
计算其绝对草稿路径
${LOG_DIR}/${RUN_ID}__<batchN>.draft.json,并在委派之前,将issued行追加到${LOG_DIR}/${RUN_ID}__<batchN>.jsonl:printf '{"ts":"%s","event":"issued","runId":"%s","batchN":%d,"doc":"%s","hash":"%s"}\n' \ "$(date -u +%Y-%m-%dT%H:%M:%SZ)" "$RUN_ID" <batchN> "<relpath>" "<sha256>" \ >> "${LOG_DIR}/${RUN_ID}__<batchN>.jsonl" -
向子 Agent 委派该文档的起草工作,并提供聚焦的指示:
你正在为 ONE 个源文档起草 kenkeep 节点候选项。
- 完整阅读相对路径
<relpath>下的文档(内容 sha256<sha256>)。 - 判断该文档是否值得创建 0 个、1 个或多个节点。使用父技能 Step 5 中的相同实践/映射规则。
- 对于每个选定的节点,只生成以下键:
{kind, slug, title, summary, tags[], confidence, body}。不要包含id或 YAML frontmatter — 它们由宿主写入。 - 将数组作为 JSON 写入绝对路径
<DRAFT_PATH>,除此之外不要写入任何内容。0 个节点也是有效结果;此时写入[]。 - 成功后,仅返回绝对草稿路径。
- 完整阅读相对路径
收集器轮次 — 当前批次中的所有已调度 Agent 均已返回后,针对每个批次的草稿文件:
- 读取并解析为 JSON。预期结构是由对象组成的数组,对象包含键
kind、slug、title、summary、tags(数组)、confidence(high|medium|low)和body。 - 如果解析出错或结构不匹配,追加一行
event:"invalid",向用户显示 "batch produced invalid output, skipped",然后继续 — 不要中止运行。 - 对于每份通过验证的草稿,通过
node write持久化(见下文),并传入其源文档的--source-doc和--source-hash。该原语会锁定其bootstrap-state.json更新,因此连续调用是安全的。 - 追加一行
event:"validated",其中包含写入数量和解析出的 ID。只有在当前批次的收集器轮次结束后,才能启动下一批次。
内联回退路径
如果探测结果表明不存在调度原语,则在本会话中内联起草每个候选项的节点正文 — 使用相同的词汇表(kind、slug、title、summary、tags、confidence、body),并在起草后立即通过 node write 持久化每个节点。仍需写入每批次的 JSONL 日志(每个文档一个批次):起草前追加 event:"issued" 行,node write 返回后追加 event:"validated" 行,确保两条路径生成的产物结构相同。
通过 node write 持久化
两条路径都将每份保留下来的草稿交给同一个持久化原语,通过 stdin 传入正文,并在同一次调用中合并更新每个文件的哈希映射:
npx --yes kenkeep@latest node write <kind> <slug> \
--title "<title>" --summary "<summary>" \
--tags "<tag1,tag2,...>" \
--confidence <high|medium|low> \
--source-doc "<relpath>" --source-hash "<sha256>" <<'EOF'
<body markdown>
EOF
必须同时提供 --source-doc 和 --source-hash(若只提供其中一个,该原语会报错)。同时提供二者时,同一次调用会原子地更新 bootstrap-state.json,因此重新运行步骤 2 时会跳过此文件。--source-doc 是你在 finddocs 输出中看到的相对路径;--source-hash 是同一行中的 SHA-256。
成功时,该原语会打印解析出的节点 ID 并以 0 退出。请捕获该 ID。如果 slug 与现有节点冲突,该原语会自动追加后缀(-2、-3、…),因此打印出的 ID 可能与 <slug> 不同。如果退出码非 0,请向用户显示 stderr,并继续处理下一个候选项;不要盲目重试。
绝不要覆盖现有节点。 node write 不会覆盖 — ensureUniqueId 始终会生成新的 ID。如果候选项的范围与现有节点确实相同,请跳过,并在最终报告中说明,而不是让它以 -2 同级节点的形式写入。
多源节点。 如果候选项来自多个文档(你在两个地方都发现了相同的约定),请选择最权威的文档作为 --source-doc / --source-hash 对,并在正文中提及其他来源(例如:"Also documented in docs/auth.md.")。不要写入重复节点。
7. 刷新 ENTRY.md 和 GRAPH.md
完成所有写入后,重建索引,使审核者看到的索引与新节点保持同步:
npx --yes kenkeep@latest index rebuild
8. 汇报结果
完成后,向用户总结:
- 你阅读了多少篇文档;跳过了哪些文档以及原因。
- 你写入了多少个实践节点。
- 你写入了多少个地图节点。
- 你跳过了哪些与现有节点重叠的候选内容;用户可能希望手动合并内容。
- 你注意到了哪些交叉引用但没有继续跟进(用户可能希望引导你查看这些内容)。
- 有哪些文档看起来已经过时或存在矛盾,用户应当进行复核。
- 确认已刷新
ENTRY.md和GRAPH.md。
然后请用户检查写入的文件:保留文件即表示接受,删除文件(rm nodes/<folder>/<file>.md)即表示拒绝。
约束
- 绝不覆盖
nodes/中已有的节点。 Bootstrap 应采取保守策略:如果候选内容的范围确实已由现有节点涵盖,就跳过并报告。不要让ensureUniqueId用-2后缀掩盖重叠。 - Bootstrap 期间绝不自动解决你认为存在的矛盾。 如果发现两篇文档存在分歧,只将其中一篇写为节点,并在最终报告中指出冲突,供用户决定。不要写入第二个矛盾节点。
- 不要臆造理由。 只包含源文档中实际存在的“因为……”内容。如果文档只说“使用 X”,节点就写“使用 X”,不要编造“因为 [理由]”。请引用或贴近原文改写。
- 不要尝试读取代码文件。 只阅读 Markdown 文档。Bootstrap 的目的是提取已有文档中的内容。
- 实践/地图边界不可逾越。 实践候选内容不能变成地图节点,反之亦然。将混合内容拆分为两个节点。
- 将发现、哈希、slug 冲突处理和状态管理交由
finddocs和node write负责。 不要自行重新实现这些功能。
何时停止
出现以下情况时,停止并询问用户:
finddocs列出的 Markdown 文件超过约 100 篇(可能需要限定范围)。- 遇到明显存在争议或与特定版本相关,且无法判断哪个版本是当前版本的文档。
- 发现自己提取的内容过多(节点数量增长过快,用户难以逐一审核)。
- 用户很久没有纠正你,而你的信心正在下降。
Bootstrap 需要有人监督。如有不确定之处,请交由人工判断。