フィーチャー単位の検証マップ
すべてのコントラクトを決定論的な証拠に対応づけ、各証明が確立できないことを記録し、環境依存の未証明作業を可視化し続けるフィーチャー単位の台帳。
アーキテクチャドキュメントを証明のインベントリで締めくくる
フィーチャーのアーキテクチャドキュメントは、コンポーネントと矢印に名前を付けたところで終わるべきではない。最後に置くべきものは 検証マップ だ。コントラクトごとに 1 行を設け、それを証明する決定論的なスイートまたはゲート、その証拠の限界、そして証拠が有効になる環境を記す。検証マップはフィーチャーの証明インベントリである。レビュー担当者は「アダプターにトランスポートの seam がある」から、「まさにこのゲートがその seam を実行し、レスポンスのマッピングがドリフトすれば赤になる」までたどれる。
単位はテストファイルではなくコントラクトだ。1 つのコントラクトに複数レイヤーの証拠が必要なこともあれば、1 つのスイートが複数のコントラクトを証明することもある。コントラクトの行を書くことで、緑のスペックが並ぶディレクトリをカバレッジについての論証の代わりにできなくなる。その行には「手動でテスト済み」や「E2E でカバー」ではなく、再現可能なコマンドまたはゲートを記す。読者が証拠を見つけ、宣言されたティアで実行し、緑の結果によってどの主張が許されるのかを理解できなければならない。
最後の点が重要だ。証明には肯定的な主張だけでなく境界もある。トランスポートテストは、制御されたサービスに対するリクエストのシリアライズ、レスポンスのデコード、エラーのマッピングを証明できる。実在アカウントが認証できることや、プロバイダーが現在そのリクエストを受け付けることは証明しない。WebKit ワークフローは、ブラウザでレンダリングされるフロントエンドの経路を証明できる。同じ経路が署名済みのパッケージ版 macOS アプリケーション内で動くことは証明しない。その否定的な記述を、緑の証拠の隣の行に置こう。暗黙知として残してはならない。
検証マップの実例
あるデスクトップクライアントが外部サービスのアダプターを介してリモートドキュメントをインポートするとする。そのアーキテクチャドキュメントは、次の表で終わる。
| コントラクト | ステータス | 決定論的な証拠 | この証拠が証明すること | この証拠が証明しないこと | 環境の有効条件 |
|---|---|---|---|---|---|
| ドメインのインポートがドキュメントの順序、タイトル、安定した ID を保つ | 証明済み | 必須 PR ゲート内の test:import-domain | チェックインされたフィクスチャに対する純粋な正規化とマージの規則(不正なレコードと重複レコードを含む) | フィクスチャがプロバイダーの現在の wire レスポンスと一致すること | 固定されたフィクスチャコーパスを使用する、サポート対象の任意の Node ランナー |
| アダプターが必要な HTTP リクエストを発行し、成功・認証・quota・不正レスポンスの結果をマッピングする | 証明済み | 必須 PR ゲート内で stateful fake service に対して実行する test:external-service-transport | 実際のアダプター境界を通るトランスポートコントラクトと、名前の付いたすべての結果 | 実在アカウントのセッションが存在すること、プロバイダーに認証が受理されること、または live service に到達できること | ネットワークアクセスを無効化した hermetic な Linux CI またはローカル実行。この行に live-service run は不要 |
| ユーザーがインポートを開始し、成功とマッピング済みの失敗をフロントエンドで確認できる | 証明済み | 必須 PR ゲート内の e2e:import-webkit | フロントエンド、コマンド境界、実際のアダプター、stateful fake service を通る walking skeleton | ネイティブのパッケージング、実在アカウントのセッション、または real-service traffic | 宣言された WebKit/dev-server workflow のみ。packaged-app evidence として報告してはならない |
| 署名済みのパッケージ版 macOS アプリが実在アカウントと real service を介してインポートする | Outstanding(未証明) | 適格な実行記録なし。native- に従う | 現時点では何も証明しない。必要なレポートが添付されるまで、この行は未証明のまま | transport suites が証明するのは contract であり、real account session ではない。WebKit と dev-serve run は packaged native path を証明しない | packaged macOS + real-service traffic だけが適格。 Linux/WSL も WebKit workflow もこの行の証拠として報告してはならない。dev-serve report は無効な証拠 |
4 行目は、表の下に置く弁明ではない。マップそのものの一部だ。ステータスは Outstanding(未証明)、現在の証拠は適格な実行がないことを示し、環境の有効条件セルは代用したくなるものを名指しで拒否している。Linux の実行で real-service traffic が完全に動いても、それは有用な診断証拠にはなり得るが、パッケージ版 macOS の行を閉じるものではない。WebKit が実在アカウントに対してパスしても、ネイティブシェルを実行したことにはならない。この台帳は fail-closed だ。誤った環境から得た証拠を、未証明の証明としてラベルし直すことはできない。
Warning
証明済みの行しか含まないマップは、検証マップではない。ギャップを編集で消した成功一覧だ。設計中は、証明が存在する前にコントラクトを追加し、Outstanding(未証明) と記す。レビュー中に未証明の行を削除してよいのは、適格な証拠が得られたとき、またはそのコントラクト自体がもう存在しないという明示的なプロダクト判断があるときだけだ。近くのスイートが緑というだけで削除してはならない。
環境は証拠の型の一部である
証拠は単なる成果物ではない。条件のもとで作られた成果物だ。ティア、OS、パッケージングモード、サービスの接続先、認証情報の種類、mutation policy はすべて主張の一部になり得る。環境ティア別テストのフレームワークは、ローカル、プレビュー、本番の実行で権限と失敗の意味が異なる理由を説明している。検証マップはそのフレームワークをコントラクト単位で適用する。
レビュー担当者が解釈を挟まず、誤って提出されたレポートを拒否できるだけの厳密さで有効条件を書こう。コントラクトが「署名済みのパッケージ版アプリが real service に到達する」であるなら、「macOS で実行」は弱すぎる。Mac 上で開いたブラウザ、署名されていない debug shell、パッケージ版リリースは 3 つの異なる環境だ。live account、service target、application build、観測結果が欠けた「手動で確認」も弱すぎる。必要条件のいずれかが欠けている、または保存されたレポートから確認できない場合、その行は Outstanding のままになる。
これは、別の環境で得た証拠に価値がないという意味ではない。Linux/WSL の実行は live API と認証情報が機能することを確立できるかもしれない。WebKit の実行はフロントエンドが正しくアダプターに到達することを確立できるかもしれない。フィーチャーがそれらの主張に依存するなら、それぞれに独自の行を与える価値がある。ただし、より強い環境依存の主張のラベルを引き継いではならない。fail-closed な有効条件は、「有用なことが分かった」と「このコントラクトを証明した」の区別を守る。
Outstanding の行を手動検証手順と対にする
マップは索引であって、runbook ではない。環境依存の Outstanding 行は、native- のような兄弟の手動検証ドキュメントを指し、そこに手順とレポートのコントラクトを定義する。アーキテクチャの表は一覧できる短さに保ち、運用の詳細は、適格なマシンと認証情報を持つ人が実行できるようフィーチャーの隣に置く。
その companion document には、次を記す。
パッケージングや署名の要件を含む、使用必須のアプリケーション成果物と環境。
実行を許可されたアカウントとサービスティア。シークレットは参照するだけで、レポートにコピーしない。
セットアップ、操作、期待する観測、クリーンアップ、必要な mutation fence。
保存する証拠 -- build identity、platform、timestamp、service target、outcome、scrub 済みの screenshot または log。
無効な代用品。この例では、dev serve から作られたレポートは有効な証拠ではない。Linux/WSL と WebKit workflow も同様である。
また、その手順は実行が判定に到達できない場合の扱いも定義する。認証情報がない、利用可能なマシンがない、レポートを読めない、cleanup が中断された、といった状態を pass に変えてはならない。マップの行は Outstanding のままにし、理由を別途記録する。手順によって将来の証明を再現可能にはできるが、手順が存在するだけでは何も証明しない。適合する実行記録だけが行のステータスを変える。
2 つの fail-closed スケール
Fail-Closed Live Proofs and Evidence Contracts が統制するのは、1 回の live proof だ。execution、evidence completeness、recovery を分離し、成果物の欠落や曖昧な終了を成功した実行として報告できないようにする。検証マップが統制するのは、より大きな問い、すなわち フィーチャーにどの証明がそもそも存在するのか だ。
2 つの統制は異なるスケールで機能する。
live-proof contract は、1 回の実行が証拠で支えられない判定を主張するのを防ぐ。
verification map は、緑の実行群が、実際には持っていない feature coverage を主張するのを防ぐ。
両者を合わせることで、よくある報告上のギャップを閉じられる。完全に fail-closed な transport suite が緑でも、real-account native behavior は未証明のままかもしれない。逆に、正しく名付けられた Outstanding 行が、個々の実行では不完全な証拠しか残さない live procedure を指していることもある。per-proof contract がその実行を判定し、適格な実行が 1 つ現れるまで feature ledger が未証明集合を露出し続ける。
マップを生きた状態に保つ
コントラクト、実行環境、必須ゲートのいずれかが変わるたびにマップをレビューする。プロバイダーの結果を追加するなら、実装が入る前に行を追加または拡張する。テストをパッケージ実行から dev server に移したなら主張が変わり、native の行を再び開く必要があるかもしれない。CI gate を削除したなら、それに依存していたすべての行は、代わりの証拠が存在するまで Outstanding になる。コマンド名の変更はドキュメントのドリフトであり、環境を黙って弱めることはカバレッジのドリフトだ。
有用なレビューの問いは「テストは緑か」ではない。「このフィーチャーのすべてのコントラクトについて、どの決定論的な証拠がその主張を獲得し、その証拠は何を証明せず、どの行がまだ Outstanding なのか」だ。アーキテクチャドキュメントが推論なしに答えられるなら、緑はチームが語る意味だけを持つ。それ以上ではない。
証拠の有効条件と退役
既存記録から、契約ごとの関連入力・環境条件と証拠の出所を辿れるようにします。入力、テスト、fixture、依存、設定、runtime・browser、live外部条件の変化で該当証拠を失効させます。ソースSHAだけでは不十分です。変更範囲に応じた検証が有効な再利用と入力不明時の安全側の再実行を定義します。
検知の置換・退役はライフサイクルに従います。現役契約のうち十分な証拠を失うgapだけを戻し、十分な部分はProvenを維持します。終了した契約はサポート判断を記録して現役mapから外せます。受容した未検証リスクは未検証と明示し、受容だけでProvenにしません。