@adcp/client 4.22.1 → 4.23.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (65) hide show
  1. package/dist/lib/index.d.ts +1 -1
  2. package/dist/lib/index.d.ts.map +1 -1
  3. package/dist/lib/index.js.map +1 -1
  4. package/dist/lib/testing/compliance/comply.d.ts +22 -5
  5. package/dist/lib/testing/compliance/comply.d.ts.map +1 -1
  6. package/dist/lib/testing/compliance/comply.js +242 -276
  7. package/dist/lib/testing/compliance/comply.js.map +1 -1
  8. package/dist/lib/testing/compliance/index.d.ts +1 -0
  9. package/dist/lib/testing/compliance/index.d.ts.map +1 -1
  10. package/dist/lib/testing/compliance/index.js +6 -1
  11. package/dist/lib/testing/compliance/index.js.map +1 -1
  12. package/dist/lib/testing/compliance/platform-storyboards.d.ts +44 -0
  13. package/dist/lib/testing/compliance/platform-storyboards.d.ts.map +1 -0
  14. package/dist/lib/testing/compliance/platform-storyboards.js +230 -0
  15. package/dist/lib/testing/compliance/platform-storyboards.js.map +1 -0
  16. package/dist/lib/testing/compliance/storyboard-tracks.d.ts +2 -9
  17. package/dist/lib/testing/compliance/storyboard-tracks.d.ts.map +1 -1
  18. package/dist/lib/testing/compliance/storyboard-tracks.js +4 -44
  19. package/dist/lib/testing/compliance/storyboard-tracks.js.map +1 -1
  20. package/dist/lib/testing/index.d.ts +1 -1
  21. package/dist/lib/testing/index.d.ts.map +1 -1
  22. package/dist/lib/testing/index.js +6 -1
  23. package/dist/lib/testing/index.js.map +1 -1
  24. package/dist/lib/types/core.generated.d.ts +241 -2
  25. package/dist/lib/types/core.generated.d.ts.map +1 -1
  26. package/dist/lib/types/core.generated.js +1 -1
  27. package/dist/lib/types/schemas.generated.d.ts +3380 -3154
  28. package/dist/lib/types/schemas.generated.d.ts.map +1 -1
  29. package/dist/lib/types/schemas.generated.js +220 -115
  30. package/dist/lib/types/schemas.generated.js.map +1 -1
  31. package/dist/lib/types/tools.generated.d.ts +267 -74
  32. package/dist/lib/types/tools.generated.d.ts.map +1 -1
  33. package/dist/lib/version.d.ts +3 -3
  34. package/dist/lib/version.js +3 -3
  35. package/docs/llms.txt +46 -30
  36. package/package.json +1 -1
  37. package/storyboards/audience_sync.yaml +18 -29
  38. package/storyboards/behavioral_analysis.yaml +40 -72
  39. package/storyboards/brand_rights.yaml +172 -75
  40. package/storyboards/campaign_governance_conditions.yaml +187 -0
  41. package/storyboards/campaign_governance_delivery.yaml +231 -0
  42. package/storyboards/campaign_governance_denied.yaml +135 -0
  43. package/storyboards/capability_discovery.yaml +106 -0
  44. package/storyboards/content_standards.yaml +251 -0
  45. package/storyboards/creative_ad_server.yaml +108 -16
  46. package/storyboards/creative_lifecycle.yaml +284 -0
  47. package/storyboards/creative_sales_agent.yaml +2 -6
  48. package/storyboards/creative_template.yaml +1 -5
  49. package/storyboards/error_compliance.yaml +105 -108
  50. package/storyboards/media_buy_catalog_creative.yaml +6 -4
  51. package/storyboards/media_buy_governance_escalation.yaml +9 -5
  52. package/storyboards/media_buy_guaranteed_approval.yaml +9 -7
  53. package/storyboards/media_buy_non_guaranteed.yaml +7 -6
  54. package/storyboards/media_buy_proposal_mode.yaml +9 -8
  55. package/storyboards/media_buy_seller.yaml +153 -165
  56. package/storyboards/media_buy_state_machine.yaml +100 -99
  57. package/storyboards/property_governance.yaml +239 -0
  58. package/storyboards/schema.yaml +2 -2
  59. package/storyboards/schema_validation.yaml +58 -51
  60. package/storyboards/si_session.yaml +99 -317
  61. package/storyboards/signal_marketplace.yaml +6 -5
  62. package/storyboards/signal_owned.yaml +5 -5
  63. package/storyboards/social_platform.yaml +274 -0
  64. package/storyboards/governance_content_standards.yaml +0 -213
  65. package/storyboards/governance_property_lists.yaml +0 -372
