Part 5 AIと知識作業

第20章 テクニカルライティングと知識共有

第19章では、AIコーディングを、feature brief、context pack、session plan、diff review、work log、PR説明という作業工程として扱った。 第20章では、その工程で生まれた情報を、チームが使える技術文書へ変える。 AIに何を頼んだか、どの差分を採用したか、どのテストを通したか、どの判断を残したか。 これらは一回の作業記録で終わらせるには惜しい。 README、設計メモ、ADR、PR説明、runbook、インシデント報告へ整理すれば、未来の開発者が同じ調査を繰り返さずに済む。

テクニカルライティングは、文章をきれいに飾る技術ではない。 技術的な事実、手順、判断、制約、残課題を、読者が次に行動できる形へ並べ替える技術である。 文体は大切だが、文体だけを直しても文書は良くならない。 読者が分からない前提を補い、必要な順序で情報を出し、判断の根拠を残し、古くなりやすい箇所を見えるようにする。 それが、開発者が日常的に書く技術文書の役割である。

本章の題材は、支援ステータス一覧の絞り込み機能である。 第19章で、AIを使ってこの機能を実装する計画を作った。 第20章では、その成果を文書にする。 新しく参加した開発者が起動方法を知るためのREADME。 レビュアーが判断理由を読むための設計メモ。 将来の開発者が、なぜ絞り込み条件をURLに残したのかを知るためのADR。 AIで文章を整えた後に、人間が何を確認したかを残す文書レビュー記録。 余裕があれば、問題が起きたときに学習へ変えるインシデント報告の下書きも作る。

この章を読み終えると、次ができるようになる。

  • 文書を書く前に、読者、目的、読むタイミング、文書タイプを決められる。
  • README、設計メモ、ADR、PR説明、runbook、インシデント報告に、何を書くかと何を書かないかを分けられる。
  • 手順に前提、実行場所、期待結果、失敗時の止め方を書ける。
  • 判断文書に、根拠、制約、採用しなかった案、残課題を残せる。
  • AIで文章を整えた後に、事実の追加、判断理由の削除、secret混入を確認できる。
  • 文書のowner、last reviewed、置き換え先を書き、古くなる情報を管理できる。

この章で扱う範囲

この章では、文書を書く前に読者、目的、読むタイミングを決める。 そのうえで、README、設計メモ、ADR、PR説明、runbook、インシデント報告を使い分ける。 さらに、AIで文章を整えるときの注意点と、文書レビューの観点を扱う。

最終的に作るのは、doc-audience-plan.mdreadme-update-draft.mdfeature-design-note.mdadr-0001-filtering-support-status.mddoc-review-note.md である。 余裕があれば、incident-report-draft.md も作る。 ここで作る文書は、第21章の個人開発プロジェクトでも再利用する。 個人開発では、動くものを作るだけでなく、誰に向けたものか、どう確認したか、なぜその設計にしたかを説明する必要があるからだ。

エンジニアは毎日文章を書いている

エンジニアの仕事は、コードだけで進まない。 Pull Requestには変更理由を書く。 レビューコメントには、何を直したかを書く。 READMEには起動方法と確認方法を書く。 設計メモには、なぜその構成にしたかを書く。 runbookには、障害時に何を確認するかを書く。 インシデント報告には、何が起き、次に何を変えるかを書く。

これらは、書籍やブログのように読ませるための文章ではない。 仕事を進めるための文章である。 だから、上手な比喩や凝った表現よりも、読者が次に取る行動を間違えないことが優先される。 新しく入った開発者は、READMEを読んで起動したい。 レビュアーは、PR説明を読んでレビューの入口を知りたい。 運用担当者は、runbookを読んで安全に確認したい。 将来の自分は、ADRを読んで過去の判断を思い出したい。

Googleの技術文書教材は、技術文書をエンジニアの仕事の一部として扱い、読者、明確さ、簡潔さ、構造を重視している。 Software Engineering at Googleでも、文書はコードやAPIの理解、設計判断の共有、オンボーディング、手順の再現に効くと説明されている。 文書は「余裕があるときに書く飾り」ではない。 チームで長くソフトウェアを扱うなら、文書は変更を支える基盤になる。

良い文書は、読者の次の行動を助ける

良い技術文書は、読者を感心させる文書ではない。 読者が次の行動を取れる文書である。 行動とは、起動する、設定する、レビューする、判断する、障害対応する、設計を変更する、古い判断を置き換える、といった具体的な作業である。

この定義を置くと、文書の評価基準が変わる。 文章が自然かどうかだけでは足りない。 読者が誰か。 その読者は何を知っているか。 いつ読むのか。 読み終えたら何をできるべきか。 どの情報が足りないと行動を誤るか。 どの情報はここに書くと邪魔になるか。 これらを決める必要がある。

