FLARES LLC

Technical document

検証・デプロイ・監視・自動復旧を一つの経路にして、機能開発へ集中する

機能開発が遅れる理由は、書く量が足りないことより、直す場所と出す手順が毎回別になることにあります。仕様の抜け、設定の食い違い、大きなPR、デプロイと公開が同じ操作、本番のエラーを人が拾って戻す。この摩擦を一つの変更が通る経路へ接続し、CUEとBazel、QuintとApalache、トランクベースとStacked PR、機能フラグ、Sentry、スケジューラによるオートヒールの役割を分け、順番を固定することが、当社の開発標準です。道具の数を増やすこと自体が目的ではなく、バグ修正とデプロイの手作業を減らし、人が見る対象を、業務の意味と例外の判断へ戻すことです。
開発基盤 / 運用設計約18分公開日 2026年8月30日更新日 2026年8月30日
仕様と検証、小さく載せる、監視、自動復旧を一本の経路としてつなぐ開発基盤のイラスト

Summary

この文書の要点

  • 静的な契約はCUE、動的な不変条件はQuint、検査はApalache、実行はBazelです。コードを厚くしてから論理バグを探す、という順にはしません。
  • 変更は小さく積み、トランクへ頻繁に載せます。公開の可否は機能フラグで分け、デプロイとリリースを同じ操作にしません。
  • 本番のエラーはSentryで捉え、閾値を超えたらフラグを閉じる、Issueを残す、再検証する、という退避を先に置きます。自動修正は、その後ろです。
  • 学習コストは高いです。核の状態遷移と、戻せる公開から先に接続し、全部を一度に入れません。

1. 機能開発に集中する、とは手作業を無くすことではない

開発者がビジネスロジックだけを書けばよい、という言葉は、確認を捨てる意味では使いません。確認の場所を、人の記憶と大きな差分から、契約、モデル、小さなPR、フラグ、監視へ移す、という意味です。

トイルになるのは、次のような繰り返しです。設定ファイルのキーが環境ごとに違う。決済の再実行で二重計上しない、という条件がコメントにしかない。機能が一つの巨大なPRに入り、レビューも戻しも重い。本番へ出した瞬間に全利用者へ届く。エラー通知を見て、人がフラグも戻しも判断する。

これらは、それぞれ別の文書で扱ってきました。型と制約はCUEとBazel、状態遷移はQuintとApalache、ビルドの速さと費用、Sentry起点の自動復旧。本稿は、それらを一つの経路として接続したときの順番と、境界を整理します。

  • 人が判断する: 契約の意味、新しい状態、公開してよいか、例外を正本へ上げるか。
  • 機械が先にやる: 検証、生成、差分テスト、小さな統合、フラグの閉じ、証跡の保存。
  • 残してはいけない: 大きなPRのままの本番投入、デプロイと公開の同一視、監視のない自動修正。

2. 経路の全体像

一つの変更は、次の順で流れます。途中で落ちたら、下流へ進みません。

上流で止まった欠陥は、CUEかQuintへ戻します。下流の本番で見えた抜けも、フラグを閉じたあと、同じ正本へ還流します。自動で直した差分を、生成物や本番設定へだけ残す運用はしません。

検証・デプロイ・監視・自動復旧の経路
flowchart TB
  subgraph SPEC["仕様と検証"]
    CUE["CUE:契約・設定・フラグのスキーマ"]
    QNT["Quint:状態遷移・不変条件"]
    APA["Apalache:モデル検査"]
    BZL["Bazel:生成・検証・テスト"]
    CUE --> QNT --> APA --> BZL
    APA -->|反例| CUE
  end
  subgraph SHIP["小さく載せる"]
    SPR["トランクベース + Stacked PR"]
    FF["機能フラグ:デプロイと公開の分離"]
    BZL --> SPR --> FF
  end
  subgraph RUN["本番"]
    PRD["本番"]
    SEN["Sentry:エラー検知"]
    FF --> PRD --> SEN
  end
  subgraph HEAL["退避と還流"]
    SCH["スケジューラ"]
    OFF["フラグOFF / 影響の最小化"]
    ISS["Issue起票"]
    FIX["再検証・修正PR"]
    SEN --> SCH --> OFF
    SCH --> ISS
    SCH --> FIX --> BZL
    OFF --> CUE
  end

