[🛠] Operations Automation #4: 文書更新を減らしながらstaleな状態を防ぐ構造
✨ GPT-5.6 Solの要約
複数の文書へ状態変更を繰り返し書く方式をやめ、変動する状態の単一owner、条件付きdownstream更新、phase checkpointへ文書更新の流れを整理し直した記録。
文書を最新にするほど、現在の状態が食い違った
長い作業がcompactionされたり、別のsessionへ引き継がれたりした後、古い文書に書かれた次の作業を現在の状態だと誤認することがあった。この問題を防ぐため、しばらくの間は状態が変わるたびに、関連していそうな文書をすべて更新していた。
README、文書router、requirements、current-direction文書、Runbook、TODOに、同じ完了情報と次の作業を繰り返し書いた。更新漏れがなければ安全だと思っていた。
だが、一つの状態変更を六か所に書いた瞬間から、その六か所を常に同じ内容に保たなければならなくなった。ある文書はdeploy前の状態で止まり、別の文書には実機検証まで終わったと書かれていた。多くの文書を更新することはstaleな状態を防ぐどころか、新しいstaleな状態を生み出した。
小さな検証が一つ終わるたびに複数の文書を直し、commitまで残したため、Git historyも細切れになった。実装がどこで終わったかより、文言を何度同期したかのほうがよく見える状態だった。
変動する状態は一つの文書だけが所有するようにした
問題は文書の数ではなく、同じ事実を複数の文書が所有していることだった。そこでまず、事実の種類ごとにownerを一つだけ決めた。
| 変わった事実 | owner | 他の文書を更新する条件 |
|---|---|---|
| 現在のRuntime、blocker、phase、次の作業 | canonical current-state snapshot | 他の文書へコピーしない |
| 安定した製品判断、禁止した回避策、active Goal | current-direction文書 | 製品判断やGoalそのものが変わったときだけ |
| 動作、データ、権限、acceptance | requirementsまたはcontract | ユーザー・システムの動作契約が変わったときだけ |
| 運用手順、gate、rollback、recovery | Runbook | 運用者が従う手順が変わったときだけ |
| 文書の関係、製品stage、実行entry point | READMEまたはrouter | 探索経路や製品の関係が変わったときだけ |
| 詳細なcommand、log、worker検証 | report、artifact、Git evidence | aggregate文書には結論と根拠linkだけを残す |
重要なのは、「関連がある」と「所有する」を分けることだ。deployが終わったからといってrequirementsを変える必要はない。deploy過程で運用rollback手順が変わったならRunbookを更新し、動作契約まで変わったなら、そのとき初めてrequirementsを更新する。
READMEとrouterも、現在のrevision、端末の状態、次の作業を追いかけない。何をどこで読み、どこから実行すべきかだけを安定して指し示す。
即時更新とdurable checkpointを分けた
単一ownerにしたからといって、文書更新をphaseの終わりまで遅らせるわけではない。新しい根拠が得られたり、Runtimeの状態、blocker、優先順位、次の作業が変わったりしたら、canonical current-state snapshotは次の実装へ進む前にすぐ更新する。そうすれば、途中でcompactionやhandoffが起きても、次のsessionは一か所から実際の状態を復元できる。
一方、状態が一行変わるたびにcommitを作ることはしない。独立してreviewし、再開できる境界でだけcurrent-stateを一度確認し、checkpointを作る。
- 実装が完了したとき
- deployと事後検証が完了したとき
- 実機・ユーザーentry pointのE2E結果が出たとき、またはblockerが確定したとき
- interruptionやhandoffによって作業を引き継ぐとき
即時更新はresumeの安全性のためにあり、phase checkpointは変更のまとまりをreviewし、元に戻せるようにするためにある。両方を同じルールで扱ったため、micro-event commitが増えていた。
commit権限がない作業では、さらに単純だ。reviewが終わったという理由でCOMMITTEDやCLOSEDの状態を作らない。統合候補をfreezeした状態で維持し、実際のcheckpointができるまではdurableな完了として記録しない。
worker検証はreportに残し、aggregate文書から外した
並列作業では、workerごとに実行したcommand、検査結果、重なったhunk、残った制約が生じる。これらをroot TODO、README、requirementsへ書き戻すと、coordinatorが読まなければならない文書が増えるだけだ。
worker単位の詳細な根拠はimmutable reportとGit diffに残し、current-stateには統合された結論、現在への影響、根拠へのpathだけを置く。coordinatorはreportを一つずつreviewするが、report一つをcommit一つとして扱わない。同じphaseを構成する複数のreportは、統合検証の後に一つのcheckpointを共有できる。
この区別により、aggregate文書は短くなり、詳細な検証も失われない。次のsessionは現在の状態を先に読み、判断の根拠が必要なときだけ、linkされたreportとGit evidenceをたどる。
resume順序がownerルールに反していた
ルールを整理した後、フロー全体を改めて確認すると、意外なほど基本的な矛盾が見つかった。開始手順がREADMEを先に読み、その後でtodo.mdを読む順序になっていた。
READMEには変動する状態を複製しないと書いているのに、実際のresume手順ではcurrent-stateより先にrouterを読んでいた。古い状態の文言が残っていれば、最初の判断から誤った方向へ進む可能性があった。
そこで開始順序を変えた。最初にcanonical current-stateで、現在のRuntime、blocker、phase、次の作業を確認する。その後でREADMEと文書routerからrepositoryの境界と必要なleaf文書を探す。安定した製品判断はcurrent-directionから、実際の動作契約はrequirementsから読む。
文書ownerの表を追加するだけでは足りなかった。読むのが人でもAgentでも、実際に読む順序がowner関係に沿っていなければならない。
現在の適用範囲と残る限界
この構造は、共有作業ルール、Operations Automationの文書routing、変更文書化manifest、並列coordination protocolへ反映した。skill validator、文書同期検査、diff検査は通過した。ただし、現在の変更はまだlocal working treeにあり、commitもdeployもされていない。
既存文書のすべてをさかのぼって書き直したわけでもない。過去の記録と詳細reportはそのまま残し、active文書で同じcurrent-stateの事実が衝突するときだけ、ownerへの参照へ縮める方式だ。古い文書が残っていることより、それを現在の作業のauthorityとして読み直さないようにすることを先にした。
今では、文書の最新化を何か所更新したかでは判断しない。compactionやhandoffの後、一か所を読むだけで現在のphaseと次の作業を間違えずに復元できるか、詳細な根拠が必要なときにもう一度追跡できるかが基準だ。
コメントする