支援ステータス一覧の絞り込み機能で考える。 新しく参加した開発者は、まずアプリを起動し、一覧画面を開き、絞り込み機能を手元で確認したい。 この人に必要なのはREADMEである。 一方、レビュアーは、なぜURLに絞り込み条件を残すのか、APIで不正なquery valueをどう扱うのか、担当外データが見えないことをどう守るのかを知りたい。 この人に必要なのは設計メモやPR説明である。 半年後に別の開発者が「絞り込み条件をsession storageに移したい」と考えたときは、過去のADRが必要になる。 同じ機能でも、読者が違えば文書が違う。

読者、目的、読むタイミングを先に決める

文書を書き始める前に、読者、目的、読むタイミングを決める。 この三つが決まらないまま書くと、文書は情報の置き場になってしまう。 READMEに設計判断が長く入り、設計メモに起動手順が入り、ADRに日々の作業ログが入り、どれも読みにくくなる。

最初に、次の表を作る。

# Document Audience Plan

| reader | timing | what they need | document |
| --- | --- | --- | --- |
| 新規参加の開発者 | 初回セットアップ時 | 起動方法、確認方法、関連リンク | README |
| レビュアー | PRレビュー前 | 変更理由、設計判断、確認結果 | PR説明、設計メモ |
| 将来の開発者 | 仕様変更を検討するとき | 当時の文脈、採用案、捨てた案 | ADR |
| 運用担当者 | 問題発生時 | 影響確認、切り分け、戻し方 | runbook、インシデント報告 |
| AIコーディング支援 | 次回の実装時 | 現在の仕様、制約、確認方法 | README、設計メモ、ADR |

この表には、文章の上手さは出てこない。 しかし、ここを先に決めると、文書の役割が混ざりにくくなる。 どの読者にも全部を読ませる必要はない。 必要な読者に、必要な文書を渡す。 詳細が必要ならリンクでつなぐ。

もう一つ、文書を書く前に決めたいことがある。 何が事実で、何が判断で、何が推測で、何が未決定かである。 技術文書では、自然な文章よりも、この区別が読者を助ける。

| item | kind | evidence or owner |
| --- | --- | --- |
| API testは通った | fact | `npm test -- support-statuses-api` |
| URL queryに条件を残す | decision | ADR 0001 |
| 日付境界が原因かもしれない | hypothesis | 追加調査が必要 |
| `updated_to` を含むかどうか | open question | チーム確認待ち |

事実には、実行結果、コード、ログ、公式資料、PR、issueなどの根拠を付ける。 判断には、判断した理由と代替案を書く。 推測には、推測だと分かる言葉を使う。 未決定事項には、誰がいつ決めるかを書く。 この分け方があると、AIが文章を自然に整えたあとでも、根拠のない断定に気づきやすい。

文書タイプは、情報の置き場所を決める道具である

Diátaxisは、技術文書をチュートリアル、ハウツー、リファレンス、説明に分ける考え方である。 この分類は、英語の名前を覚えるためのものではない。 読者が今、何をしようとしているのかを見て、情報の置き場所を決めるために使う。

チュートリアルは、初めて学ぶ人が順に手を動かす文書である。 支援ステータス機能なら、ローカルでアプリを起動し、サンプルデータを見て、絞り込みを試す学習用手順が近い。 読者はまだ全体を知らないため、選択肢を増やしすぎず、成功できる一本道を用意する。

ハウツーは、特定の作業や問題を解く文書である。 たとえば「支援ステータス一覧で、最終更新日を指定して対象者を確認する」「ローカルでAPIの絞り込みを確認する」という文書である。 読者は何を達成したいかを知っている。 文書はその目的へ向かう手順に集中する。

リファレンスは、正確な情報を引く文書である。 query parameterの名前、許可されるstatus値、API responseの形、設定値、エラーコードなどが入る。 ここに長い背景説明を混ぜると、読者は必要な事実を探しにくくなる。

説明は、背景や理由を理解する文書である。 なぜURLに絞り込み条件を残すのか。 なぜDB schemaを変えないのか。 なぜ不正なstatusを500にしないのか。 こうした判断理由は、説明や設計メモ、ADRに置く。

文書の失敗の多くは、この四つが混ざるところから始まる。 READMEにチュートリアル、ハウツー、リファレンス、説明をすべて入れると、入口文書が重くなる。 逆に、設計メモに手順ばかり書くと、判断理由が残らない。 分類は厳密な箱ではないが、混ざったときに気づくための道具になる。

READMEは、プロジェクトの入口である

READMEは、リポジトリの入口である。 新しく参加した人、レビュー前に手元で動かす人、AIに作業前提を渡す人が最初に読むことが多い。 したがって、READMEの役割は、すべてを説明することではない。 最初に必要な情報へ迷わず到達できる入口を作ることである。

支援ステータス機能のREADME更新案には、少なくとも次を入れる。

  • 概要:何の機能か。
  • 起動前提:必要なランタイム、依存関係、環境変数、DB、実行するdirectory。
  • 使い方:どの画面で、どの条件を指定できるか。
  • 確認方法:どのコマンドや画面操作で動作を確認できるか。
  • 設定変更:環境変数やfeature flagがあれば書く。
  • 制約:未対応、注意点、古くなりやすい情報。
  • 関連文書:設計メモ、ADR、PR、runbookへのリンク。
  • 保守情報:owner、last reviewed、見直すタイミング。