@@ -0,0 +1,284 @@
1
+ id: creative_lifecycle
2
+ version: "1.0.0"
3
+ title: "Creative lifecycle"
4
+ category: creative_lifecycle
5
+ summary: "Full creative lifecycle on a stateful platform: sync multiple creatives, list with filtering, build and preview across formats, observe status transitions."
6
+ track: creative
7
+ required_tools:
8
+ - list_creative_formats
9
+
10
+ narrative: |
11
+ You run a creative platform with a persistent library — an ad server, creative management
12
+ platform, or publisher that accepts and stores creative assets. A buyer agent pushes
13
+ multiple creatives in different formats, queries the library, builds serving tags, previews
14
+ renderings, and monitors creative status as assets move through your review pipeline.
15
+
16
+ This storyboard covers the complete creative lifecycle from the buyer's perspective:
17
+ uploading assets, browsing the library, building deliverables across formats, and
18
+ observing status transitions as creatives move from pending_review through to accepted.
19
+
20
+ The individual creative storyboards (template, ad server, sales agent) cover specific
21
+ interaction models. This storyboard tests the full lifecycle across multiple creatives
22
+ and formats on a single platform.
23
+
24
+ agent:
25
+ interaction_model: stateful_preloaded
26
+ capabilities:
27
+ - has_creative_library
28
+ - supports_transformation
29
+ examples:
30
+ - "Innovid"
31
+ - "Flashtalking"
32
+ - "CM360"
33
+ - "Creative management platforms"
34
+
35
+ caller:
36
+ role: buyer_agent
37
+ example: "Pinnacle Agency (buyer)"
38
+
39
+ prerequisites:
40
+ description: |
41
+ The caller needs creative assets in multiple formats (display, video, native) and
42
+ a brand identity. The test kit provides sample assets at standard ad dimensions.
43
+ test_kit: "test-kits/acme-outdoor.yaml"
44
+
45
+ phases:
46
+ - id: discover_formats
47
+ title: "Discover accepted formats"
48
+ narrative: |
49
+ Before pushing any creatives, the buyer discovers what formats your platform accepts.
50
+ This determines which assets to prepare and what dimensions and specs to target.
51
+
52
+ steps:
53
+ - id: list_formats
54
+ title: "List creative formats"
55
+ narrative: |
56
+ The buyer calls list_creative_formats to discover what your platform accepts.
57
+ The response defines format specs: dimensions, asset requirements, mime types,
58
+ and any platform-specific constraints.
59
+ task: list_creative_formats
60
+ schema_ref: "creative/list-creative-formats-request.json"
61
+ response_schema_ref: "creative/list-creative-formats-response.json"
62
+ doc_ref: "/creative/task-reference/list_creative_formats"
63
+ comply_scenario: creative_lifecycle
64
+ stateful: false
65
+ expected: |
66
+ Return all creative formats your platform accepts:
67
+ - format_id with your agent_url and unique id
68
+ - Asset requirements (dimensions, file sizes, mime types)
69
+ - Render dimensions
70
+ - At least two formats (e.g., display and video)
71
+
72
+ sample_request: {}
73
+
74
+ validations:
75
+ - check: response_schema
76
+ description: "Response matches list-creative-formats-response.json schema"
77
+ - check: field_present
78
+ path: "formats"
79
+ description: "Response contains formats array"
80
+
81
+ - id: sync_multiple
82
+ title: "Sync multiple creatives"
83
+ narrative: |
84
+ The buyer pushes three creatives in different formats to your platform: a display
85
+ banner, a video spot, and a native card. Your platform validates each creative
86
+ against its format specs and returns per-creative status.
87
+
88
+ steps:
89
+ - id: sync_creatives
90
+ title: "Push three creatives in different formats"
91
+ narrative: |
92
+ The buyer syncs three creatives simultaneously: a 300x250 display banner, a 30s
93
+ video spot, and a native content card. Your platform validates each against its
94
+ format specs and returns per-creative action and status.
95
+ task: sync_creatives
96
+ schema_ref: "creative/sync-creatives-request.json"
97
+ response_schema_ref: "creative/sync-creatives-response.json"
98
+ doc_ref: "/creative/task-reference/sync_creatives"
99
+ comply_scenario: creative_lifecycle
100
+ stateful: true
101
+ expected: |
102
+ Accept and validate all three creatives:
103
+ - Per-creative action: created
104
+ - Per-creative status: accepted or pending_review
105
+ - Validation results for each creative
106
+ - Platform-assigned IDs if applicable
107
+
108
+ sample_request:
109
+ account:
110
+ brand:
111
+ domain: "acmeoutdoor.com"
112
+ operator: "pinnacle-agency.com"
113
+ creatives:
114
+ - creative_id: "display_trail_pro_300x250"
115
+ name: "Trail Pro 3000 - Display 300x250"
116
+ format_id:
117
+ agent_url: "https://your-platform.example.com"
118
+ id: "display_300x250"
119
+ assets:
120
+ - asset_id: "image"
121
+ asset_type: "image"
122
+ url: "https://cdn.pinnacle-agency.example/trail-pro-300x250.png"
123
+ mime_type: "image/png"
124
+ - creative_id: "video_30s_trail_pro"
125
+ name: "Trail Pro 3000 - 30s Video"
126
+ format_id:
127
+ agent_url: "https://your-platform.example.com"
128
+ id: "video_30s"
129
+ assets:
130
+ - asset_id: "video"
131
+ asset_type: "video"
132
+ url: "https://cdn.pinnacle-agency.example/trail-pro-30s.mp4"
133
+ mime_type: "video/mp4"
134
+ - creative_id: "native_trail_pro"
135
+ name: "Trail Pro 3000 - Native Card"
136
+ format_id:
137
+ agent_url: "https://your-platform.example.com"
138
+ id: "native_content"
139
+ assets:
140
+ - asset_id: "image"
141
+ asset_type: "image"
142
+ url: "https://cdn.pinnacle-agency.example/trail-pro-native.png"
143
+ mime_type: "image/png"
144
+ - asset_id: "headline"
145
+ asset_type: "text"
146
+ content: "Trail Pro 3000 — Built for the Summit"
147
+
148
+ validations:
149
+ - check: response_schema
150
+ description: "Response matches sync-creatives-response.json schema"
151
+ - check: field_present
152
+ path: "results"
153
+ description: "Response contains per-creative results"
154
+
155
+ - id: list_and_filter
156
+ title: "List creatives with filtering"
157
+ narrative: |
158
+ The buyer queries the creative library to see their synced creatives. First a broad
159
+ list, then filtered by format. This verifies the library correctly stores and indexes
160
+ the pushed creatives.
161
+
162
+ steps:
163
+ - id: list_all
164
+ title: "List all creatives in library"
165
+ narrative: |
166
+ The buyer calls list_creatives with no filters to see all creatives in the
167
+ library for their account. The response includes the three creatives synced
168
+ in the previous phase.
169
+ task: list_creatives
170
+ schema_ref: "creative/list-creatives-request.json"
171
+ response_schema_ref: "creative/list-creatives-response.json"
172
+ doc_ref: "/creative/task-reference/list_creatives"
173
+ comply_scenario: creative_lifecycle
174
+ stateful: true
175
+ expected: |
176
+ Return creatives in the library:
177
+ - creatives array containing the synced items
178
+ - Each creative includes: creative_id, name, format_id, status
179
+ - At least three creatives from the sync phase
180
+
181
+ sample_request:
182
+ account:
183
+ brand:
184
+ domain: "acmeoutdoor.com"
185
+ operator: "pinnacle-agency.com"
186
+
187
+ validations:
188
+ - check: response_schema
189
+ description: "Response matches list-creatives-response.json schema"
190
+ - check: field_present
191
+ path: "creatives"
192
+ description: "Response contains creatives array"
193
+
194
+ - id: list_filtered
195
+ title: "List creatives filtered by format"
196
+ narrative: |
197
+ The buyer lists creatives filtered to a specific format (display only). The
198
+ response should only include creatives matching that format.
199
+ task: list_creatives
200
+ schema_ref: "creative/list-creatives-request.json"
201
+ response_schema_ref: "creative/list-creatives-response.json"
202
+ doc_ref: "/creative/task-reference/list_creatives"
203
+ comply_scenario: creative_lifecycle
204
+ stateful: true
205
+ expected: |
206
+ Return only creatives matching the format filter:
207
+ - creatives array filtered to display format
208
+ - Should include display_trail_pro_300x250 but not video or native
209
+
210
+ sample_request:
211
+ account:
212
+ brand:
213
+ domain: "acmeoutdoor.com"
214
+ operator: "pinnacle-agency.com"
215
+ filters:
216
+ format_ids:
217
+ - agent_url: "https://your-platform.example.com"
218
+ id: "display_300x250"
219
+
220
+ validations:
221
+ - check: response_schema
222
+ description: "Response matches list-creatives-response.json schema"
223
+ - check: field_present
224
+ path: "creatives"
225
+ description: "Response contains filtered creatives"
226
+
227
+ - id: build_and_preview
228
+ title: "Build and preview across formats"
229
+ narrative: |
230
+ The buyer builds serving tags and previews renderings for the synced creatives.
231
+ This tests multi-format output: a display tag, a VAST tag for video, and a
232
+ native rendering preview.
233
+
234
+ steps:
235
+ - id: preview_display
236
+ title: "Preview the display creative"
237
+ narrative: |
238
+ The buyer calls preview_creative for the display banner to see how it renders
239
+ in the platform's environment before going live.
240
+ task: preview_creative
241
+ schema_ref: "creative/preview-creative-request.json"
242
+ response_schema_ref: "creative/preview-creative-response.json"
243
+ doc_ref: "/creative/task-reference/preview_creative"
244
+ comply_scenario: creative_flow
245
+ stateful: true
246
+ expected: |
247
+ Return a preview of the display creative:
248
+ - preview_url: rendered preview the buyer can inspect
249
+ - render_dimensions: matches the 300x250 format
250
+ - status: preview available
251
+
252
+ sample_request:
253
+ creative_id: "display_trail_pro_300x250"
254
+
255
+ validations:
256
+ - check: response_schema
257
+ description: "Response matches preview-creative-response.json schema"
258
+
259
+ - id: build_video_tag
260
+ title: "Build a VAST tag for the video creative"
261
+ narrative: |
262
+ The buyer builds a serving tag for the video creative. The platform produces
263
+ a VAST-compatible tag that the buyer can traffic to ad servers.
264
+ task: build_creative
265
+ schema_ref: "creative/build-creative-request.json"
266
+ response_schema_ref: "creative/build-creative-response.json"
267
+ doc_ref: "/creative/task-reference/build_creative"
268
+ comply_scenario: creative_flow
269
+ stateful: true
270
+ expected: |
271
+ Return a built serving tag for the video creative:
272
+ - tag: VAST-compatible serving tag or URL
273
+ - format: matches the video format
274
+ - creative_id: matches the requested creative
275
+
276
+ sample_request:
277
+ creative_id: "video_30s_trail_pro"
278
+ output_format:
279
+ agent_url: "https://your-platform.example.com"
280
+ id: "vast_30s"
281
+
282
+ validations:
283
+ - check: response_schema
284
+ description: "Response matches build-creative-response.json schema"
@@ -3,14 +3,10 @@ version: "1.0.0"
3
3
  title: "Sales agent with creative capabilities"
