kk-bootstrap について
kk-bootstrapは、既存のMarkdown文書から再利用可能なプロジェクト知識を抽出し、nodes/配下のノードファイルにまとめる、監督付きスキルです。LLMによる文書の発見、サンプリング、下書き、ユーザーレビューを導きます。
主な機能
- 01Markdown文書の検出
- 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/ の直下に新しいノードファイルとして書き込みます。ユーザーは書き込まれた各ファイルを確認し、そのまま残せば承認、削除すれば却下となります。判断しながら調査し、内容を抜き出して、相互参照をたどります。網羅的に行うのではなく、監督下での一度限りの作業です。抽出を行うのはLLMであるあなたであり、サブエージェントもランナーもありません。
入力
- ユーザーから任意のパス引数が渡される場合があります。渡された場合は、そのパスをドキュメント範囲のルートとして扱います。指定がない場合は、リポジトリのルートをデフォルトとします(
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 を省略してリポジトリのルートからスキャンします。出力は1ファイルにつき1行です。
+ <relpath>\t<sha256>
このプリミティブでは、.gitignore、.kkignore、静的スキップリスト(LICENSE、CHANGELOG、CODE_OF_CONDUCT、CONTRIBUTORS、ENTRY.md、GRAPH.md、releases/**/*.md などのファイル名)がすでに適用されています。これらは表示されません。
行数を数え、内容を詳しく読む前に、ユーザーに簡潔に報告してください。例:「CLI は docs/ 内の Markdown ファイルを30件、3つのモジュールの README、トップレベルの概要ドキュメントを2件表示しています。まず概要ドキュメントを優先し、その後にモジュールをサンプルします。」判断に基づいて、決定的な順序で並んだリストから入口、古くなっている可能性のあるドキュメント、サンプルを調べる順序を見極めます。ただし、リストを作り直してはいけません。
Markdown ファイルが約100件を超える場合は、作業を止めてユーザーに確認してください。続行するには範囲を明示する必要がある可能性があります。
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 の候補 — 命令形のプロジェクトガイダンス:
- 規約(「Y には常に X を使う」)。
- 禁止事項(「X をしてはいけない」)。
- 注意点(警告、「…には注意する」)。
- 理由(「Y のため、X を選んだ」)。
- ツール/ワークフロー(「テストは X で実行する」)。
ドキュメント内での手がかり:命令形の動詞(「使う」「する」「避ける」「常に」「決して」「必須」など)、理由を示す語句(「なぜなら」「〜なので」「〜を避けるため」など)、注意喚起ブロック(> Note:, > Warning:)、明示的な「すべきこと/してはいけないこと」のセクション。
Map の候補 — 何が存在するか:
- 名前の付いた機能、モジュール、サービスとその役割。
- このプロジェクト固有の用語。
- 主要システムのファイルツリー上の場所。
ドキュメント内での手がかり:コンポーネント名を示すセクション見出し(「## Rivermark Cards Module」など)、定義パターン(「X は Y のためのサービスです」)、明示的なファイルパスへの言及(「modules/custom/x/」など)。
任意の変更関連の文節(根拠がある場合に限る)。 元のドキュメントに、対象のエンティティを変更する際に確認すべきこと(実行するチェック、維持すべき不変条件、編集を制約する関連ルール)が記載されている場合、短い「変更時は、…を確認します」という文を 1 つ、Map の本文の末尾に加えてもかまいません。ドキュメントに根拠がある場合に限って追加し、テンプレートを埋めるために注意事項を作り上げてはいけません。エンティティの編集に関する記載がない場合は、この文節を省略します。
コンテンツに両方の側面がある場合(例:「イベントを追跡するサービスである rm_analytics.dispatcher を使う」)、分割します。dispatcher を使うことは Practice に、その役割は Map に記述します。
スキップするもの(コンテンツの判断のみ。ファイル名パターンによるスキップは finddocs ですでに処理済みです):
- 自動生成された API リファレンス(メソッド一覧、パラメーターの羅列)。
- ほかの点では有用なドキュメントに含まれる定型的な段落(標準的なライセンスの前文、一般的な CI バッジなど)。
- プロジェクト固有ではない一般的なプログラミング知識(Drupal/React/Django の基礎など)。
- まだ実現していないことに関する TODO や「いつか実現すべき」という内容。
- 共通の 知識採用基準で除外されるすべての内容 — 保守/ライフサイクルに関する作業、プロジェクトの経緯や歴史(特に計画/チケット/課題への言及)、規約を装った偶発的で一度きりの事実を含みます — および「6 か月後も残すか」という基準に該当するもの。.ai/kenkeep/.config/prompts/knowledge-admission.md をすべての候補に適用します。この基準をここで再述してはいけません。
6. 各ノードの本文を作成してから、node write で保存する
各候補について、作成するノードには、種類(practice | map)、タイトルから作った短いスラッグ(小文字、ハイフン区切り、ASCII)、1~5 個の短い小文字タグ、命令形または名詞句のタイトル(80 文字以内)、要約(140 文字以内)、1~4 個の短い段落からなる本文が必要です。
確信度の調整。 初期登録コンテンツの confidence: medium を既定値とします。既存のドキュメントは古くなっていたり、実現予定の内容だったりする可能性があります。レビュー担当者は、採用前に各ファイルを評価する必要があります。ドキュメントで理由とともにルールが明示され、そのドキュメントが継続的に保守されているように見える場合に限り、confidence: high を使用します。ルールが暗黙的である、ドキュメントに draft/deprecated/legacy のマークがある、または内容が曖昧な場合は、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(プローブの定義、1 ターンあたり最大 5 件という並列数の上限とウェーブルール、絶対パスでのドラフト作成、発行済み/検証済み/無効な成果物の形式)に従って、並列方式かインライン方式かを選びます。以下のブートストラップ固有の詳細では、各ユニットが作成する内容と、収集担当者がそれを保存する方法を説明します。
並列処理の経路 — オーケストレーター+サブエージェントへの振り分け+コレクター
並列処理の単位は、1つの候補ドキュメント(1から番号を付けた<batchN>)です。現在のウェーブに含まれる各ドキュメント(オーケストレーターの1ターンにつき最大5件)について、次の手順を実行します。
-
絶対パス
${LOG_DIR}/${RUN_ID}__<batchN>.draft.jsonを計算し、委任する前に${LOG_DIR}/${RUN_ID}__<batchN>.jsonlへissued行を追記します。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" -
この1件のドキュメントの草案作成を、以下の具体的な指示とともにサブエージェントに委任します。
1つのソースドキュメントについて、kenkeepのノード候補を作成してください。
- 相対パス
<relpath>(コンテンツのsha256は<sha256>)にあるドキュメントを、すべて読んでください。 - ノードが0個、1個、または複数必要かを判断してください。親スキルのステップ5と同じプラクティス/マップのルールを使用してください。
- 選んだ各ノードについて、次のキーだけを正確に出力してください:
{kind, slug, title, summary, tags[], confidence, body}。idやYAMLフロントマターは含めないでください。どちらもホストが付与します。 - 配列をJSONとして(それ以外は何も付けずに)絶対パス
<DRAFT_PATH>へ書き込んでください。ノードが0個でも有効な結果です。その場合は[]を書き込んでください。 - 成功したら、絶対パスだけを返してください。
- 相対パス
コレクターのターン — ウェーブ内のすべてのエージェントから応答が返った後、各バッチの草案ファイルについて次の手順を実行します。
- JSONとして読み取り、解析します。想定される形式は、
kind、slug、title、summary、tags(配列)、confidence(high|medium|low)、bodyの各キーを持つオブジェクトの配列です。 - 解析エラーまたは形式の不一致が発生した場合は、
event:"invalid"行を追記し、**「batch produced invalid output, skipped」**をユーザーに伝えてから続行します。実行を中止してはいけません。 - 検証済みの草案はそれぞれ、元のドキュメントの
--source-docと--source-hashを指定してnode write(下記参照)で保存します。このプリミティブはbootstrap-state.jsonの更新をロックするため、連続して呼び出しても安全です。 - 書き込んだ件数と解決済みIDを記した
event:"validated"行を追記します。現在のウェーブのコレクターのターンが完了してから、次のウェーブを実行してください。
インラインの代替経路
プローブでディスパッチ用プリミティブが存在しないと判明した場合は、このセッション内で各候補のノード本文をインラインで作成します。語彙は同じです(kind、slug、title、summary、tags、confidence、body)。作成後、各ノードをすぐにnode writeで保存します。バッチごとのJSONLログ(ドキュメントごとに1バッチ)も引き続き記録します。成果物の形式をどちらの経路でも同じにするため、草案作成前にevent:"issued"行を追記し、node writeの完了後にevent:"validated"行を追記します。
node writeで保存する
どちらの経路でも、残った草案はすべて同じ保存プリミティブに渡します。本文を標準入力から渡し、ファイルごとのハッシュマップ更新も同じ呼び出しにまとめます。
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で終了します。その値を取得してください。スラッグが既存のノードと重複する場合、プリミティブは自動的に接尾辞(-2、-3、…)を付加するため、出力されたIDは<slug>と異なる場合があります。終了コードが0以外の場合は、stderrをユーザーに伝え、次の候補へ進んでください。むやみに再試行してはいけません。
既存のノードを上書きしてはいけません。 node writeは上書きしません。ensureUniqueIdは常に新しいIDを生成します。候補が既存のノードと実質的に同じスコープの場合は、-2の兄弟ノードとして作成せず、スキップして、最終報告でその旨を伝えてください。
複数ソースのノード。 候補が複数のドキュメントを情報源とする場合(同じ規約が2か所で説明されている場合など)は、最も権威のあるドキュメントを--source-doc/--source-hashの組み合わせに選び、他の情報源については本文中で言及してください(例:「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/内の既存ノードを上書きしてはいけません。 ブートストラップでは慎重に判断します。候補の内容が既存のノードで実質的にカバーされている場合は、スキップして報告してください。重複を覆い隠すためにensureUniqueIdで-2の接尾辞を付けてはいけません。- ブートストラップ中に、認識した矛盾を自動で解決してはいけません。 2つのドキュメントの内容が食い違っていることに気づいた場合は、片方だけをノードとして書き、最終報告でその矛盾を示して、ユーザーが判断できるようにしてください。矛盾する2つ目のノードは作成しないでください。
- 根拠のない理由を作り上げてはいけません。 「なぜなら……」に当たる内容を含めるのは、ソースに実際に記載されている場合だけです。ドキュメントに「Xを使う」とだけ書かれている場合、ノードにも「Xを使う」と記載し、理由を捏造しないでください。ソースから引用するか、忠実に言い換えてください。
- コードファイルを読もうとしてはいけません。 Markdown のドキュメントだけを対象にしてください。ブートストラップの目的は、すでに文書化されている内容を抽出することです。
- プラクティスとマップの境界は厳守してください。 プラクティスの候補をマップノードにしてはいけません。その逆も同様です。両方の内容が混在している場合は、2つのノードに分けてください。
- 検出、ハッシュの計算、スラッグの衝突解決、状態管理は
finddocsとnode writeに任せてください。 これらを独自に再実装してはいけません。
停止する条件
次の場合は停止して、ユーザーに確認してください。
finddocsの一覧に Markdown ファイルが約100件を超えて含まれている場合(対象範囲の指定が必要な可能性があります)。- 現行のバージョンを判断できないほど、明らかに議論が分かれている、またはバージョン固有のドキュメントに遭遇した場合。
- 内容を過剰に抽出していることに気づいた場合(ユーザーが現実的にレビューできる量を超えてノードが増えている)。
- ユーザーからしばらく修正がなく、自信が低下している場合。
ブートストラップは人の監督のもとで行います。不確かな場合は、人に判断を委ねてください。