READMEの悪い例は、情報が少ないことだけではない。 情報が多すぎることも悪い。 設計議論の全履歴、AIとの作業ログ、採用しなかった案の詳細、事故対応の時系列を全部READMEへ入れると、起動したい読者にとって邪魔になる。 READMEは入口であり、すべての倉庫ではない。

README更新案は、次の形で始められる。

# README Update Draft

## 概要

支援ステータス一覧では、メンターが担当受講者をステータスと最終更新日で絞り込める。
絞り込み条件はURLのquery parameterに残るため、再読み込みやリンク共有後も同じ条件を確認できる。

## 使い方

1. 開発サーバーを起動する。
2. `/support-statuses` を開く。
3. `status` を選ぶ。
4. 必要に応じて `updated_from``updated_to` を指定する。
5. 一覧に表示される受講者が条件に合っていることを確認する。

## 確認方法

| check | where | command or operation | expected result |
| --- | --- | --- | --- |
| API test | repository root | `npm test -- support-statuses` | 絞り込み条件のテストが通る |
| lint | repository root | `npm run lint` | lint errorがない |
| manual | browser | statusと日付を指定して一覧を見る | 条件に合う受講者だけが表示される |

## 制約と注意

- DB schemaは今回変更しない。
- 担当外の受講者は、絞り込み条件に関係なく表示しない。
- 日付範囲の境界は設計メモを参照する。
- `.env` の実値、token、Cookie、実在する受講者の個人情報はREADMEに書かない。

## 関連文書

- `feature-design-note.md`
- `adr-0001-filtering-support-status.md`
- PR:

## Maintenance

- owner:
- last reviewed:
- review when:

手順を書くときは、前提、順序、期待結果を入れる。 単に「テストを実行する」と書くより、どのコマンドをどこで実行し、何が表示されればよいかを書く。 ただし、本番に依存する値、secret、個人情報は入れない。 また、READMEに書くべきでないものも決める。 設計議論の詳細、AIとの全ログ、インシデントの時系列、古い判断の履歴は、READMEからリンクする別文書へ置く。 入口を軽く保つことは、情報を隠すことではない。 読者が最初に必要な情報へ進めるよう、置き場所を分けることである。

設計メモは、判断の背景を残す

設計メモは、コードを読むだけでは分からない判断を残す文書である。 コードは、何をしているかを示す。 設計メモは、なぜその形にしたかを示す。 この二つは役割が違う。

支援ステータス一覧の絞り込みでは、いくつかの判断がある。 絞り込み条件をURLに残すのか。 サーバー側でfilterするのか、クライアント側でfilterするのか。 不正なstatusをエラーにするのか、無視するのか。 日付範囲の境界を含むのか。 DB schemaを変えるのか、既存schemaで行くのか。 これらは、実装後のコードだけを見ても理由が分かりにくい。

設計メモには、背景、課題、制約、根拠、選択肢、採用案、判断理由、影響、残課題を書く。 特に、採用しなかった案を残す。 採用しなかった案は、未来の読者が同じ議論を繰り返さないための材料になる。

# Feature Design Note

## 背景

メンターは、担当受講者の支援状態を一覧で確認している。
受講者が増えると、対応が必要な人を見つけるために一覧を目視で探す時間が増える。

## 課題

支援ステータスと最終更新日で一覧を絞り込み、対応が必要な受講者を見つけやすくしたい。

## 制約

- DB schemaは今回変更しない。
- 担当外の受講者を表示しない既存の認可は維持する。
- 既存の一覧画面の構造を大きく変えない。
- 不正なquery valueで500を返さない。

## 根拠

| evidence | source |
| --- | --- |
| status/dateの絞り込みは受け入れ条件に含まれる | ai-feature-brief.md |
| 認可条件を壊さないことはdiff reviewで確認対象 | ai-diff-review.md |
| API testを追加する方針 | ai-work-log.md |

## 選択肢

| option | summary | good | concern |
| --- | --- | --- | --- |
| URL queryに条件を残す | `status` と日付範囲をURLに保持する | 再読み込み、共有、戻る操作に強い | query validationが必要 |
| local stateだけで保持する | 画面内stateに条件を持つ | 実装が軽い | 再読み込みで条件が消える |
| session storageに保持する | browser storageへ保存する | 画面をまたいで残せる | 共有URLにならず、状態の説明が難しい |

## 採用案

URL queryに絞り込み条件を残す。
APIはquery parameterを検証し、許可された条件だけを検索に使う。

## 判断理由

メンターは、同じ条件を再読み込み後にも確認したり、レビュー時にURLを共有したりする可能性がある。
URLに条件を残すと、画面状態とrequestの対応が見えやすく、テストでも確認しやすい。

## 影響

| area | impact |
| --- | --- |
| UI | 絞り込みフォームとURL同期が必要 |
| API | query validationが必要 |
| Test | status、日付範囲、不正値、認可の確認が必要 |
| Docs | READMEとADRにURL方針を残す |

## 残課題