4
4
  category: creative_sales_agent
5
5
  summary: "Stateful sales agent that accepts pushed creative assets and renders them in its environment."
6
- platform_types:
7
- - retail_media
8
- - social_platform
9
-
10
6
  track: creative
11
7
  required_tools:
12
8
  - sync_creatives
13
- - list_creative_formats
9
+
14
10
  narrative: |
15
11
  You run a publisher platform, retail media network, or other sell-side system that
16
12
  accepts creative assets from buyers. The buyer pushes assets or catalog items to your
@@ -122,7 +118,7 @@ phases:
122
118
  - check: response_schema
123
119
  description: "Response matches sync-creatives-response.json schema"
124
120
  - check: field_present
125
- path: "creatives[0].action"
121
+ path: "results[0].action"
126
122
  description: "Each creative has an action (created/updated)"
127
123
 
128
124
  - id: preview
@@ -3,14 +3,10 @@ version: "1.0.0"
3
3
  title: "Creative template and transformation agent"
4
4
  category: creative_template
5
5
  summary: "Stateless creative agent that takes assets in, applies templates, and produces tags or rendered output."
6
- platform_types:
7
- - creative_transformer
8
- - creative_library
9
-
10
6
  track: creative
11
7
  required_tools:
12
8
  - build_creative
