Distillation de motifs récurrents dans le wiki

Extrait les motifs récurrents des PR, issues et fichiers de recherche, puis propose une documentation distillée au wiki via une PR.

Spar Skills Guide Bot
DocumentationAvancé
0029/08/2026
Claude CodeCursor
#wiki#pr-analysis#knowledge-distillation#documentation

Recommandé pour


name: scribe description: 過去の closed PR / issue と .claude/workspace/research/ の調査結果から繰り返しの共通項を抽出し、最新コードと突き合わせて docs/wiki/ に PR で提案する。 when_to_use: scribe 実行, wiki 抽出, 共通項の蒸留, PR/issue からの知見蓄積, research 成果の蓄積, run scribe, wiki extraction, distill recurring patterns allowed-tools: Bash(git:) Bash(gh:) Bash(find:) Bash(python3:) Read Write Edit LS

/scribe - PR / issue / research 共通項の wiki 蓄積

拾う共通項は、定型手順や規約として繰り返される手順と、再発する指摘や失敗のパターン。1 度きりの個別事情と、設計判断そのものは拾わない。

不変条件

| 条件 | 内容 | | ------------------- | -------------------------------------------------------------------------------------------------------------------------------------------- | | PR 経由 | デフォルトブランチへ直接コミット / プッシュしない | | 進捗の記録 | cursor は最後にマージされた scribe PR の mergedAt。research ファイルはその mergedAt と最終コミット時刻を比べる | | 閾値の所在 | ページにするか候補に置くかの判定は scripts/triage.py が持ち、この skill は判定しない | | 事実のみ | PR / issue と research ファイルに書かれた事実、および現在のコードで確認できた事実のみ書く。推測で埋めない | | research は引かない | .claude/workspace/research/ のファイルパスを docs/wiki/ 配下に書かない。wiki は蒸留した共通項を置く場所で、パスは読者を原資料へ送り返す | | worktree 隔離 | 編集 / commit は隔離 worktree 内で行い、ユーザーの作業ツリーを動かさない。worktree を作るのは Phase 6 なので、書き込む Phase は Phase 6 だけ |

Phase 1: 前提確認とオンボーディング

  1. gh pr list --label scribe --state open --limit 1 で未マージの scribe PR を確認する。あれば追い越さず、中断して報告する
  2. docs/wiki/README.md が無ければ ${CLAUDE_SKILL_DIR}/templates/readme.md の内容を用意する
  3. docs/wiki/_candidates.md が無ければ ${CLAUDE_SKILL_DIR}/templates/candidates.md の内容を用意する。手順 2 と合わせ、書き込みは Phase 6 の worktree 内で行う
  4. scribe ラベルが無ければ gh label create scribe --description "scribe による wiki 提案" で作成する

Phase 2: スコープ決定

  1. 最後にマージされた scribe PR の mergedAt を gh pr list --label scribe --state merged --limit 1 --json mergedAt -q '.[0].mergedAt' で取得する
  2. mergedAt が取れなければ初回。gh pr list --state merged --search '-label:scribe'gh issue list --state closed の全件、および find .claude/workspace/research -name '*.md' の全件を対象にする
  3. mergedAt が取れたら差分だけを対象にする。PR は gh pr list --state merged --search "-label:scribe merged:><mergedAt>" で集める。issue は gh issue list --state closed --search "closed:><mergedAt>" で集める。調査ファイルは git log --since="<mergedAt>" --name-only --diff-filter=AM --pretty=format: -- '.claude/workspace/research/*.md' | sort -u で集める。これに未追跡分の git ls-files --others --exclude-standard -- '.claude/workspace/research/*.md' を加える。未コミットのレポートは git log に載らず、それこそローカル run が持っていやすい 1 件になる
  4. research の対象は *.md だけとし、他の形式は読まない。cursor には各ファイルの最終コミット時刻を使い、mtime とファイル内の Generated: 行は使わない。checkout は内容の変更時期と無関係に mtime を checkout 時刻へ戻すので、mtime では比較の基準にならない。Generated: は生成時の日付で、後から追記してもその日付のままなので、更新を取りこぼす
  5. PR/issue/research のいずれも 0 件でも、docs/wiki/_candidates.md に根拠 2 件以上の行があれば Phase 3 へ進む。その行も無いときだけ「新規なし」と報告して終了する