- 日付境界を含むかどうかを仕様として確定する。
- 絞り込み条件が増えた場合のURL設計を再検討する。

## 未決定事項

| item | owner | due | note |
| --- | --- | --- | --- |
| `updated_to` の境界を含むか |  |  | READMEとADR更新が必要 |

設計メモでは、すべてを美しく結論づける必要はない。 残課題は残課題として書く。 不明点を隠すと、未来の読者は決定済みだと誤解する。 分かっていること、決めたこと、まだ決めていないことを分ける方が、文書として信頼できる。 根拠が薄い判断には、根拠が薄いと書く。 「AIがそう提案したから」だけでは、設計理由として弱い。 受け入れ条件、実行結果、既存コード、公式資料、チーム判断のどれに基づくかを書く。

ADRは、一つの重要な判断を残す

ADRは、Architecture Decision Recordの略である。 アーキテクチャ上重要な判断を、小さな記録として残す文書である。 Michael NygardのADRの記事では、大きな文書よりも小さく保守しやすい記録として、文脈、決定、状態、結果を残す考え方が示されている。

ADRは、設計メモより狭い。 設計メモは、問題、選択肢、影響を広く扱う。 ADRは、一つの決定を将来へ残す。 支援ステータス機能なら、「絞り込み条件をURLに残す」という判断だけをADRにする。 「一覧画面を改善する」や「検索を便利にする」は広すぎる。

ADRには、状態を書く。 提案中、採用、置き換え済み、廃止などである。 一度採用したADRも、未来永劫変わらない真理ではない。 状況が変わったら、新しいADRで置き換える。 古いADRは消さず、supersededとして新しい判断へのリンクを残す。 古い判断を消すと、過去の文脈が失われる。 また、ADRには良い影響だけを書かない。 決定によって生まれる悪い影響や中立の影響も、将来の読者には重要である。 「URLで共有しやすい」という利点と、「条件が増えるとURLが読みにくくなる」という注意点を同じ文書に置く。

# ADR 0001: 支援ステータス一覧の絞り込み条件をURLに残す

## 状態

提案中

## 背景

メンターは支援ステータス一覧を、ステータスと最終更新日で絞り込みたい。
絞り込み条件は、レビュー時や再確認時に再現できる必要がある。
一方で、DB schema変更や画面全体の大改修は今回の範囲に含めない。

## 決めたこと

絞り込み条件はURLのquery parameterとして表す。
APIは許可されたquery parameterだけを受け取り、不正な値では500を返さない。

## 影響

良い影響:

- 再読み込み後も条件が残る。
- URLを共有すると、同じ条件で画面を開ける。
- API requestと画面状態の対応を確認しやすい。

悪い影響・注意点:

- query parameterの検証が必要になる。
- 条件が増えた場合、URLが読みにくくなる可能性がある。
- 日付境界の仕様をREADMEまたは設計メモで説明する必要がある。

中立の影響:

- URLが画面状態の一部として扱われるため、UI testとAPI testの両方で確認する。

## 選ばなかった案

| 案 | 選ばなかった理由 |
| --- | --- |
| 画面内stateだけで保持する | 再読み込みや共有で条件が失われる |
| session storageに保存する | URLから状態を再現できず、レビュー時の共有に向かない |

## 関連リンク

- PR:
- **設計メモ**`feature-design-note.md`
- superseded by: none

ADRでは、決定を短く書く。 長い背景説明を入れたくなったら、設計メモへリンクする。 ADRは、将来の読者が「この判断はまだ有効か」「置き換えるなら何に注意すべきか」を判断するための記録である。 採用済みADRの本文を後から大きく書き換えると、当時の判断が見えにくくなる。 誤字修正やリンク追加はよいが、判断そのものが変わるなら新しいADRを作り、古いADRをsupersededにする。

PR説明は、レビューの入口である

PR説明は、差分の目次ではない。 レビュアーがレビューを始めるための入口である。 GitHubのPull Requestは変更を提案し、議論し、レビューする場所である。 Googleの変更説明のガイドでも、変更説明は将来の履歴として読まれるため、何をしたかだけでなく、なぜその変更が必要かを伝えることが重視されている。

PR説明に必要なのは、次の情報である。

  • 変更の背景。
  • 何を変えたか。
  • 何を変えていないか。
  • どう確認したか。
  • 何を確認していないか。
  • レビュアーに見てほしい点。
  • 残課題やリスク。
  • AIを使った場合は、どこに使い、人間が何を確認したか。

支援ステータス機能なら、PR説明は次のように書ける。

## Summary

支援ステータス一覧に、ステータスと最終更新日の絞り込みを追加しました。
絞り込み条件はURL queryに残るため、再読み込みやレビュー時の共有で同じ条件を確認できます。

## Changes

- 一覧画面に絞り込みフォームを追加
- APIで `status``updated_from``updated_to` を検証して検索へ反映
- 不正なstatusで500を返さないように処理
- API testと手動確認手順を追加

## Not included

- DB schema変更
- 通知機能
- CSV export

## Verification