13
- - list_creative_formats
9
+
14
10
  narrative: |
15
11
  You build a creative management or rich media platform — think Celtra, a format
16
12
  conversion service, or any tool that defines ad templates and transforms input assets
@@ -1,10 +1,9 @@
1
1
  id: error_compliance
2
2
  version: "1.0.0"
3
3
  title: "Error handling and compliance"
4
- category: media_buy_seller
5
- track: error_handling
4
+ category: error_compliance
6
5
  summary: "Validates that agents return properly structured AdCP errors with correct codes, recovery hints, and transport bindings."
7
-
6
+ track: error_handling
8
7
  required_tools:
9
8
  - get_products
10
9
 
@@ -33,6 +32,12 @@ caller:
33
32
  role: buyer_agent
34
33
  example: "Compliance test harness"
35
34
 
35
+ prerequisites:
36
+ description: |
37
+ No special prerequisites. The storyboard sends intentionally invalid requests
38
+ to test error handling.
39
+ test_kit: "test-kits/acme-outdoor.yaml"
40
+
36
41
  phases:
37
42
  - id: error_responses
38
43
  title: "Error responses for invalid input"
@@ -46,16 +51,19 @@ phases:
46
51
  title: "Reject negative budget"
47
52
  narrative: |
48
53
  A negative budget is never valid. The agent must reject this with INVALID_REQUEST