Phase 3: 抽出

  1. docs/wiki/*.md を読み、既存ページを把握する。kind: structure を持つページは共通項ではないので、名前が一致しても existing: "none" のままにする
  2. スコープの各 PR/issue を gh pr view <番号> --comments/gh issue view <番号> --comments で本文/コメントまで読む
  3. スコープの各 research ファイルを Read で全文読む。セクション名で絞らない
  4. 読んだ内容を共通項ごとにまとめ、配列へ足す。同じ共通項が配列にあれば根拠だけを足す。設計判断とその経緯は docs/decisions/ の領分なので対象外
  5. docs/wiki/_candidates.md を読み、配列の共通項が既存の候補行と同じものを指すなら、その行の本文をそのまま name に使う
  6. その配列を python3 ${CLAUDE_SKILL_DIR}/scripts/triage.py '<共通項の JSON 配列>' docs/wiki/_candidates.md に渡す。script が _candidates.md の両方の節から候補行を読んで配列へ混ぜ、閾値 2 件と 1 回あたりのページ上限を当て、pages (新規/昇格/更新)、candidatesdeferred (今回は見送り) に分ける。閾値と上限を自分で判定しない
  7. docs/wiki/_candidates.md を書き換える形を用意する。candidates は「単発」節へ、deferred は「昇格待ち」節へ置き、pages になった共通項の行は消す。行は - <内容 1 行> <根拠> の形にし、根拠は #番号(research) をスペース区切りで並べる。既に行があれば根拠だけを足す。書き込みは Phase 6 の worktree 内で行う

| フィールド | 値 | | ---------- | ------------------------------------------------------------------------------------------------------------- | | name | 共通項の同一性を決めるキー。候補行から来たものは行の本文がそのまま入る。ページのファイル名は Phase 6 で決める | | evidence | 根拠の配列。PR/issue 由来は #番号、research 由来は (research) | | existing | 既存ページにあれば page_candidates.md にあれば candidate、無ければ none |

Phase 4: 最新コードとの突き合わせ

ページ化/昇格/更新の前に、各共通項を現在のコードと突き合わせる。この Phase で決めるのは書く内容で、ファイルへの書き込みは Phase 6 の worktree 内でまとめて行う。

  1. 成立を確認した項目に、現行コードの位置を参照コードとして path + シンボル名で付記する。行番号は書かない
  2. その決まりごとが効く実装ファイルの glob と、find_wiki_rule.pySCENES 定数から選ぶ scenes を決める。両者は独立した判定になる。glob は実装ファイルを、scenes は場面を指し、起票や PR の運用に閉じる決まりごとは glob が空配列のまま scenes を持つ
  3. 今回のスコープに関係しない既存ページも含め、docs/wiki/*.md 全ページの参照コードを掃除する。ファイルの存在と、ファイル内でのシンボル名の grep 一致を機械的に確認する
  4. 構造ページごとに、境界・契約・要求の各節が挙げる行を現行コードと突き合わせる。参照コードの状態とは独立に、対象のページを毎回すべて行う。ずれがあれば現行コードに合わせて書き直す文面を決める。落とさない
  5. 壊れていた参照は現行コードを読み直す。決める内容は下表による
  6. 落とした項目が _candidates.md に行を持つとき、その行を「棄却」節へ移し、次の行に落とした理由をインデントして書く。Phase 3 手順 7 が用意した削除より優先する

| 確認 | 不成立のときに決める内容 | | --------------------------------------------------- | ------------------------------------------------ | | 規約 / 手順が現在の実装でも成立するか | 落とす。既存ページの項目なら不成立と書き直す文面 | | 構造ページの記述が現在の実装と一致するか | 現行コードに合わせて書き直す文面。落とさない | | lint / hook / CI ですでに機械的に強制されていないか | 落とす | | 参照するパス / コマンドが現存するか | 現行のパス / コマンドへの張り替え先 |

Phase 5: 由来リンクの判定

ページ化/昇格/更新するページでは、共通項が docs/decisions/ の特定 DR の決定から派生している場合に限り、「由来」節に DR のファイルパスを書く。判定は反事実テスト「その DR が supersede されたらこのページは書き換えが必要になるか」で、Yes のときだけ張る。1 ページに 3 本以上並んだら各リンクへ反事実テストを再適用し、No になったものを外す。

あわせて、既存ページも含めた全ページの由来リンクを点検する。DR ファイルの実在と status を確認し、superseded なら後継 DR を読む。共通項が引き続き成立する場合は由来の張り替え先を後継に決め、成立しない場合は不成立として書き直す内容を決める。ここでも書き込みは Phase 6 で行う。

Phase 6: PR 作成

扱うページは Phase 3 の pages に限り、deferred は PR 本文に残しとして明記する。参照修理と由来修理、そして Phase 4 手順 4 が決めた構造ページの書き直しは上限の外なので、pages が 0 件でも実施する。候補への追記だけでも PR を作り、変更が何も無いときだけ作らない。

  1. git fetch origin <デフォルトブランチ> の後、origin/<デフォルトブランチ> から隔離 worktree とブランチ scribe/<yyyymmdd-HHMMSS> を作る
  2. worktree 内で Phase 3-5 が決めた内容を書き込む。骨格は書き込みの種類で選ぶ。pages の項目は ${CLAUDE_SKILL_DIR}/templates/page.md の共通項の骨格に従う。Phase 4 手順 4 が書き直しを決めた構造ページは、同ファイルの構造ページの骨格に従い、既存ページの当該行だけを差し替える。候補行は Phase 3 手順 7 の形で _candidates.md へ、参照修理と由来修理は Phase 4-5 が決めた張り替え先で書く
  3. commits の要素を先頭から順にコミットする。1 コミット目は自分が含むページに加え _candidates.md の更新と参照修理・由来修理も git add し、残りの要素は自分が含むページだけを git add する。要素ごとにメッセージ docs(wiki): <要素内の共通項名, ...> を追加/更新 で 1 要素 1 コミットする
  4. python3 ${CLAUDE_SKILL_DIR}/scripts/verify_run.py <worktree> <base> を実行し、Phase 3 の report JSON を stdin へ渡す。<base> は手順 1 で分岐した origin/<デフォルトブランチ>。昇格待ちの行数と期待コミット数は script が report から読むので、自分で数えない。ok が true であることを確認し、false なら手順 5 へ進まない
  5. push して gh pr create --base <デフォルトブランチ> を実行する。タイトル [scribe] <共通項名, ...> を追加/更新、ラベル scribe。本文には追加/昇格/更新したページをコミットごとに分けて並べ、候補への追記、参照修理/由来修理したページ、読んだ PR/issue の範囲と research の件数、検証で落とした項目、打ち切った残しを書く
  6. worktree を削除する
  7. 手順 4 が false を返したときは worktree を残す。書き込みをやり直せる状態にしておく。手順 5 以降が失敗したときは git worktree remove --force <worktree>git branch -D scribe/<yyyymmdd-HHMMSS> を実行し、worktree とローカルブランチを残さない
Skills similaires