- [ ] `npm test -- support-statuses`
- [ ] `npm run lint`
- [ ] `/support-statuses?status=needs_support` の手動確認
- [ ] 担当外受講者が表示されないことの確認

## Checks not run

- `npm run typecheck`: scriptがないため未実行
- E2E test: 対象のE2Eがまだないため未実行

## Review focus

- query parameterのvalidation
- URLと画面状態の同期
- 認可条件が既存と変わっていないこと
- 日付境界の扱い

## AI assistance

AIには関連ファイルの調査、テスト観点の洗い出し、PR説明の下書き整理を依頼しました。
最終差分、テスト結果、認可観点、secretが含まれていないことは人間が確認しました。

## Remaining work

- 日付境界の仕様をチームで確定する。

PR説明が薄いと、レビュアーは差分から背景を推測することになる。 レビュー時間が増え、指摘が表面的になりやすい。 逆に、PR説明が長すぎて要点が埋もれると、入口として機能しない。 背景、変更、確認、見てほしい点を分けるだけで、レビューは始めやすくなる。 未実行確認を書くことは、弱さを見せることではない。 レビュアーが次に見るべき場所を分かるようにするためである。 「確認していないこと」を隠すより、残課題として明示した方が、チームは安全に判断できる。

runbookは、判断中に読む文書である

runbookは、繰り返す運用作業や問題対応をまとめる文書である。 READMEが入口なら、runbookは運用中の手順である。 平常時に読んで学ぶ文書というより、何かを確認したいとき、失敗を止めたいときに開かれる。

runbookには、前提、使ってよい条件、使ってはいけない条件、手順、確認方法、戻し方、危険な操作、エスカレーション先を書く。 コマンドだけを並べると危険である。 どの環境で実行するのか。 実行前に何を確認するのか。 期待される結果は何か。 失敗したらどう止めるのか。 この情報がないと、読者は手順を実行してよいか判断できない。

支援ステータス機能でrunbookを書くなら、たとえば「絞り込み結果がおかしいと報告されたときの確認手順」が考えられる。

# Runbook: 支援ステータス一覧の絞り込み結果を確認する

## 前提

- 本番データの個人情報を外部AIへ入力しない。
- 担当外データが表示される疑いがある場合は、調査を止めてメンターへエスカレーションする。
- 実行環境と対象URLを記録してから確認する。

## このrunbookを使ってよい条件

- 絞り込み結果が期待と違うという報告を受けた。
- 本番データへ直接書き込む操作をしない。

## このrunbookを使ってはいけない条件

- 担当外データが見えている可能性がある。
- 個人情報がログや画面に出ている可能性がある。
- 影響範囲が判断できない。

この場合は調査を止め、エスカレーション条件に従う。

## 確認手順

1. 報告されたURLのquery parameterを確認する。
2. `status``updated_from``updated_to` が許可された形式か確認する。
3. 同じ条件をローカルまたは検証環境で再現する。
4. API responseで担当外データが含まれていないことを確認する。
5. 直近の関連PRとADRを確認する。

## 期待結果

- 不正なquery valueで500にならない。
- 担当外受講者が表示されない。
- URL条件と画面表示が一致する。

## 戻し方

- 直近PRのrevert可否を確認する。
- feature flagがある場合は無効化手順を確認する。
- DB変更が含まれる場合は、このrunbookだけで戻さない。

## エスカレーション条件

- 担当外データが表示される。
- 個人情報がログに出ている。
- 影響範囲が判断できない。

runbookでは、詳細な背景説明より、正確に動けることを優先する。 背景が必要なら、設計メモやADRへリンクする。 runbookは、書いた時点では正しくても環境変更で古くなりやすい。 最後に実行確認した日、owner、見直す条件を残す。 古いrunbookが実行されると危険な場合は、古い手順を残すより、置き換え先を明示して読者を誘導する。

インシデント報告は、責める文書ではない

インシデント報告は、問題が起きたあとに、事実、影響、対応、原因候補、再発防止を残す文書である。 Google SREのポストモーテム文化では、障害から学ぶための形式化された過程が重視される。 インシデント報告は、責任追及ではなく、次に同じ問題を起こしにくくする学習へ向ける。

新人研修では、大きな本番障害を扱う必要はない。 ただし、小さな不具合でも、インシデント報告の型を知っておく価値がある。 たとえば、絞り込み条件の不正値で一覧画面が500になった、日付境界の扱いが曖昧で対象者が漏れた、担当外データが見えそうな実装になっていた、という問題は、学習用の報告にできる。

報告では、事実、推測、判断を分ける。 事実は、ログ、時刻、操作、影響範囲など、確認した情報である。 推測は、まだ確定していない原因候補である。 判断は、次にどうするかである。 これらを混ぜると、読者はどこまで確認済みなのか分からなくなる。 時刻を書くときは、タイムゾーンも書く。 発生、検知、対応開始、復旧、再発防止の作業開始を分ける。 影響が分からない場合は、分からないと書く。

# Incident Report Draft

## 概要

支援ステータス一覧で、不正な `status` query value を指定すると500になる問題が見つかった。

## 影響

