MAY ブランチ、スキーマがまだ要求しないがストーリーボードがアサートするレスポンスフィールド、またはベクターがリファレンス SDK を通じてプローブするのを妨げるテストインフラの癖。
エントリは、タグ付けされた @adcp/sdk または仕様リリースで修正が出荷されるまで持続します — GitHub issue のクローズは削除トリガーではありません。なぜなら、修正に先行する SDK バージョンの実装者は依然として症状に遭遇するからです。各エントリの回避策は、関連するときリリースゲートを名指しします。ここのエントリがあなたが見ているものと一致しない場合、最新の状態について GitHub issue を確認してください — 修正がまだ引いていないリリースに着地したかもしれません。
このページの使い方
ストーリーボードが仕様準拠と信じる動作で失敗する場合、ストーリーボード名またはアサーションテキストをこのページで検索してください。各エントリは、ギャップ、ブロッカーを越えさせる回避策、修正を追跡する issue を記述します。エントリは、issue がクローズされたときではなくタグ付けされたリリースで修正が出荷されたときに削除されます — 権威ある状態については、このページをリンクされた issue と SDK / 仕様リリースノートとペアにしてください。 反対方向 — このリストに ない クリーンな修正のある失敗 — については、ストーリーボードトラブルシューティングガイド を参照。現在の曖昧さ
check_governance conditions フィールド形状
- スキーマ:
check-governance-response.jsonはconditions[]アイテムを{ field, required_value?, reason }と定義し、fieldとreasonを必須とします。status: conditionsステータスは今やminItems: 1のconditionsを要求します。 - 解決: #2603。スキーマ厳格化は、このエントリの削除に続くプロトコルパッチリリースに着地します。
- 回避策(修正を引くまで): すべての
status: conditionsレスポンスで正準の{ field, reason }形状のconditions[]を発します。散文の説明に従うエージェントは既にこれをします。スキーマ厳格化は強制を機械的にするだけです。
非 OAuth エージェントに必要な PRM
- ストーリーボード:
universal/security.yamlフェーズoauth_discovery+mechanism_required。 - ギャップ: RFC 9728 / RFC 8414 プローブがデフォルトですべてのエージェントに対して実行されます。API キーのみのサンドボックスは、プローブを「通過」するために偽の発行者 URL を立てていて、それはスキップするより悪いです。
- 解決: #2606 と #5042 — ストーリーボードの物語は今や、静的認証情報のみのエージェントに、テストキットで
auth.api_keyまたはauth.basicを宣言し PRM を完全に省略するよう明示的に指示します。任意フェーズのセマンティクスがoauth_discovery失敗を致命的でなくします。mechanism_requiredは一致する静的認証情報パス経由で通過します。 - 回避策: エージェントに OAuth 発行者がない場合、
/.well-known/oauth-protected-resource/...を提供しないでください。テストキットのプローブ認証情報を有効として受け入れるようエージェントを設定します。Bearer エージェントについては、デフォルトテストキット(acme-outdoor)がdemo-acme-outdoor-v1でプローブし、エージェントは本番鍵と並んでその値を受け入れなければなりません。Basic エージェントについては、auth.basic.username/auth.basic.passwordまたはauth.basic.credentialsを持つテストキットを提供します。これはtest_kit.auth.api_keyまたはtest_kit.auth.basicのいずれかを満たし一致する静的認証情報フェーズを実行させます。それなしではフェーズがスキップされassert_mechanismがactual: []で失敗します。具体的な修正については ストーリーボードトラブルシューティングガイド — 静的認証情報エージェント: assert_mechanism を参照。
SDK 経由の冪等性 missing-key プローブ
- ストーリーボード:
universal/idempotency.yamlステップmissing_key/create_media_buy_missing_key。 - ギャップ: リファレンス
@adcp/sdkSDK が変更タスクでidempotency_keyを自動注入するため、「missing key rejection」をプローブしようとするベクターが missing key でエージェントに決して到達しません — ランナーがディスパッチ前に 1 つを注入します。 - 解決: #2607 — ステップが
omit_idempotency_key: trueを宣言し、ランナーに自身のapplyIdempotencyInvariantと SDK の自動注入の両方をスキップするようシグナルします。リクエストが鍵なしでエージェントに到着し、ベクターが拒否パスを正直にプローブできます。 - 回避策: 必要なものなし — 既存の仕様要件を尊重する(変更タスクで欠けている
idempotency_keyをINVALID_REQUESTまたはVALIDATION_ERRORで拒否)。
ストーリーボードがアサートするレスポンススキーマフィールド
- ストーリーボード:
sales_catalog_driven(カタログ数)、creative_ad_server(pricing_options)、media_buy_seller/inventory_list_targeting(property_list エコー)、creative_ad_server(vendor_cost 必須)。 - ギャップ: ストーリーボードベクターがアサートするものとレスポンススキーマが要求するものの間の歴史的ドリフト。
- 解決: #2604。監査完了:
sync-catalogs-response.jsonは今やactionがcreated/updated/unchangedのときカタログエントリにitem_countを要求。property_list/collection_listエコー:packages[].targeting_overlay経由で既に正準。list-creatives-response.jsonpricing_options: 既に正準(配列、minItems: 1、アイテムはpricing_option_idを要求)。report-usage-request.jsonvendor_cost: 既に必須。
- 回避策: すべての非失敗/非削除のカタログエントリに
item_countを発します。準拠エージェントは既にこれをします。スキーマ厳格化がresponse_schema検証でギャップを捕まえます。
ブランドプロトコルの権利保持者対広告主 brand_id
- ストーリーボード:
specialisms/brand-rights/index.yamlフェーズidentity_discovery+rights_search。 - ギャップ:
get_brand_identity.brand_idは広告主(例:acme_outdoor)を識別します。get_rights.brand_idは検索を特定の権利保持者ブランド(例:daan_janssenのようなタレント)にスコープします。同じフィールド名、異なるエンティティ — #2627 修正の前はストーリーボードが広告主 id を権利保持者フィルターに通し、準拠エージェントは空の権利を返す(失敗)か「一致なしのとき全返し」フォールバック(バグをマスク)を追加しました。 - 解決: #2627 — ストーリーボードは今や
buyer_brand(互換性フィルタリング用の広告主)を送り、エージェントが完全なカタログを返すよう権利保持者brand_idフィルターを省略します。 - 回避策:
get_rights.brand_idを権利保持者フィルターとしてのみ扱います。バイヤーのbrand.jsonに対する互換性フィルタリングのためbuyer_brandを投入します。
再キャンセルエラーコード — NOT_CANCELLABLE 対 INVALID_STATE
- ストーリーボード:
protocols/media-buy/state-machine.yaml > recancel_buyとscenarios/invalid_transitions.yaml > double_cancel/second_cancel。 - ギャップ:
specification.mdx§128(MAYNOT_CANCELLABLE)と §129(terminal-state 更新で MUSTINVALID_STATE)の両方がcanceledバイの再キャンセルに適用されました。state-machine-first の実装は §129 に従いINVALID_STATEを返し、cancellation-first の実装はNOT_CANCELLABLEを返しました。ベクターは歴史的に 1 つをピンしました。 - 解決: #2617 / #2619 + #2628 — §129 は今やキャンセルケースを切り出します: terminal-state 更新がキャンセル試行のとき、エージェントは
NOT_CANCELLABLEを返さなければなりません(MUST)。他の不正な遷移(canceled での pause/resume)は依然INVALID_STATEを返します。両ストーリーボードは今や再キャンセルでNOT_CANCELLABLEをアサートします。 - 回避策: 既に
canceledのバイへのcanceled: true更新でNOT_CANCELLABLEを返します。terminal-state バイの pause/resume でINVALID_STATEを返します。キャンセル固有のコードが再キャンセルで勝ち、汎用コードが他のすべてで勝ちます。
ブランチセットステップグレーディング(peer_branch_taken)
- ストーリーボード:
contributes_to:フラグを共有する並列optional: trueフェーズを持つ任意のもの。 - ギャップ: 準拠エージェントは 1 つのブランチ(例: 即時成功)を選びます。他のブランチのアサーション(例:
status: pending_review)は、エージェントが反対の動作を取ったため失敗します。#2629 修正の前のランナーは、any_of集計が通過してもこれをサマリーで× (unknown step)としてサーフェスしました — 実装者はいないブランチをデバッグしました。 - 解決: #2629 — ランナーは今や、選ばれなかったブランチステップをスキップ理由
peer_branch_taken(not_applicableとは別、後者はプロトコル/専門分野カバレッジギャップ用に予約)でグレードします。オーサリングルールについてはstoryboard-schema.yaml§ “Per-step grading in any_of branch patterns” を、正準のdetail形状についてはrunner-output-contract.yaml > skip_result.reasons.peer_branch_takenを参照。 - 回避策: ランナーが予期しないブランチ失敗をレポートする場合、ピア optional フェーズが同じ
contributes_toフラグに寄与したかを確認してください。そうなら、選んだブランチで準拠しています — ランナーは #2629 更新が必要です。
仕様準拠の sample_request を上書きする SDK リクエストビルダー
- ストーリーボード:
sales_catalog_drivenoptimization_loop/provide_feedback、@adcp/sdkコンプライアンスランナー経由で公開。 - ギャップ: ストーリーボードの
sample_requestはprovide-performance-feedback-request.jsonスキーマに従いperformance_index、metric_type、feedback_sourceを正しく宣言します。しかし@adcp/sdkの内部request-builder.jsに、ペイロードを非仕様のfeedback: { satisfaction, notes }形状で置き換えるprovide_performance_feedbackのハードコードされた上書きがあったため、準拠エージェントはINVALID_REQUESTで拒否しベクターに失敗しました。 - 解決: 上流 adcontextprotocol/adcp-client#689 + #2626 — 上書きを削除しストーリーボードの
sample_requestにペイロードを駆動させます。 - 回避策: adcp-client#689 修正を含む
@adcp/sdkリリースに上げます。それまで、provide_performance_feedbackベクターは、リクエストを仕様スキーマに対して検証する任意のエージェントで失敗します。