feat(training-agent): impairment tracking for media buys (closes #4719)#4733
Merged
Conversation
When a creative referenced by a media buy's package transitions to rejected, the buy now surfaces `health: impaired` and an `impairments[]` entry. When the buyer recovers via assignment swap (update_media_buy replacing the offline creative with an approved sibling), the impairment clears and health returns to ok. Closes the dependency_impairment + dependency_impairment_cardinality storyboards added in #4677/#4685. - types.ts: Impairment interface + MediaBuyState.impairments - comply-test-controller.ts: propagateCreativeImpairment walks session.mediaBuys on forceCreativeStatus, appending on approved→rejected and removing on the inverse; idempotent on re-emission - task-handlers.ts: - get_media_buys emits health + impairments mapped to wire shape - update_media_buy recomputes impairments after creative_assignments replacement; drops any whose resource_id is no longer referenced - tenants/comply.ts: wire force_creative_status adapter on /sales (was missing, storyboards reported force_scenario_unsupported) Scenario fixes: - Both dependency_impairment storyboards restructure sync_creatives + inline assignments into sync_creatives + update_media_buy. v6 SalesPlatform.syncCreatives doesn't expose request-level assignments to the platform (filed upstream at adcp-client#1842). Both surfaces are spec-canonical; this is a v6-SDK compatibility choice, not a deprecation. - dependency_impairment_cardinality also needs bid_price: 10.0 on its packages because its brief lands on an auction pricing_option as products[0].pricing_options[0] (test-design issue filed at #4732). Sales floor lifts from 72:340 to 74:380. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
When a creative referenced by a media buy's package transitions to
rejected, the buy now surfaceshealth: "impaired"and animpairments[]entry perstatic/schemas/source/core/impairment.json. When the buyer recovers via assignment swap, the impairment clears and health returns took.Closes the
media_buy_seller/dependency_impairmentanddependency_impairment_cardinalitystoryboards added in #4677/#4685 (both clean now, 12P + 19P = 31 steps passing on /sales).Changes
types.ts—Impairmentinterface +MediaBuyState.impairments?: Impairment[].comply-test-controller.ts—propagateCreativeImpairment(session, creativeId, prev, next)walkssession.mediaBuys, finds buys with dependent packages, appends/removes impairment entries based on transition direction. Called fromforceCreativeStatusafter the status mutation. Idempotent on re-emission.task-handlers.ts:handleGetMediaBuysmapper emitshealth('impaired'iff impairments.length > 0, else'ok') andimpairments[]mapped to the wire shape.handleUpdateMediaBuyrecomputesmb.impairmentsaftercreative_assignmentsreplacement — drops any creative-impairment whoseresource_idis no longer referenced. This is the canonical recovery vector (assignment swap).tenants/comply.ts—creative_statusadapter wired into the v6/salescomply config. Was missing; storyboards previously reportedforce_scenario_unsupported.Storyboard adjustments
Both
dependency_impairment*storyboards originally used inlinesync_creatives.assignments[]to bind the creative. The v6SalesPlatform.syncCreatives(creatives, ctx)signature drops the request-levelassignments[]— the platform has no surface for it (filed upstream at adcp-client#1842).Both storyboards restructured to:
sync_creatives(library only, no assignment)update_media_buywithpackages[].creative_assignmentsBoth surfaces are equally canonical per the spec — this is a v6-SDK compatibility choice, not a deprecation. The impairment.coherence contract is identical regardless of binding path. Narrative in both scenarios updated to reflect this.
dependency_impairment_cardinalityalso needsbid_price: 10.0on its packages because its brief lands on an auction pricing_option asproducts[0].pricing_options[0]. Filed test-design issue at #4732 for scenarios depending onpricing_options[0]discriminator.Floors
/sales: 72:340 → 74:380 (observed 75 clean, 398 steps)Reviewed by
code-reviewer(no blockers, "ready to push")ad-tech-protocol-expert("scenarios are spec-conformant"; narrative adjustments applied for canonical-surface framing)Test plan
bash scripts/run-storyboards-matrix.sh— all 6 tenants pass new floorsnpx tsc --noEmit -p server/tsconfig.jsonclean🤖 Generated with Claude Code