3. Quint / Apalache と CUE / Bazel:出す前に論理を止める

形式検証と契約の正本は、別文書「CUE・Quint・Apalache・Bazelを一つのパイプラインにした開発標準」が担当します。ここでの役割は、デプロイ経路の入口になる、という一点です。

Quintは、認証、決済、再実行、障害復旧のように、時間と並行で壊れる振る舞いをモデルにします。Apalacheは、指定した手数の範囲で不変条件を調べ、反例があれば実装の前に返します。CUEは、データ構造、設定、許可された遷移、機能フラグのスキーマを静的に検証します。Bazelは、`cue vet`、`quint verify`、生成、テストを依存グラフで回します。

この層が弱いと、トランクベースも機能フラグも、壊れたロジックを速く配る装置になります。速さの前に、破ってはいけない条件を正本へ置きます。

  • QuintとApalacheは実装バイナリを検査しません。モデルを検査します。
  • CUEに状態機械の全経路を書かせません。フラグ名とスキーマ、許可遷移はCUE、実行経路はQuintです。
  • Bazelは不変条件を定義しません。検査の実行と再現を担当します。

4. トランクベースとStacked PR:変更を、レビューできる大きさへ割る

大きな機能を一つのPRに載せる運用は、衝突と待ちを増やします。当社はトランク(main)へ頻繁に統合し、変更は依存関係のある小さなPRの積み重ねとして扱います。レビューとCIは、その単位で回します。積み重ねの管理にはGraphiteを使い、GitHubをリポジトリの正本とマージキューにします。

小さく割る目的は、見た目のPR数を増やすことではありません。失敗したときの戻し範囲を、その一段に閉じることです。形式検証とBazelの差分テストは、この粒度と相性がよいです。契約かモデルか実装の、どこが壊れたかをターゲットのラベルで指せます。

一方で、小さく割っただけでは、未完成の機能が本番の利用者へ届きます。次の層、機能フラグが必要になる理由です。

  • 統合先はトランクです。長寿命の機能ブランチは標準にしません。
  • 一つのPRに、契約変更と画面とインフラを混ぜません。
  • CIの回転を上げるために検査を外す、という順にはしません。核の `quint verify` と契約検証は残します。

5. 機能フラグ:デプロイとリリースを分ける

コードをトランクへ載せ、成果物を本番へ配ることと、利用者へ機能を見せることを分けます。フラグが閉じているあいだ、その経路はデプロイ済みでも公開ではありません。

フラグの名前、型、既定値、対象の環境はCUEのスキーマで管理します。本番の設定ファイルへ、その場でキーを足す運用はしません。キルスイッチとして使うフラグは、初期値と閉じたときの振る舞いを、仕様の一部として置きます。閉じたあと何が残るか、何が消えるかを曖昧にすると、自動退避が別の障害になります。

フラグは増やすほど、組み合わせがテストできなくなります。長期の「一応残しているフラグ」は、契約の肥大と同じです。公開が終わったフラグは消す期限を持ちます。

  • デプロイ: 成果物を本番の実行環境へ置く。
  • リリース: フラグを開き、利用者へ届ける。
  • 退避: エラーが閾値を超えたら、該当フラグを閉じる。バイナリの巻き戻しより先に、影響範囲を閉じます。

6. Sentry とスケジューラ:先に閉じ、あとで直す

本番のエラーはSentryで捉えます。スタック、リリース、フラグ状態、どの変更かを残します。通知を人が読むだけの運用にはしませんが、最初の自動操作は修正ではありません。影響の最小化です。

スケジューラは、決めた閾値を超えたときに動きます。優先順は次です。

1. 該当機能のフラグを閉じる。障害の広がりを止める。

2. Issueを残す。再現の文脈、フラグ名、関連するBazelターゲット、Quintの不変条件があればその名前。

3. 必要なら再ビルドや検証を回す。修正用のPRは、証跡と検証を通したものだけを提案する。