- **影響範囲**:絞り込みURLを直接開いた利用者
- **データ破損**:なし
- **個人情報露出**:現時点では確認なし
- **検知方法**:PRレビュー中の手動確認
- **復旧状態**:修正PRで確認中

## 前提

- timezone: Asia/Tokyo
- 事実、推測、判断を分けて書く。
- 個人情報やsecretの実値は記録しない。

## 時系列

| 時刻 | 出来事 |
| --- | --- |
| 10:05 | レビュアーが不正なURLで500を確認 |
| 10:15 | APIのquery validation不足を原因候補として確認 |
| 10:30 | 不正値を安全に扱う修正を作成 |
| 10:45 | API testと手動確認を実行 |

## 起きたこと

APIが `status` query valueを許可値に照合せず、検索条件として扱っていた。

## 対応

- 許可値以外のstatusを検索条件に使わないよう修正した。
- 不正値のAPI testを追加した。

## 原因候補・関係した要因

- 受け入れ条件に不正値の扱いはあったが、テストケースへの反映が漏れていた。
- 設計メモでvalidation方針の記述が短かった。

## まだ分かっていないこと

- 実利用者が同じURLを開いたかは未確認。
- 他のquery parameterでも同じ問題が起きるかは追加確認が必要。

## 次にやる対応

| 対応 | 担当 | 期限 | 確認方法 |
| --- | --- | --- | --- |
| 不正query valueのテストを追加 |  |  | API test |
| READMEにquery parameterの許可値を追記 |  |  | 文書レビュー |
| ADRにvalidation方針へのリンクを追加 |  |  | ADR確認 |

インシデント報告では、誰が悪かったかを探すより、どの仕組みが足りなかったかを見る。 テストケース、レビュー観点、文書、runbook、アラート、権限のどこを変えると再発しにくいかを書く。 action itemは、反省文ではなく、所有者、期限、確認方法を持つ作業にする。 「気をつける」では弱い。 「不正query valueのAPI testを追加し、CIで実行されることを確認する」のように、完了を確認できる形にする。

AIは文章を整えられるが、事実を確定しない

AIは、技術文書の作成に役立つ。 構成案を作る。 見出しを整理する。 長い作業ログを要約する。 読者に合わせて表現を言い換える。 曖昧な表現を指摘する。 レビュー観点を洗い出す。 PR説明や設計メモの下書きを読みやすくする。

しかし、AIに任せたままにしてはいけないことがある。 技術的事実の追加。 判断理由の変更。 根拠のない断定。 secret、個人情報、未公開情報を含む文書の貼り付け。 障害報告の事実関係の確定。 ライセンスや法務判断。 古い情報の更新判断。 これらは人間が確認する。

AIへ文書改善を依頼するときは、制約を明示する。

次の設計メモを、レビュアーが読みやすいように改善してください。

前提:
- 技術的な事実は勝手に追加しない
- 判断理由を削らない
- 制約と残課題を残す
- APIキー、個人情報、未公開情報は含めない

見てほしい観点:
- 読者が分かる順序になっているか
- 背景、判断、影響が分かれているか
- 曖昧な表現がないか
- PRレビューで使いやすいか

AIの出力を採用するときは、変更前後を読む。 文が自然になっていても、判断理由が削られていることがある。 読みやすくなっていても、不確実だった事項が断定に変わっていることがある。 短くなっていても、制約や残課題が消えていることがある。 AIによる推敲では、文面の改善と情報の欠落を同時に確認する。

文書にもdiff reviewが必要である。 AIに推敲させたら、次を確認する。

| check | question |
| --- | --- |
| fact | 実行していない確認が実行済みに変わっていないか |
| decision | 判断理由や採用しなかった案が削られていないか |
| uncertainty | 未決定事項が断定に変わっていないか |
| scope | READMEに設計議論やincident時系列を入れすぎていないか |
| safety | secret、個人情報、内部URL、実tokenが残っていないか |
| links | 関連文書へのリンクが壊れていないか |

AIに「短くして」とだけ頼むと、制約や残課題から削られることがある。 依頼するときは「削ってはいけない情報」を明示する。 採用後は、AIが変えた文と元の根拠を照合する。

文書レビューは、誤字探しだけではない

文書レビューは、誤字や表記ゆれを見るだけではない。 読者が次の行動を取れるかを確認する作業である。 コードレビューと同じように、文書にも品質観点がある。

最低限、次を確認する。

  • 読者が明確か。
  • 目的が明確か。
  • 手順が再現できるか。
  • コマンドに実行場所と期待結果があるか。
  • 判断理由があるか。
  • 事実、判断、推測、未決定が分かれているか。
  • 根拠のない追加がないか。
  • 制約や残課題が削られていないか。
  • 古くなりやすい情報が分かるか。
  • secret、個人情報、未公開情報がないか。
  • 公開リポジトリに出せない内部URL、絶対パス、顧客情報がないか。
  • 関連文書へのリンクがあるか。
  • リンク先の文書タイプが適切か。
  • AIに渡す前提情報として使いやすいか。

