diff --git a/skills/build-pr-description/SKILL.md b/skills/build-pr-description/SKILL.md index 94b7fb6..feee703 100644 --- a/skills/build-pr-description/SKILL.md +++ b/skills/build-pr-description/SKILL.md @@ -18,12 +18,9 @@ PR description は reviewer が diff を読むための文書。**Why は論証 (Google の CL description ガイド・Kubernetes template などが収束する Why → What → Test)に従う。 how の解説は diff 自身が語るので書かない。 -build-readme と同じく、匂い狩り(denylist)ではなく -**書いてよい文の allowlist** で判定する。該当しない文は書かない。 - +**形式の規律は `writing-documents` に委譲する。** この skill が持つのは PR 固有の +allowlist・骨子・fact の収集経路・PR 固有のチェックだけ。 publish-pr(PR 作成 flow)は body の作成をこの skill に委譲する。 -body の有無で変えるのは fact の収集経路だけ。既存 body は候補の入手元にはするが、 -正しい記載として継承しない。新規作成と全面再構築に同じ骨子・形式・完了チェックを適用する。 ## ルール @@ -43,7 +40,7 @@ body の有無で変えるのは fact の収集経路だけ。既存 body は候 根拠のない主張はただの意見 — 根拠を見つけるか、主張ごと落とす。 どの主張も支えない fact は Why に置かない(Notes 行きか削除)。 -文単位で迷ったら: **その文を消したとき、reviewer の diff の読み方や質問が変わるか?** +削除テストの主体は **reviewer**: その文を消したとき、reviewer の diff の読み方や質問が変わるか。 変わらないなら落とす。 ### 骨子 @@ -64,38 +61,22 @@ body の有無で変えるのは fact の収集経路だけ。既存 body は候 - allowlist と section の対応: 主張 + 根拠 → Why、変更の fact → What、 検証結果 → Test、注記 → Notes -### 形式 — section 内に置けるのは3形式のみ +### 形式 — PR の例外宣言 -- **bullet list** — 1 bullet = 1 fact。句点なし。「以下は〜」のような document 自身への言及は - bullet に形を変えた paragraph であり、fact ではない -- **table** — 各行が fact で、列の比較に意味があるとき bullet より優先する - (test 一覧・endpoint と契約の対応など。bullet 化すると比較可能性が落ちる) -- **code block** — 実行した検証コマンドなど、コピペして実行できる verbatim 成果物 +次の2つだけを例外として宣言する。 -- **Why は主張 → 根拠の2段 bullet**。主張が top-level、根拠をその直下に nest する。 +- **Why は主張 → 根拠の2段 bullet。** 主張が top-level、根拠をその直下に nest する。 nest を使ってよいのは Why だけ -- What / Test / Notes は上の3形式 + 1 fact 1 bullet -- paragraph(地の文)は全 section で禁止 - -例外: **Notes の bullet は理由節をぶら下げてよい**。README では理由節は弁明の -再侵入だが、Notes では rationale が fact そのもの -(「Tavern も検証のうえ pure pytest を採用 — assertion が YAML から漏れるため」で1 fact)。 +- **Notes の bullet は理由節をぶら下げてよい。** README では理由節は弁明の再侵入だが、 + Notes では rationale が fact そのもの(「Tavern も検証のうえ pure pytest を採用 — + assertion が YAML から漏れるため」で1 fact) -### 書き換え技法 — What を書くときの変換 - -- **rationale → 観測可能な保証。** What で理由を説明したくなったら、変更後に成り立つ契約に変換する - - 悪: `synchronize` では発火しない — push のたびに再付与すると人間の操作と競合するため - - 良: `synchronize` では付与せず、人間による assignee の付け替えを上書きしない - - 契約に変換できない rationale は Notes の管轄 -- **操作 → 不変条件。** 手続き(上書きする・剥がす・付け直す)が書きにくいときは、結果の状態を書く - - 悪: 更新のたびに label を上書きし、古い label を削除する - - 良: PR には常に、最新の変更量を反映した `size/*` が1つだけ付く -- **曖昧動詞の対象を明示。** 削除する・更新する・作る は、何に対する操作か読者が誤読する - (「label を削除」= repo の label 定義の削除に読める)。対象を書くか不変条件に変換する +What / Test は例外なし。 ### 判断の住処 — 問いの向きと寿命で分ける -- 「なぜこの変更が要るか」→ Why の主張。「なぜ X という代替じゃないか」→ Notes に 1-2 bullet +- 「なぜこの変更が要るか」→ Why の主張。「なぜ X という代替じゃないか」→ Notes に 1-2 bullet。 + What で説明したくなった rationale は観測可能な保証に変換し、できないものは Notes へ - 将来コードを触る人が必要とする決定 → ADR / code comment。PR は merge 後に 発掘されにくく、寿命の長い決定の恒久の家にならない - フル装備の「Rationale and alternatives」section を PR に張らない(RFC / ADR の形式) @@ -119,41 +100,37 @@ body の有無で変えるのは fact の収集経路だけ。既存 body は候 - **diff 内 doc の再掲** — README に書いた恒久 fact の丸写し。reviewer は diff で doc を読む - **動機の取り違え** — assertion や実装が参照する issue を「関連 issue:」として 動機に昇格させたもの。test が #N の契約を検証することと、PR の動機が #N であることは別 -- **session leak** — 会話の文脈への言及・自己弁護 tone ## 手順 — 主張と fact の収集・適用 -1. 既存 body がある場合は `gh pr view --json body` で取得し、**文単位**で allowlist に照合する。 +1. `writing-documents` を invoke し、共通の判定方法・形式・書き換え技法を読み込む +2. 既存 body がある場合は `gh pr view --json body` で取得し、**文単位**で allowlist に照合する。 section や構成は継承せず、生き残る文だけを候補にする -2. **What** — diff(`git diff` / `gh pr diff`)から観測できる変更と、変更後の対外契約を拾う。 +3. **What** — diff(`git diff` / `gh pr diff`)から観測できる変更と、変更後の対外契約を拾う。 既存 body と diff が食い違う場合は diff を正とする -3. **Why の主張は diff から導出できない**。既存 body・会話・commit message・既存 issue に求め、 +4. **Why の主張は diff から導出できない**。既存 body・会話・commit message・既存 issue に求め、 無ければ user に確認する。根拠はコード・実 resource・実測で検証してから主張の下に置く。 関連しそうな issue link を勝手に動機へ昇格させない -4. **Test** — session 中に実際に実行した検証コマンドと実測値を拾う。既存 body の記載値は +5. **Test** — session 中に実際に実行した検証コマンドと実測値を拾う。既存 body の記載値は 信じず、安全に再実行できるもの(`--collect-only`・lint 等)は再実行して照合する。 外部環境を叩くものは既存の実測値を使う -5. **Notes** — 既存 body・session から却下した代替案・設計の前例を拾う。 +6. **Notes** — 既存 body・session から却下した代替案・設計の前例を拾う。 merge 後に失われ、reviewer の一往復を減らす rationale だけを残す -6. 主張と fact を骨子に配置し、形式ルールを適用する。既存 body・会話由来の文は session leak を - **文単位**で検査する -7. **適用前に「完了チェック」を1項目ずつ機械的に検査する**。書く行為と検査する行為を - 分けないと守れない -8. `gh pr create --body-file ` または `gh pr edit --body-file ` で適用する -9. 以後 PR に commit を積んだら、What / Test に同じ規律で追記して同期する +7. 主張と fact を骨子に配置し、形式ルールを適用する +8. 完了チェックを1項目ずつ機械的に検査する +9. `gh pr create --body-file ` または `gh pr edit --body-file ` で適用する +10. 以後 PR に commit を積んだら、What / Test に同じ規律で追記して同期する ## 完了チェック +`writing-documents` の共通チェックに、以下を足して検査する。 + - [ ] Why の各 top-level bullet が主張(判断の叙述文)である — 事実の陳列になっていない - [ ] 全主張が「偽なら PR が不要になる」を満たす - [ ] 各主張の直下に検証済みの根拠が1つ以上 nest されている - [ ] どの主張も支えない fact が Why に残っていない - [ ] 主張が user 確認済みか、既存 body / commit / 会話に根拠がある -- [ ] paragraph(地の文)が1つも無い -- [ ] 各 bullet が単一の主張または fact(Notes 以外は理由節なし) -- [ ] 「以下は〜」型の meta-bullet(document への言及)がない - [ ] 恒久 fact が diff 内 doc と重複していない(PR は参照のみ) - [ ] 外部 SoT の値の snapshot に「現在値」の銘がある - [ ] Test の数値・コマンドが実装・再実行と照合済み - [ ] Notes が「reviewer が聞くであろう質問への先回り」だけで構成されている -- [ ] 消しても reviewer の読み方が変わらない文が残っていない diff --git a/skills/build-readme/SKILL.md b/skills/build-readme/SKILL.md index 80526c3..612cc52 100644 --- a/skills/build-readme/SKILL.md +++ b/skills/build-readme/SKILL.md @@ -14,12 +14,8 @@ description: > README を「system が何であるか」の観測可能な事実の集合として書く。 決定の物語・レビューへの弁明・実装の how は README の管轄外(PR / ADR / code の管轄)。 -悪い文の variation は無限にあるため、匂い狩り(denylist)ではなく -**書いてよい文の allowlist** で判定する。該当しない文は書かない。 - -README の有無で変えるのは fact の収集経路だけ。新規作成では system から収集し、 -全面再構築では既存 README を文単位で解体して候補を救出する。 -どちらも同じ allowlist・section composition・形式・完了チェックを適用する。 +**形式の規律は `writing-documents` に委譲する。** この skill が持つのは README 固有の +allowlist・section composition・fact の収集経路・README 固有のチェックだけ。 ## ルール @@ -38,7 +34,7 @@ README の有無で変えるのは fact の収集経路だけ。新規作成で 例外として、値の出典 link 1行(例: threshold は Prow size plugin の default)は bikeshedding 防止として許可する。 -判定に迷ったら: **その文を消したとき、読者の行動や期待が変わるか?** +削除テストの主体は **README の読者**: その文を消したとき、読者の行動や期待が変わるか。 変わらないなら弁明なので落とす。変わるなら(保証・非自明な挙動)残す。 ### section composition @@ -80,39 +76,12 @@ allowlist は「その fact を書いてよいか」、section は「読者が | `Troubleshooting` | 観測できる症状と読者が行う対処 | **Resources** は宣言、**Setup** は一度だけ行う操作、**Usage / Running** は繰り返す操作。 -前提・準備・日常操作を同じ section に混ぜない。順序に意味がある手順だけ ordered list を使う。 - -### 形式 — section 内に置けるのは3形式のみ - -- **bullet list** — 1 bullet = 1 fact。句点なし。「〜だが」「〜のため」で理由をぶら下げない - (bullet は接続詞を持てないので、弁明の再侵入を構文で防げる)。 - fact とは **system についての事実**。「以下は〜」のような document 自身への言及は - bullet に形を変えた paragraph であり、fact ではない。section の意味は見出しと配置で示す -- **table** — 各行が fact で、列の比較に意味があるとき bullet より優先する - (threshold 表・課金表など。bullet 化すると比較可能性が落ちる) -- **code block** — コピペして実行する verbatim 成果物(deploy commands など) - -paragraph(地の文)は禁止。ordered list は順序に意味がある手順だけに使う。 - -**1 fact = 1 home。** 同じ fact を2箇所に書かない。手で維持する概要 table・目次は -subsection 見出しの再述になり、drift の温床(機能の列挙は `##`/`###` 見出し自体が担う)。 -fact はそれが固有に属する場所に1回だけ書き、他所からは名前で参照する。 +前提・準備・日常操作を同じ section に混ぜない。 -### 書き換え技法 +### 形式 — README の例外宣言 -**操作 → 不変条件。** 手続き(上書きする・剥がす・付け直す)が書きにくいときは、 -結果の状態を書く。冪等性・重複排除・掃除が1文に含意される。 - -- 悪: 更新のたびに label を上書きし、古い label を削除する -- 良: PR には常に、最新の変更量を反映した `size/*` が1つだけ付く - -**rationale → 観測可能な保証。** 理由を説明したくなったら、読者から見える契約に変換する。 - -- 悪: `synchronize` では発火しない — push のたびに再付与すると人間の操作と競合するため -- 良: `synchronize` では付与せず、人間による assignee の付け替えを上書きしない - -**曖昧動詞の対象を明示。** 削除する・更新する・作る は、何に対する操作か読者が誤読する -(「label を削除」= repo の label 定義の削除に読める)。対象を書くか不変条件に変換する。 +- **paragraph の例外は h1 直下の lead 1-2文だけ。** section 内は例外なし +- **理由節・nest の例外は宣言しない。** README では理由節が弁明の再侵入になる ### 落ちる典型(allowlist が自動で弾くもの) @@ -130,30 +99,27 @@ fact はそれが固有に属する場所に1回だけ書き、他所からは ## 手順 -1. 対象 README の状態に応じて fact の候補を収集する +1. `writing-documents` を invoke し、共通の判定方法・形式・書き換え技法を読み込む +2. 対象 README の状態に応じて fact の候補を収集する - README がない場合: 実装(code・terraform・justfile 等)から収集する - README がある場合: 現 README を**文単位**で allowlist に照合する。既存 section や構成は 継承せず、生き残る文だけを候補にする -2. 候補を実装と照合する。README の prose・記憶・推測・会話の記載を根拠にしない。 +3. 候補を実装と照合する。README の prose・記憶・推測・会話の記載を根拠にしない。 内部 pipeline は、読者が観測できる結果(不変条件)に変換するか落とす -3. 読者が体感する値と限界を抽出する。cost は +4. 読者が体感する値と限界を抽出する。cost は 常時課金 resource の有無 → 従量課金の軸(何に比例するか)→ 上限・抑制の仕組みの順に確認する -4. system が前提とするが管理しない外部リソースを抽出する -5. 読者自身が行う操作を抽出し、初回の準備・繰り返す操作・保守操作を区別する -6. allowlist を通った fact を読者の関心ごとに cluster 化し、section composition のルールと +5. system が前提とするが管理しない外部リソースを抽出する +6. 読者自身が行う操作を抽出し、初回の準備・繰り返す操作・保守操作を区別する +7. allowlist を通った fact を読者の関心ごとに cluster 化し、section composition のルールと canonical section palette を使って header と順序を決める -7. 形式ルールを適用し、**提出前に「完了チェック」を1項目ずつ機械的に検査する** - (grep / 目視走査)。書く行為と検査する行為を分けないと守れない +8. 形式ルールを適用し、完了チェックを1項目ずつ機械的に検査する ## 完了チェック -- [ ] section 内に paragraph がない(prose は h1 lead のみ) +`writing-documents` の共通チェックに、以下を足して検査する。 + - [ ] 内容がない section や、固定骨子を埋めるためだけの section がない - [ ] 各 header が配下の fact に対する読者の関心を具体的に表している - [ ] 前提・一度だけ行う準備・繰り返す操作が同じ section に混ざっていない -- [ ] 各 bullet が単一の fact で、理由節をぶら下げていない -- [ ] 「以下は〜」型の meta-bullet(document への言及)がない -- [ ] 同じ fact が2箇所に書かれていない(概要 table・再掲・重複 link) - [ ] 読者が体感しない内部 config 値(batch window 等)が table や bullet に紛れていない - [ ] Cost がある場合、その数値・上限が実装と一致している -- [ ] 「消しても読者の行動・期待が変わらない文」が残っていない diff --git a/skills/writing-documents/SKILL.md b/skills/writing-documents/SKILL.md new file mode 100644 index 0000000..3c3e324 --- /dev/null +++ b/skills/writing-documents/SKILL.md @@ -0,0 +1,83 @@ +--- +name: writing-documents +description: > + The shared writing discipline for documents whose value is the facts a reader acts on — + README, PR description, issue, handover, design note. Judges every sentence against an + allowlist the caller defines instead of hunting smells, permits only three forms inside a + section (bullet, table, code block) with paragraphs banned, converts rationale into + observable guarantees, and separates writing from a mechanical final check. Use when + writing or fully rebuilding such a document, and when asked to strip prose, 地の文, + padding, or self-justification out of an existing draft. Owns no document type; + build-readme and build-pr-description delegate to it and add their own allowlist and skeleton. +--- + +# writing-documents + +読者が行動するための fact を運ぶ document に共通の規律。 + +**この skill が持つのは判定の方法と形式だけで、document 型は持たない。** allowlist の中身・ +section 骨子・fact の収集経路・削除テストの主体・形式の例外は呼び出し側 +(`build-readme`・`build-pr-description` など)が定義する。 +単独で呼ばれた場合は、対象 document の読者と「読者が取る行動」を先に確定させてから適用する。 + +## 判定 — allowlist で書く + +悪い文の variation は無限にあるため、匂い狩り(denylist)ではなく**書いてよい文の allowlist** +で判定する。候補の文を呼び出し側が列挙する文型に照合し、どれにも当たらなければ落とす。 + +**削除テスト** — 判定に迷ったら: **その文を消したとき、読者の行動・期待・判断が変わるか?** +変わらないなら落とす。変わるなら残す。主体(読者か reviewer か)は呼び出し側が決める。 + +新規作成と全面再構築の差は **fact の収集経路だけ**。既存 document は文単位で allowlist に照合し、 +生き残った文だけを候補にする。section・構成・記載の正しさは継承しない。 + +## 形式 — section 内に置けるのは3形式のみ + +- **bullet list** — 1 bullet = 1 fact。句点なし。「〜だが」「〜のため」で理由をぶら下げない。 + fact とは **document の主題についての事実**。section の意味は見出しと配置で示す +- **table** — 各行が fact で、列の比較に意味があるとき bullet より優先する +- **code block** — コピペして実行できる verbatim 成果物 + +**paragraph(地の文)は禁止。** ordered list は順序に意味がある手順だけに使う。 +nest と理由節は、呼び出し側が section を名指しで例外宣言したときだけ使える。 + +**1 fact = 1 home。** fact はそれが固有に属する場所に1回だけ書き、他所からは名前で参照する。 +手で維持する概要 table・目次は見出しの再述であり、drift の温床。 + +## 書き換え技法 + +**操作 → 不変条件。** 手続き(上書きする・剥がす・付け直す)が書きにくいときは、結果の状態を書く。 +冪等性・重複排除・掃除が1文に含意される。 + +- 悪: 更新のたびに label を上書きし、古い label を削除する +- 良: PR には常に、最新の変更量を反映した `size/*` が1つだけ付く + +**rationale → 観測可能な保証。** 理由を説明したくなったら、読者から見える契約に変換する。 + +- 悪: `synchronize` では発火しない — push のたびに再付与すると人間の操作と競合するため +- 良: `synchronize` では付与せず、人間による assignee の付け替えを上書きしない + +契約に変換できない rationale は、その document の管轄外(呼び出し側が行き先を決める)。 + +**曖昧動詞の対象を明示。** 削除する・更新する・作る は、何に対する操作か読者が誤読する +(「label を削除」= repo の label 定義の削除に読める)。対象を書くか不変条件に変換する。 + +## 落ちる典型 + +- **session leak** — 会話の文脈への言及・自己弁護 tone・「先ほどの指摘を反映し」型の編集履歴。 + document は成果物であり、それが作られた過程の記録ではない。会話・既存 document 由来の文は + **文単位**で検査する +- **meta-bullet** — 「以下は〜」「この section では〜」。document 自身への言及は + bullet に形を変えた paragraph であり、fact ではない + +## 完了チェック(共通) + +提出前に、呼び出し側の document 型固有チェックと合わせて **1項目ずつ機械的に検査する** +(grep / 目視走査)。書く行為と検査する行為を分けないと守れない。 + +- [ ] paragraph(地の文)が1つも無い(呼び出し側が許した lead を除く) +- [ ] 各 bullet が単一の fact で、nest・理由節が例外宣言された section 以外に無い +- [ ] 「以下は〜」型の meta-bullet がない +- [ ] 同じ fact が2箇所に書かれていない +- [ ] 会話への言及・自己弁護 tone が残っていない +- [ ] 消しても読者の行動・期待が変わらない文が残っていない