49
- or BUDGET_TOO_LOW and a correctable recovery hint so the buyer knows to fix the value.
54
+ or BUDGET_TOO_LOW and a correctable recovery hint.
50
55
  task: create_media_buy
51
- requires_tool: create_media_buy
52
- expect_error: true
56
+ schema_ref: "media-buy/create-media-buy-request.json"
57
+ response_schema_ref: "media-buy/create-media-buy-response.json"
58
+ doc_ref: "/media-buy/task-reference/create_media_buy"
59
+ comply_scenario: error_handling
53
60
  stateful: false
54
61
  expected: |
55
62
  Reject the request with an error containing:
56
63
  - code: INVALID_REQUEST or BUDGET_TOO_LOW
57
64
  - recovery: correctable
58
65
  - field: packages[0].budget (optional but recommended)
66
+
59
67
  sample_request:
60
68
  idempotency_key: "error-test-negative-budget"
61
69
  start_time: "2026-05-01T00:00:00Z"
@@ -64,10 +72,11 @@ phases:
64
72
  - product_id: "test-product"
65
73
  budget: -500
66
74
  pricing_option_id: "test-pricing"
75
+
67
76
  validations:
68
- - check: error_code
69
- value: "INVALID_REQUEST"
70
- description: "Error code is INVALID_REQUEST or BUDGET_TOO_LOW"
77
+ - check: field_present
78
+ path: "errors"
79
+ description: "Response contains an error for negative budget"
71
80
 