自動でコードを直して本番へ載せる経路は、別文書のオートヒール設計に詳しいです。本稿での約束は、キルスイッチと証跡が先、自動修正は後、という順を崩さないことです。停止条件のない自動修正は、壊れた変更を速く配ります。

  • 自動にしてよい: フラグOFF、Issue起票、対象テストの再実行、影響範囲の記録。
  • 人が残る: 契約の意味が変わる修正、金銭と認可、フラグを再び開く判断。
  • やってはいけない: 監視の無い自動マージ、生成物だけの修正、閉じ方の決まっていないフラグの自動操作。

7. 接続したときに起きる相乗効果

各層は、単体でも意味があります。接続すると、次の循環ができます。

Quintの反例は、CUEの遷移表かフラグの前提の更新として戻ります。Stacked PRは、その更新を小さな一段としてレビューできます。フラグは、検証を通したコードを本番へ先行して置き、公開だけを遅らせます。Sentryのエラーは、どのフラグとどのリリースかを持ってスケジューラへ渡り、閉じたフラグの名前が次のQuintとCUEの材料になります。

この循環があると、夜間の障害対応は「全部戻すか、全部残すか」ではなく、「該当の公開を閉じ、証跡を残し、翌朝に正本へ戻す」になります。開発者の集中先は、画面の応急より、破ってはいけない条件と、次の小さな変更です。

一方で、循環のどこかが飾りだと、全体が信用を失います。フラグがスキーマ外なら、キルスイッチは動きません。Issueにフラグ名が無ければ、閉じた理由が翌日残りません。モデルが現実の障害を省略していれば、検査の緑は偽の安心です。接続は、各層の入力と出力の名前を揃える作業でもあります。

8. 入れ方と、入れすぎない範囲

学習コストと初期の構築コストは、無視できません。一気に全部を「完成形」として入れると、チームの作業が道具の接続そのものになります。当社の標準でも、適用範囲は核から広げます。

既存の型生成、CIの費用、オートヒールの停止条件は、それぞれの文書の方針を引き継ぎます。本稿が足すのは、それらを「機能開発へ戻すための一本の経路」として扱う、という位置づけです。

  • 先に置くもの: 金銭、認可、再実行、テナント境界など、破れると損害が大きい状態遷移のQuint。
  • 先に置くもの: フラグのスキーマと、閉じたときの振る舞い。
  • 先に置くもの: Sentryのエラーをリリースとフラグへ結びつけること。
  • 先に置くもの: 閾値を超えたときのフラグOFF。
  • 後でよいもの: 画面の細部までのモデル化。
  • 後でよいもの: 全エラーの自動PR。
  • 後でよいもの: フラグの大量追加。
  • 後でよいもの: 検査範囲を広げただけの `quint verify`。

9. 自社での採用方針

これが、検証から公開、障害、還流までの標準です。案件ごとに監視とデプロイの道具を選び直すのではなく、この順を既定にします。外す場合は、既存資産、法令、運用体制の理由を設計記録に残します。

標準を固定することは、将来の変更を禁止することではありません。変えるときに、どの層の入力と出力がずれるかを説明できるようにすることです。

  • CUE / Quint / Apalache / Bazel: 仕様と検証の正本と実行。詳細は形式検証の文書。
  • トランクベースとStacked PR: GraphiteとGitHub。小さく統合する。
  • 機能フラグ: デプロイとリリースの分離。スキーマはCUE。キルスイッチは初期値と閉じたあとまで定義する。
  • Sentryとスケジューラ: 検知、フラグOFF、Issue、再検証。自動修正は停止条件の内側だけ。

10. まとめ:速く出すことと、先に止められることを同じ経路へ置く

CUEとQuintは、何が許され、どう遷移してよいかを先に定義します。Bazelはその検査を毎回同じ順で回します。Stacked PRは変更をレビューできる大きさへ割ります。機能フラグは、載せることと見せることを分けます。Sentryとスケジューラは、壊れた公開を先に閉じ、理由を正本へ戻します。

この構成を、完成した理想として飾る必要はありません。接続が途切れると、速さだけが残ります。順番を保てるなら、バグ修正とデプロイの摩擦は減り、人は機能の意味と、例外を正本へ上げるかどうかに戻れます。それが、機能開発へ集中する、という標準の中身です。

Technical documents

技術文書を増やしていきます。

AI、クラウド、業務アプリ開発、要件定義、運用設計に関する考え方を、今後も文書として整理します。

技術文書一覧へ