Back to skills
SKILL.md
Scribe
ASecurity過去の closed PR / issue と対象 repo の docs/research/ の調査結果から繰り返しの共通項を抽出し、最新コードと突き合わせて docs/wiki/ に PR で提案する。
- 12 stars
- 0 votes
- 0 copies
- 0 views
- Added September 24, 2026
Works with
Security analysis
100/100Pro scans all 8 files and shows the line behind each finding
npx -y skills add thkt/dotclaude --skill scribe --agent claude-codeAre you the author of Scribe?
Add the live security badge to your README. It updates with every re-scan.
[](https://www.skillsdirectory.com/skills/thkt-scribe)---
name: scribe
description: 過去の closed PR / issue と対象 repo の docs/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(${CLAUDE_SKILL_DIR}/scripts/*) Bash(${CLAUDE_SKILL_DIR}/../research/scripts/*) Read Write Edit LS
---
# /scribe - PR / issue / research 共通項の wiki 蓄積
拾う共通項は、定型手順や規約として繰り返される手順と、再発する指摘や失敗のパターン。1 度きりの個別事情と、設計判断そのものは拾わない。
## 不変条件
| 条件 | 内容 |
| ------------------- | -------------------------------------------------------------------------------------------------------------------------------------------- |
| PR 経由 | デフォルトブランチへ直接コミット / プッシュしない |
| 進捗の記録 | cursor は最後にマージされた scribe PR の mergedAt。research ファイルはその mergedAt と最終コミット時刻を比べる |
| 閾値の所在 | ページにするか候補に置くかの判定は `scripts/triage.ts` が持ち、この skill は判定しない |
| 事実のみ | PR / issue と research ファイルに書かれた事実、および現在のコードで確認できた事実のみ書く。推測で埋めない |
| 原本の識別 | research の根拠は原本への相対リンクで特定する。旧 `(research)` の原本が不明なら保持し、推測で対応付けない |
| 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. `${CLAUDE_SKILL_DIR}/../research/scripts/find-prior-research.ts --all docs/research research .claude/workspace/research` で新旧配置の原本を再帰的に列挙する。対象 repo 内の通常ファイルだけを読む。`path` を読み、root 相対名・原文同一のコピーは `aliases` で 1 件として扱う。同名で内容が違う原本は両方を確認し、版の違いを独立した根拠数にしない。mergedAt が無ければ初回として全原本と `gh pr list --state merged --search '-label:scribe'`、`gh issue list --state closed` の全件を対象にする
3. mergedAt があれば PR/issue は従来どおり `merged:><mergedAt>`/`closed:><mergedAt>` で絞る。原本は次のコマンドが列挙したパスを対象にする。
```sh
git log --since="<mergedAt>" --name-only --diff-filter=AM --pretty=format: -- 'docs/research/*.md' 'research/*.md' '.claude/workspace/research/*.md'
git ls-files --others --exclude-standard -- 'docs/research/*.md' 'research/*.md' '.claude/workspace/research/*.md'
git diff --name-only HEAD -- docs/research research .claude/workspace/research
```
`aliases` のどれかが該当すれば含める。手動実行は PR/issue が増えていなくても研究を調べる。自動 gate の起動条件は広げない。
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. その配列を `${CLAUDE_SKILL_DIR}/scripts/triage.ts '<共通項の JSON 配列>' docs/wiki/_candidates.md` に渡す。script が `_candidates.md` の両方の節から候補行を読んで配列へ混ぜ、閾値 2 件と 1 回あたりのページ上限を当て、`pages` (新規/昇格/更新)、`candidates`、`deferred` (今回は見送り) に分ける。閾値と上限を自分で判定しない
7. `docs/wiki/_candidates.md` を書き換える形を用意する。`candidates` は「単発」節へ、`deferred` は「昇格待ち」節へ置き、`pages` になった共通項の行は消す。行は `- <内容 1 行> <根拠>` の形にし、根拠は `#番号` と `[research:name.md](../research/name.md)` をスペース区切りで並べる。既に行があれば根拠だけを足す。書き込みは Phase 6 の worktree 内で行う
研究リンクのラベルは `[research:name.md](../research/name.md)` とする。旧配置だけにある原本は実在する旧配置へリンクする。同じ原本の新旧パスやラベル違いは triage が 1 件にまとめる。旧 `(research)` が識別済み原本と同じ項目に残るときは、別原本と確認できないため追加の 1 件には数えない。原本の特定は現在の内容・版・移行対応で確認し、移動やコピー自体を再発の根拠にしない。
| フィールド | 値 |
| ---------- | ------------------------------------------------------------------------------------------------------------- |
| `name` | 共通項の同一性を決めるキー。候補行から来たものは行の本文がそのまま入る。ページのファイル名は Phase 6 で決める |
| `evidence` | 根拠の配列。PR/issue は `#番号`、research は原本への Markdown 相対リンク。旧 `(research)` は不明のまま保持 |
| `existing` | 既存ページにあれば `page`、`_candidates.md` にあれば `candidate`、無ければ `none` |
## Phase 4: 最新コードとの突き合わせ
ページ化/昇格/更新の前に、各共通項を現在のコードと突き合わせる。この Phase で決めるのは書く内容で、ファイルへの書き込みは Phase 6 の worktree 内でまとめて行う。
1. 成立を確認した項目に、現行コードの位置を参照コードとして `path` + シンボル名で付記する。行番号は書かない
2. その決まりごとが効く実装ファイルの glob と、`find_wiki_rule.ts` の `SCENES` 定数から選ぶ 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 作成
wiki からリンクする原本が共有先の base または今回の許可済み変更に同じ内容で存在するか確認する。未追跡・共有未確認の原本を自動で取り込まない。欠ける原本に依存する公開は保留し、共有確認と必要な操作を報告する。
扱うページは 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. `${CLAUDE_SKILL_DIR}/scripts/verify_run.ts <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 とローカルブランチを残さない
Files in this skill
- SKILL.md
- scripts/find_wiki_rule.ts
- scripts/structure_page.ts
- scripts/triage.ts
- scripts/verify_run.ts
- templates/candidates.md
- templates/page.md
- templates/readme.md
Attribution
Comments
Loading comments…
Newsletter
Get the weekly list of safe new skills, and the ones we pulled.