72
81
  - id: nonexistent_product
73
82
  title: "Reject nonexistent product ID"
@@ -75,157 +84,145 @@ phases:
75
84
  The buyer references a product ID that does not exist on this platform.
76
85
  The agent should return PRODUCT_NOT_FOUND or INVALID_REQUEST.
77
86
  task: create_media_buy
78
- requires_tool: create_media_buy
79
- expect_error: true
87
+ schema_ref: "media-buy/create-media-buy-request.json"
88
+ response_schema_ref: "media-buy/create-media-buy-response.json"
89
+ doc_ref: "/media-buy/task-reference/create_media_buy"
90
+ comply_scenario: error_handling
80
91
  stateful: false
81
92
  expected: |
82
- Reject the request with an error containing:
93
+ Reject the request with:
83
94
  - code: PRODUCT_NOT_FOUND or INVALID_REQUEST
84
95
  - recovery: correctable
96
+
85
97
  sample_request:
86
98
  idempotency_key: "error-test-nonexistent-product"
87
99
  start_time: "2026-05-01T00:00:00Z"
88
100
  end_time: "2026-05-31T23:59:59Z"
89
101
  packages:
90
- - product_id: "NONEXISTENT_PRODUCT_ID_12345"
91
- budget: 1000
92
- pricing_option_id: "nonexistent-pricing"
102
+ - product_id: "nonexistent-product-id-xyz"
103
+ budget: 10000
104
+ pricing_option_id: "test-pricing"
105
+
93
106
  validations:
94
- - check: error_code
95
- value: "PRODUCT_NOT_FOUND"
96
- description: "Error code is PRODUCT_NOT_FOUND or INVALID_REQUEST"
107
+ - check: field_present
108
+ path: "errors"
109
+ description: "Response contains an error for nonexistent product"
97
110
 
98
111
  - id: missing_fields
99
- title: "Handle empty get_products request"
112
+ title: "Reject empty get_products request"
100
113
  narrative: |
101
- The buyer sends an empty get_products request with no brief or brand.
102
- The agent may accept it (permissive) or reject it (strict validation).
103
- Both behaviors are acceptable — what matters is that the response is structured.
114
+ Send a get_products request with no brief and no buying_mode. The agent should
115
+ either return products (treating it as a catalog browse) or return an error
116
+ requesting the missing brief.
104
117
  task: get_products
105
- requires_tool: get_products
118
+ schema_ref: "media-buy/get-products-request.json"
119
+ response_schema_ref: "media-buy/get-products-response.json"
120
+ doc_ref: "/media-buy/task-reference/get_products"
121
+ comply_scenario: error_handling
106
122
  stateful: false
107
123
  expected: |
108
- Either:
109
- - Return products (permissive mode)
110
- - Return a structured error with INVALID_REQUEST (strict mode)
111
- Both are acceptable. An unstructured error or crash is not.
112
- sample_request: {}
124
+ Either return products (treating empty request as browse) or return a
125
+ structured error requesting the missing brief. Both are valid.
126
+
127
+ sample_request:
128
+ brand:
129
+ domain: "acmeoutdoor.com"
130
+
113
131
  validations:
114
132
  - check: response_schema
115
- description: "Response is a valid get-products-response or structured error"
133
+ description: "Response is either valid products or a structured error"
116
134
 