文書レビュー記録は、次の形で残せる。

# Document Review Note

## 対象文書

- `feature-design-note.md`
- `adr-0001-filtering-support-status.md`

## AIに依頼したこと

- 設計メモの見出し整理
- README向けに短い概要文の作成
- レビュー観点の洗い出し

## 採用した改善

- 背景、課題、制約、選択肢、採用案の順に並べ替えた。
- READMEの概要を二文に短くした。
- review focusにquery validationと認可を追加した。

## 採用しなかった改善

- AIが提案したDB schema変更の説明は、今回の非対象なので採用しなかった。
- 日付境界を断定する文は、仕様未確定のため採用しなかった。

## レビューチェックリスト

- [ ] 読者が明確
- [ ] 目的が明確
- [ ] 手順が再現できる
- [ ] コマンドに実行場所と期待結果がある
- [ ] 判断理由がある
- [ ] 事実、判断、推測、未決定が分かれている
- [ ] 根拠のない追加がない
- [ ] 重要な制約や残課題が削られていない
- [ ] 古くなりやすい情報が分かる
- [ ] 秘密情報、個人情報、未公開情報がない
- [ ] 公開リポジトリに出せない内部URL、絶対パス、顧客情報がない
- [ ] 関連文書へのリンクがある
- [ ] リンク先の役割が適切
- [ ] AIに渡す前提情報として使いやすい

## 残課題

- 日付境界の仕様をチームで決めた後、READMEとADRを更新する。

この記録があると、AIで文章を整えたこと自体よりも、人間が何を採用し、何を採用しなかったかが分かる。 文書作成でも、AI利用の説明責任は残る。

古くなる情報を管理する

文書は、書いた瞬間から古くなる可能性を持つ。 起動コマンドが変わる。 APIのquery parameterが増える。 feature flagがなくなる。 ADRが新しい判断に置き換えられる。 runbookの手順が環境変更で使えなくなる。

だから、文書には古くなりやすい情報を示す。 更新担当、最終確認日、関連PR、置き換え先、正本を書く。 すべての文書に重い管理を入れる必要はないが、判断や運用に使う文書では、読者が古さを判断できるようにする。

## Maintenance

- **owner**:support-status feature owners
- **last reviewed**:2026-06-25
- **review timing**:query parameterを追加したとき、認可方針を変えたとき
- **source of truth**`app/api/support-statuses/route.ts``tests/support-statuses-api.test.ts`
- related PR:
- **superseded by**:none

古い文書は、残すべき場合と消すべき場合がある。 ADRのように判断の履歴として価値がある文書は、supersededとして残す。 一方、古い手順が実行されると危険なrunbookは、置き換え先を明示し、古い手順を目立たない場所へ退避するか削除する。 文書の保守では、残すことも消すことも判断である。

公開リポジトリに置く文書では、書いてはいけない情報もある。 ローカルの絶対パス、社内だけで通じるリンク、未公開仕様、実在する顧客情報、secret、token、Cookie、production logの生データは入れない。 ライセンスや利用許可の説明は、READMEで勝手に広げず、LICENSEへリンクする。 公開文書は「誰が読んでもよい情報」だけで作る。

文書はAIのcontextにもなる

第18章と第19章で見たように、AIの出力はcontextに強く依存する。 README、設計メモ、ADR、PR説明、runbookは、人間だけでなくAIが読むcontextにもなる。 良い文書は、AIに作業前提を渡すときの品質を上げる。 悪い文書は、AIに古い前提や曖昧な制約を渡してしまう。

AIに読ませる文書として見ると、次の点が効く。 現在有効な仕様と過去の判断を分ける。 禁止事項を書く。 未確定事項を未確定と書く。 関連文書へリンクする。 古い情報にlast reviewedやsupersededを付ける。 secretや個人情報を含めない。

たとえば、ADRに「URLに条件を残す」と書かれていても、後のADRで「複雑な条件は保存済みビューに移す」と置き換えられているなら、その関係が見えなければAIは古い判断を現在の仕様として扱う可能性がある。 文書保守は、人間のためだけでなく、AI時代のcontext管理でもある。

成果物を作る順序

この章の提出物は、doc-audience-plan.mdreadme-update-draft.mdfeature-design-note.mdadr-0001-filtering-support-status.mddoc-review-note.md である。 余裕があれば incident-report-draft.md も作る。

最初に作るのは doc-audience-plan.md である。 読者、読むタイミング、必要な情報、文書タイプ、正本、更新担当を決める。 ここで文書の役割を分けると、後のREADMEや設計メモが混ざりにくくなる。

次に readme-update-draft.md を作る。 READMEは入口なので、概要、使い方、確認方法、制約、関連文書、保守情報を簡潔に書く。 設計判断の詳細は、設計メモやADRへリンクする。

次に feature-design-note.md を作る。 第19章のfeature brief、context pack、diff review、work logから、背景、課題、制約、選択肢、採用案、影響、残課題を拾う。 AIとの作業ログをそのまま貼るのではなく、読者が判断できる形へ整理する。 根拠、未決定事項、採用しなかった案も分ける。

