devAlice
← Alice の使い方

11. Release gates — 「完了」が事実になる線

Release gate とは何か、なぜゲートなしでは「完了」が腐るか、Auto-Gate と Manual-Gate の分離、累積ゲートパターンの実戦、lint+build+test が通過したのに成果物が42項目足りなかった日、そして運営者が約束を証明の代わりにさせない方法。

第10回 — PRD は一文で終わった。PRD は到達点を記述する。

この記事は運営者がどう到達したかを知る方法についての記事だ。

Release gates。「完了」を感覚から事実に変える、具体的・原子単位・機械検証可能な条件たち。ゲートがなければ PRD は願いだ。あれば、マイル標識の打たれた道になり、各標識を運営者の自信以外の何かが検証する。

0. 出発前提 — 「完了」は最も高価な単語だ

第7回 — 検証ループ はこの主張を コード レベルでした。運営者が「終わった」と感じる瞬間、報告が出る前に lint・ビルド・テストが自動で回る。その動きが壊れやすい単語 — 「完了」 — を運営者の記憶からシステム強制へと移す。

Release gate は同じ動きだ。一段上で。

コードレベルで「完了」は この一切れがコンパイルされ、テストが通る という意味だ。Release レベルで「完了」は システムがライブになる資格がある という意味だ。二つは同じ単語ではないし、同じメカニズムで強制することもできない。

テストが通っても privacy policy が存在することは教えてくれない。ビルドが通っても OAuth redirect URI が whitelist に入っていることは教えてくれない。lint が綺麗でも運営者の実名がメタデータの全レイヤーから掃除されたことは教えてくれない。それらの問いは別のゲートのものだ。

1. Release gate が実際に何か

Release gate は だ。

表の各行は一つの原子単位・外部検証可能な条件だ。各行に状態がある。

  • ✅ 通過 — 検証済み、現在この行は成立している
  • ⏳ 進行中 — 作業中、まだ成立していない
  • 🔒 運営者待ち — 人間にしかできない段階で塞がっている (Dashboard クリック、アカウント登録、DNS 変更)
  • ❌ 未着手 — 既知の要求、動きなし
  • 該当なし — 推測で追加された行で状況上意味を失った

表は PRD の一部だ。別ドキュメントに住まない。理由は第10回 §4 と同じだ — 道の形が到達点ドキュメントに組み込まれて いる。「何が完了としてカウントされるか」を聞く人がいなくなる。ドキュメントが答える。

ゲートは 累積 だ。Gate 1 は Gate 0 が通過した状態を前提にする。Gate 9 は 0〜8 が通過した状態を前提にする。順序は好みではなく依存だ — ドメインなしでサービスをライブにできないように、コンプライアンス (Gate 1) なしでインフラ (Gate 2) を通過することはできない。

Release gate はチェックリストではない。意図と実在の間の契約だ。

2. Auto-Gate と Manual-Gate

すべてのゲート行が同じ種類ではない。二つあり、違いが重要だ。

Auto-Gate 行 は機械が検証できる条件だ。例:

  • pnpm build が 0 で終了
  • pnpm lint が 0 で終了
  • pnpm test が 0 で終了
  • grep -r "operator-real-name" . が何も返さない
  • curl -I https://devalice.jaceclub.com が 200 を返す
  • verify:assets スクリプトが 15/15 SHA-256 一致を報告

行が 0 または非 0 で終了するシェルコマンドで表現できるなら Auto-Gate 集合に属する。システムは毎 commit、毎 push、毎晩の cron で発動できる — 運営者が起きていなくても。

Manual-Gate 行 は人間にしか決められない条件だ。例:

  • 「Privacy policy が両言語で正しく読める」
  • 「リードが M2 マイルストーン定義を承認する」
  • 「シードコンテンツが5つの別個のユーザー痛点をカバーする」
  • 「OAuth スコープが信頼レベルに対して適切に見える」
  • 「Lighthouse 'Best Practices' の指摘が受け入れ可能な trade-off だ」

これらの行は人を待つ。ゲートで 自動化できない 部分であり、自動化できるふりをするのが release 事故の大半の源だ。

規律:

規律理由
すべての Auto-Gate 行にスクリプトがあり — CI がそれを回すそうでなければ行は紙の上にあって実在にはない
すべての Manual-Gate 行は 誰が 承認するかを明示 — ただ「approved」ではないそうでなければ誰も承認していないまま通過としてカウントされる
Auto と Manual は表で 視覚的に区別 される運営者がどちらかを覚えなくてよいべきだ
Manual 承認は痕跡を残す (commit、comment、PR review)記憶は腐る。commit は腐らない。

3. 累積パターンの実戦

実プロジェクト — devalice — の実形のゲート表、短縮版:

Gate 0: M0 ローンチ (一時ドメイン)
  - pnpm build 通過           [Auto]   ✅
  - Vercel preview デプロイ   [Auto]   ✅
  - カテゴリルート × 4         [Auto]   ✅
  - シードガイド × 4           [Manual] ✅ (リードレビュー 2026-05-10)
  - ESLint clean              [Auto]   ✅
  - Vercel env vars 設定      [Manual] 🔒 (運営者)

Gate 1: コンプライアンス
  - Privacy Policy (ko + en)  [Manual] ✅
  - コンテンツライセンス (CC BY) [Auto] ✅ (ファイル存在、ヘッダーテキスト一致)
  - コードライセンス (MIT)    [Auto]   ✅
  - About ページ存在          [Auto]   ✅
  - クッキー通知 (PIPA)       [Manual] ✅

Gate 2: インフラ
  - 独自ドメイン接続          [Manual] 🔒
  - SSL 有効                  [Auto]   — (Gate 2 行 1 に依存)
  - プロダクション env 分離   [Manual] 🔒

Gate 3: セキュリティ
  - シークレットのハードコード無し [Auto] ✅ (grep)
  - .env.example 完備         [Auto]   ✅
  - RLS 有効                  [Manual] 🔒 (DB push 待ち)
  - OAuth redirect whitelist  [Manual] 🔒
  - 入力検証                  [Auto]   ✅
  - 資産 SHA-256 一致         [Auto]   ✅ (verify:assets 15/15)

...

散文ができない三つをこの表がやる。

状態が一目で見える。 列を眺める。✅ の数 vs 🔒 の数を数える。絵が即座に立ち上がる。「どこまで来たか」を知るために三段落の散文を読まなくてよい。

Blocker が自ら浮き上がる。 Gate 2 の 🔒 行は次に起きなければならないことだ。表が運営者・リード・次のセッションに、何を最初に見るべきかを語る。

ゲートが自ら順序づける。 「出荷するか?」は「Gate N の最後の 🔒 は解除されたか?」に縮む。タイミングについての議論は始まる前に終わる。

4. 「完了」が嘘だった日 — コードで強制されないゲートの代価

この話は誰かが「なぜここまでするのか」と聞くとき、運営者が戻ってくる事例だ。

別のプロジェクト — Track D と呼ぼう — で、4 つの sub-phase が数週間にわたって順次出荷された。D-0、D-1、D-2、D-3。各段階の最後に「success」と報告された。lint 通過。build 通過。cargo test 通過。Lighthouse スコアも問題なし。チームリードは報告を読んで次に進んだ。

数週間後、定期監査の中で、実際の成果物が 4 つの sub-phase にまたがって 42 項目足りないことが分かった。バグではない — 構造的な約束が欠落 していた。spec が存在すると言った UI primitive 4 種類がまだ接続されていなかった。spec が分解されると言ったキュー状態 8 個が分解されていなかった。spec が削除されると言ったファイル 7 個がツリーに残っていた。spec が除去されると言った legacy バックエンドハンドラ 9 個がまだ呼ばれていた。

どうしてこんなことが起きたのか?すべての報告は正直だった。成果物はコンパイルされた。テストは通った。報告者 — この場合は委任されたエージェント — は何かが間違っているという信号を受け取る術がなかった。

理由は単純だ。spec の約束は散文だった。コードで強制されていなかった。 「spec が UI primitive 4 種類を名指した — ツリーに UI primitive 4 種類が存在するか?」を発動するチェックがなかった。「spec がファイル X が削除されたと言った — ファイル X は消えたか?」を発動するチェックがなかった。検証ハーネスはコンパイルを検査し、約束を検査しなかった。

修正は誰もやりたくなかった sub-phase だった: D-Catchup。戻る。各約束をツリーに対して検証する。欠落したものを接続する。消えるべきだったものを削除する。そして — ここが長持ちする変化だ — 以降のすべての委任に verify:d-N スクリプトを追加 し、マージゲートに据える。次の 4 つの sub-phase が嘘をつきたくても付けないように。

教訓はこれだ:

約束は release gate ではない。コードで強制された約束が release gate だ。

D-Catchup 以後、そのプロジェクトの全ての委任は同じ PR に三つを受け取る。

  1. 委任書 — 何を、なぜ、どのように
  2. verify:phase-N.mjs スクリプト — すべての約束を巡回し、欠落時に非 0 で終了
  3. CI ルール — pnpm run verify:phase-N が 0 で終了しなければマージをブロック

委任単位の release gate だ。PRD の M0〜M10 ゲートと同じ形、より小さい単位に適用しただけ。

5. verify スクリプトの形

verify スクリプトは意図的に小さく単純だ。テストフレームワークではない。文字通り walker だ。

spec の各行ごとに一ブロック:

// 行 D-1.3 — キューは 8 個の状態に分解されなければならない
const queueStates = readQueueStates();
if (queueStates.length !== 8) {
  fail("Queue has " + queueStates.length + " states, expected 8");
}

三つの性質が重要だ。

spec と 1:1。spec の 3 行目はスクリプトの 3 番目のチェックになる。spec に行が追加されると、チェックが追加されるまでスクリプトは通らない。二つのドキュメントが歩調を合わせて動く。

出力が領収書。報告者は「検証した」と言わない。raw stdout を貼る。verify:d-1 passed 18 / 18。その行が報告にないなら報告は受理されない。

失敗はうるさく具体的。「Queue has 5 states, expected 8」が「verify failed」に勝つ。運営者はスクリプトを開かなくても何が欠けているか分かるべきだ。

スクリプトは手書きだ。生成されない。フレームワークが作らない。運営者が spec を読んだ結果をコードで表現したもの、マージゲートの上に座っているものだ。

6. Manual-Gate 行 — 正直に保つ方法

Auto-Gate 行は正直に保ちやすい。CI がチェックを回し、通過するか失敗するかだ。Manual-Gate 行で規律が現れる。

運営者が使うパターン:

すべての Manual 行は承認者を名指しする。「チームが承認」ではなく、役割と日付を名指しする。Manual ✅ lead, 2026-05-10。承認者が変われば、新しい承認者が再承認するまで行は ⏳ に戻る。

Manual 行は commit の痕跡を残す。⏳ から ✅ に行を裏返す commit は、メッセージに承認者の名前と何をレビューしたかの一行メモを含む。[devAlice] chore(gate-1): privacy policy ko/en — lead approved。6 ヶ月後に誰かが「待て、これを誰が OK と決めたんだ?」と聞いたとき、git log が答える。

Manual 行は明示的な再レビュー周期を持つ。M0 で承認された privacy policy が永遠に承認されたわけではない。PRD が再レビュートリガを名指しする — M2 ローンチで再レビュー または 二四半期ごとに再レビュー。トリガが発動すると、行は再確認されるまで ⏳ に戻る。

Manual 行は「そのうちやる」を状態として使わない。担当者と締切があるか、❌ か。どちらか。

7. 落とし穴

Release gates は予測可能な仕方で崩れる。

7.1 大きくなるばかりで閉じないゲート

Gate 3 の表が二四半期にわたって行を積み上げ続け、すべての行が ✅ になる瞬間が一度もない。それはゲートではなく wish list だ。分割せよ。non-blocking な行は「Gate 3 part B」になるか、「ローンチ後追跡」に降格される。ゲートの目的は 閉じる ことだ。

7.2 チェックなしで通過するゲート

ある行が Auto ✅ と書かれているのに、それを検査するスクリプトがどこにもない。2 週間後、その行は全く通っていないのに誰も知らない。すべての Auto 行には実行可能なチェックが必要で、その名前が行にあるべきだ。 チェックが存在しなければ、行は ✅ ではなく ❌ だ。

7.3 ゲートにならなかった約束

D-Catchup のパターンだ。spec が X が真になると言う。X が真か検査するものがない。報告者は 自分が 検証したもの — ビルド、テスト、lint — について正直だ。誰も検証しなかったものが壊れる。spec で約束する価値のあるものはゲートにする価値がある。

7.4 「口頭で起きた」Manual 承認

ある行が Manual ✅ なのは、3 週間前のセッションでリードが「良さそう」と言ったからだ。git に記録されたものはない。次に誰かがなぜ通過なのか聞いたとき、痕跡はない。すべての Manual 承認は commit または PR review を残す。repo になければ起きていない。

7.5 「プロダクションでテストする」ゲート

ある行が pending — ローンチ後検証 となっている。それは release gate ではなく、待機中の post-mortem だ。ローンチ前に検証可能か (⏳ に移して検証)、ローンチ基準でないか (別の「ローンチ後追跡」セクションに移動)。どちらか。

8. 一つの原則

Release gates の全体の形は一行に縮む。

「運営者の意図が『完了』として扱いそうなものはシステムに先に検査させる。システムが検査できないものは、やった人の名前を書く。」

Release gates は PRD が願いをやめて契約になるレイヤーだ。Auto-Gate 行は機械が強制する契約だ。Manual-Gate 行は痕跡を残した名指しの人が強制する契約だ。その組み合わせが、運営者が一切れを ライブ と言うときに意味するものだ。

そしてひとたびゲートが実在すれば — すべての行が 0 で終了するスクリプトか、git に記録された人間の承認になれば — 日々の作業の大半は運営者がキーボードに居る必要がなくなる。それが 第12回 — Ralph loop についての記事だ。PRD が何を作るかを言い、ゲートがいつ作られたかを言い、ループがその間の道を 24/7、運営者が眠っている間にも自ら歩む。