117
- - id: reversed_dates
118
- title: "Reject end time before start time"
135
+ - id: reversed_dates_error
136
+ title: "Reject reversed dates with error code"
119
137
  narrative: |
120
- The buyer sends a create_media_buy with end_time before start_time.
121
- The agent must reject this temporal inconsistency.
138
+ Send a create_media_buy with end_time before start_time and verify the error
139
+ response includes the correct code and recovery classification.
122
140
  task: create_media_buy
123
- requires_tool: create_media_buy
124
- expect_error: true
141
+ schema_ref: "media-buy/create-media-buy-request.json"
142
+ response_schema_ref: "media-buy/create-media-buy-response.json"
143
+ doc_ref: "/media-buy/task-reference/create_media_buy"
144
+ comply_scenario: error_handling
125
145
  stateful: false
126
146
  expected: |
127
- Reject the request with an error containing:
128
- - code: INVALID_REQUEST
129
- - recovery: correctable
130
- - field: end_time (optional but recommended)
147
+ Reject with INVALID_REQUEST and correctable recovery.
148
+
131
149
  sample_request:
132
150
  idempotency_key: "error-test-reversed-dates"
133
- start_time: "2026-05-31T23:59:59Z"
134
- end_time: "2026-05-01T00:00:00Z"
151
+ start_time: "2026-12-31T00:00:00Z"
152
+ end_time: "2026-01-01T00:00:00Z"
135
153
  packages:
136
154
  - product_id: "test-product"
137
- budget: 1000
155
+ budget: 10000
138
156
  pricing_option_id: "test-pricing"
157
+
139
158
  validations:
140
- - check: error_code
141
- value: "INVALID_REQUEST"
142
- description: "Error code is INVALID_REQUEST for reversed date range"
159
+ - check: field_present
160
+ path: "errors"
161
+ description: "Response contains an error for reversed dates"
143
162
 
144
163
  - id: error_structure
145
- title: "Error JSON structure validation"
164
+ title: "Error structure compliance"
146
165
  narrative: |
147
- Beyond returning the right error code, the error object itself must conform to the
148
- AdCP error schema. Required fields: code (non-empty string), message (string).
149
- Optional fields: recovery (transient|correctable|terminal), retry_after (non-negative
150
- number), field (string), suggestion (string). Non-standard codes must use the X_ prefix.
166
+ Validates that error responses follow the AdCP error structure with required
167
+ and optional fields.
151
168
 
152
169
  steps:
153
170
  - id: validate_error_shape
154
- title: "Validate error JSON structure"
171
+ title: "Validate error response structure"
155
172
  narrative: |
156
- Provoke an error and inspect the JSON structure. The error object must have a
157
- code and message at minimum. If recovery, retry_after, field, or suggestion are
158
- present, they must have the correct types. Non-standard codes must use X_ prefix.
173
+ Trigger an error and inspect the response structure. The adcp_error object
174
+ must have code and message. Optional fields include recovery, retry_after,
175
+ field, and suggestion.
159
176
  task: create_media_buy
160
- requires_tool: create_media_buy
161
- expect_error: true
177
+ schema_ref: "media-buy/create-media-buy-request.json"
178
+ response_schema_ref: "media-buy/create-media-buy-response.json"
179
+ doc_ref: "/media-buy/task-reference/create_media_buy"
180
+ comply_scenario: error_codes
162
181
  stateful: false
163
182
  expected: |
164
- Error object with valid structure:
165
- - code: non-empty string (standard AdCP code or X_-prefixed vendor code)
166
- - message: string
167
- - recovery: transient, correctable, or terminal (if present)
168
- - retry_after: non-negative number (if present)
169
- - field: string path to the offending field (if present)
170
- - suggestion: string with remediation hint (if present)
183
+ Error response with:
184
+ - code: a recognized AdCP error code
185
+ - message: human-readable description
186
+ - recovery: correctable, transient, or fatal (optional)
187
+
171
188
  sample_request:
172
- idempotency_key: "error-test-structure"
173
- start_time: "2026-05-01T00:00:00Z"
174
- end_time: "2026-05-31T23:59:59Z"
189
+ idempotency_key: "error-structure-test"
190
+ start_time: "2026-12-31T00:00:00Z"
191
+ end_time: "2026-01-01T00:00:00Z"
175
192
  packages:
176
- - product_id: "NONEXISTENT_PRODUCT_ID_12345"
177
- budget: 1000
178
- pricing_option_id: "nonexistent-pricing"
179
- validations:
180
- - check: field_present
181
- path: "adcp_error.code"
182
- description: "Error has a code field"
183
- - check: field_present
184
- path: "adcp_error.message"
185
- description: "Error has a message field"
193
+ - product_id: "test-product"
194
+ budget: -1
195
+ pricing_option_id: "test-pricing"
186
196
 
187
197
  - id: error_transport
188
- title: "Error transport binding validation"
198
+ title: "Error transport bindings"
189
199
  narrative: |
190
- AdCP errors must be delivered through the correct MCP transport layers. The isError
191
- flag signals the error to the MCP client, the JSON text content provides a fallback
192
- for clients that do not support structuredContent, and structuredContent.adcp_error
193
- provides the full typed error object.
194
-
195
- Agents using the adcpError() helper from @adcp/client get all three layers automatically.
200
+ Validates that errors are transported correctly via MCP. The isError flag must
201
+ be set, and the error should be available in both JSON text content (L2) and
202
+ structuredContent (L3) bindings.
196
203
 
197
204
  steps:
198
205
  - id: validate_transport_binding
199
- title: "Validate structuredContent.adcp_error binding"
206
+ title: "Validate error transport binding"
200
207
  narrative: |
201
- Provoke an error and check that it appears in the correct transport layers:
202
- - isError: true on the MCP response
203
- - JSON text content with adcp_error (L2 fallback)
204
- - structuredContent.adcp_error (L3 full compliance)
205
-
206
- L2 is the minimum passing level. L3 is expected for agents using adcpError().
208
+ Trigger an error and verify the MCP transport binding: isError flag must be
209
+ set to true, and the error content should include the adcp_error object.
207
210
  task: create_media_buy
208
- requires_tool: create_media_buy
209
- expect_error: true
211
+ schema_ref: "media-buy/create-media-buy-request.json"
212
+ response_schema_ref: "media-buy/create-media-buy-response.json"
213
+ doc_ref: "/media-buy/task-reference/create_media_buy"
214
+ comply_scenario: error_transport
210
215
  stateful: false
211
216
  expected: |
212
217
  MCP response with:
213
218
  - isError: true
214
- - content[].text contains JSON with adcp_error (L2)
215
- - structuredContent.adcp_error present (L3)
216
- - Error code in structuredContent matches error code in text content (consistency)
219
+ - content containing adcp_error (L2: JSON text, L3: structuredContent)
220
+
217
221
  sample_request:
218
- idempotency_key: "error-test-transport"
219
- start_time: "2026-05-01T00:00:00Z"
220
- end_time: "2026-05-31T23:59:59Z"
222
+ idempotency_key: "error-transport-test"
223
+ start_time: "2026-12-31T00:00:00Z"
224
+ end_time: "2026-01-01T00:00:00Z"
221
225
  packages:
222
- - product_id: "NONEXISTENT_PRODUCT_ID_12345"
223
- budget: 1000
224
- pricing_option_id: "nonexistent-pricing"
225
- validations:
226
- - check: field_present
227
- path: "adcp_error"
228
- description: "structuredContent contains adcp_error object"
229
- - check: error_code
230
- value: "PRODUCT_NOT_FOUND"
231
- description: "Error code is a valid AdCP standard code or X_-prefixed vendor code"
226
+ - product_id: "nonexistent"
227
+ budget: -1
228
+ pricing_option_id: "bad-pricing"