次に adr-0001-filtering-support-status.md を作る。 一つの判断に絞る。 「URLに絞り込み条件を残す」を扱う。 状態、背景、決めたこと、良い影響、悪い影響、中立の影響、選ばなかった案、関連リンクを書く。

最後に doc-review-note.md を作る。 AIに何を依頼し、何を採用し、何を採用しなかったかを書く。 読者、目的、再現性、判断理由、根拠、古さ、secretの有無をチェックする。

任意の incident-report-draft.md は、問題が起きた想定で書く。 実際の障害がなくても、不正なquery value、日付境界、認可漏れ候補など、学習用の小さな事例を置けばよい。

技術文書で起きやすい誤解

  • 技術文書を文章の上手さだけで評価する。読者が次に行動できるかを見る。
  • READMEにすべてを入れる。入口、判断、運用、事故対応を分ける。
  • 設計メモに結論だけを書く。背景、制約、選択肢、採用しなかった案を残す。
  • 事実、判断、推測、未決定を混ぜる。どこまで確認済みか分からなくなる。
  • 手順に実行場所と期待結果を書かない。読者が再現できない。
  • ADRを巨大な設計書にする。一つの重要な決定へ絞る。
  • ADRに良い影響だけを書く。悪い影響や中立の影響も将来の判断材料になる。
  • 古いADRを消す。置き換えたならsupersededとして残し、置き換え先を書く。
  • PR説明を差分一覧にする。背景、確認方法、レビューしてほしい点を書く。
  • 未実行確認を隠す。レビュアーが判断できなくなる。
  • runbookにコマンドだけを書く。前提、期待結果、戻し方、危険な操作を書く。
  • インシデント報告を責任追及にする。事実、影響、対応、再発防止を書く。
  • AIの推敲をそのまま採用する。事実、判断理由、制約、secretを人間が確認する。
  • 文書レビューを誤字探しで終える。読者、目的、再現性、古さを見る。
  • 公開リポジトリの文書に、内部URL、ローカル絶対パス、実データ、secretを書いてしまう。

文書タイプとレビューで確認すること

この章では、まず第19章の成果物を開く。 ai-feature-brief.md から、機能の目的、非対象、受け入れ条件を拾う。 ai-context-pack.md から、関連ファイル、既存パターン、禁止情報を拾う。 ai-diff-review.md から、実際に確認した差分、残った懸念、テスト不足を拾う。 ai-work-log.md から、AIに依頼したこと、採用した案、失敗と修正を拾う。 ai-assisted-pr-description.md から、レビュー向けの要点を拾う。 実行していない確認や、採用しなかったAI提案も拾う。

次に、これらをそのまま貼り合わせず、文書タイプごとに再配置する。 READMEには、起動と確認に必要な情報だけを置く。 設計メモには、判断の背景と選択肢を置く。 ADRには、一つの決定だけを置く。 文書レビュー記録には、AIで整えた範囲と人間が確認した範囲を置く。 incident reportには、事実、推測、判断、次にやる対応を分けて置く。

最後に、成果物同士をリンクする。 READMEから設計メモとADRへリンクする。 設計メモからPRとADRへリンクする。 ADRから設計メモへリンクする。 文書レビュー記録から対象文書へリンクする。 文書は単体で完結させるより、役割ごとに分けて接続する方が保守しやすい。

テクニカルライティングで持ち帰ること

第20章で身につけるべきことは、技術文書を、文章の装飾ではなくチームの知識共有として扱うことである。 文書を書く前に、読者、目的、読むタイミングを決める。 そのうえで、README、設計メモ、ADR、PR説明、runbook、インシデント報告の役割を分ける。

READMEは入口である。 設計メモは判断の背景である。 ADRは一つの重要な決定の記録である。 PR説明はレビューの入口である。 runbookは運用中に安全に動くための手順である。 インシデント報告は失敗から学ぶ記録である。 どれも同じ「文書」だが、読者と目的が違う。

AIは、構成案、要約、表現改善、レビュー観点の洗い出しに使える。 しかし、事実、根拠、判断理由、機密情報の扱いは人間が確認する。 AIの出力を採用したら、採用した改善と採用しなかった改善を残す。 実行していない確認は、実行済みのように書かない。 公開リポジトリへ出せない情報は、読みやすい文章になっていても削る。

文書は、未来の人間と未来のAIが読むcontextになる。 だから、古くなりやすい情報、source of truth、更新担当、last reviewed、supersededを必要に応じて残す。 実装したことを動く状態で終わらせず、後から読める判断と使い方へ変える。 それが、技術文書による知識共有である。

個人開発プロジェクトの章へ

次章では、自由テーマの個人開発プロジェクトを始める。 第20章で作った文書は、そのまま個人開発の土台になる。 誰に向けて作るのかをproject briefに書き、READMEで起動方法を伝え、設計メモとADRで判断を残し、文書レビューで説明の品質を上げる。 動くものと説明できるものをセットにすると、最終プロジェクトは単なる制作物ではなく、レビュー可能な成果になる。

参考資料

教材を検索