feat(media-buy): add shared budgets and bidding policy - #6088
Conversation
There was a problem hiding this comment.
Ladon verdict: Escalate to human review
Escalate — gated schema paths require human/CODEOWNERS approval.
This PR modifies published protocol source under static/schemas/source/** (a deterministic hard approval gate) and review_decision is REVIEW_REQUIRED, not APPROVED. Per decision rule row 2, the outcome must be escalate until a real human/CODEOWNERS approval lifts the gate.
No blocking (critical/high) findings were reported. The reviewer classified the change as Normative (non-breaking): additive BudgetAllocation discriminated model, aggregate budget/pacing, package caps, a new capability flag, and a new update_budget_allocation action, with wire changes that are additive or relaxations, a correct minor changeset, and a properly discriminated oneOf. Two Medium coherence/validation gaps remain (see below) but do not on their own change the outcome — the gated-paths gate is the controlling trigger.
Gated files requiring human/CODEOWNERS review include: static/schemas/source/core/budget-allocation.json (added) and the modified media-buy.json, package.json, proposal.json, planned-delivery.json, product-allocation.json, optimization-goal.json, media-buy-features.json, index.json, plus the media-buy request/response schemas.
Medium findings for the human reviewer to weigh:
- docs/media-buy/task-reference/get_media_buys.mdx:84 — packages[].pacing added to response but undocumented in the package table (schema↔docs coherence gap).
- static/schemas/source/media-buy/package-request.json:47 — budget no longer required on new_packages[] for fixed-allocation buys.
Once a CODEOWNERS/human approval sets review_decision to APPROVED, this can fall through to the normal table (no blocking findings present).
Medium findings
- docs/media-buy/task-reference/get_media_buys.mdx:84 — packages[].pacing added to get-media-buys-response but undocumented in get_media_buys package table
- static/schemas/source/media-buy/package-request.json:47 — budget no longer required on new_packages[] for fixed-allocation buys
Why human review
- Touches gated protocol source under static/schemas/source/** (e.g. budget-allocation.json, media-buy.json, proposal.json, package.json) — hard approval gate; review_decision is REVIEW_REQUIRED, not APPROVED. Human/CODEOWNERS review required.
- Two medium schema↔docs coherence/validation gaps to verify: get_media_buys.mdx:84 (packages[].pacing undocumented) and package-request.json:47 (budget no longer required on new_packages[] for fixed allocation).
- This PR touches a path under a hard, non-overridable approval gate (static/schemas/source/core/budget-allocation.json (added) matches
static/schemas/source/**; static/schemas/source/core/media-buy-features.json (modified) matchesstatic/schemas/source/**; static/schemas/source/core/media-buy.json (modified) matchesstatic/schemas/source/**; static/schemas/source/core/optimization-goal.json (modified) matchesstatic/schemas/source/**; static/schemas/source/core/package.json (modified) matchesstatic/schemas/source/**; static/schemas/source/core/planned-delivery.json (modified) matchesstatic/schemas/source/**; static/schemas/source/core/product-allocation.json (modified) matchesstatic/schemas/source/**; static/schemas/source/core/proposal.json (modified) matchesstatic/schemas/source/**; static/schemas/source/enums/media-buy-valid-action.json (modified) matchesstatic/schemas/source/**; static/schemas/source/index.json (modified) matchesstatic/schemas/source/**; static/schemas/source/media-buy/create-media-buy-request.json (modified) matchesstatic/schemas/source/**; static/schemas/source/media-buy/create-media-buy-response.json (modified) matchesstatic/schemas/source/**; static/schemas/source/media-buy/get-media-buy-delivery-response.json (modified) matchesstatic/schemas/source/**; static/schemas/source/media-buy/get-media-buys-response.json (modified) matchesstatic/schemas/source/**; static/sc
…(truncated)…
|
Ladon cannot review this PR until merge conflicts are resolved. |
There was a problem hiding this comment.
Ladon verdict: Escalate to human review
Escalate — gated protocol source under a hard approval gate, review_decision is not APPROVED.
This PR modifies static/schemas/source/** (gated paths), and review_decision is unknown/not APPROVED. Per decision-table row 2, the hard approval gate is not satisfied and the outcome must be escalate — Ladon cannot auto-approve gated protocol source until a human/CODEOWNERS approval is recorded.
Iteration credit: Both prior medium findings are resolved this pass (no packages[].pacing in get-media-buys-response.json; budget still required in package-request.json). The BiddingPolicy work is coherent and well-tested — mutual exclusion via not.anyOf, deprecated-not-removed bid_price/max_bid, type-const-discriminated execution oneOf, matching docs across create/get/update, new error codes, and composed/AJV coverage. This is a net improvement over the prior run.
Medium findings (surfaced, non-blocking):
- static/schemas/source/media-buy/package-update.json:202 — bidding-conflict guards reject an explicit
bidding:nullclear, wrongly rejecting a legit legacy-migration update. Worth fixing but does not itself block.
Escalation reasons:
- Gated paths under
static/schemas/source/**(e.g. bidding-policy.json, budget-allocation.json, media-buy.json, proposal.json) touched;review_decisionis not APPROVED. Human/CODEOWNERS review required. - New protocol fields, new error codes (BIDDING_PLACEMENT_CONFLICT, AMBIGUOUS_BIDDING_POLICY), and new enum values are additive/normative surface changes on the published protocol; ratification is a human act.
Medium findings
- static/schemas/source/media-buy/package-update.json:202 — package-update bidding guards reject an explicit bidding:null clear
Why human review
- Touches gated protocol source under static/schemas/source/** (bidding-policy.json, budget-allocation.json, media-buy.json, proposal.json, package.json, and others) — hard, non-overridable approval gate; review_decision is not APPROVED, so Ladon cannot auto-approve. Human/CODEOWNERS review required.
- Adds new protocol fields, new error codes, and new enum values to the published AdCP surface — normative/additive spec changes whose ratification is a human act.
- One medium to verify during human review: static/schemas/source/media-buy/package-update.json:202 — bidding-conflict guards reject an explicit bidding:null clear, blocking a legit legacy-migration update.
- This PR touches a path under a hard, non-overridable approval gate (static/schemas/source/core/bidding-policy.json (added) matches
static/schemas/source/**; static/schemas/source/core/budget-allocation.json (added) matchesstatic/schemas/source/**; static/schemas/source/core/media-buy-features.json (modified) matchesstatic/schemas/source/**; static/schemas/source/core/media-buy.json (modified) matchesstatic/schemas/source/**; static/schemas/source/core/optimization-goal.json (modified) matchesstatic/schemas/source/**; static/schemas/source/core/package.json (modified) matchesstatic/schemas/source/**; static/schemas/source/core/planned-delivery.json (modified) matchesstatic/schemas/source/**; static/schemas/source/core/pricing-option.json (modified) matchesstatic/schemas/source/**; static/schemas/source/core/product-allocation.json (modified) matchesstatic/schemas/source/**; static/schemas/source/core/proposal.json (modified) matchesstatic/schemas/source/**; static/schemas/source/enums/error-code.json (modified) matchesstatic/schemas/source/**; static/schemas/source/enums/media-buy-valid-action.json (modified) matchesstatic/schemas/source/**; static/schemas/source/index.json (modified) matchesstatic/schemas/source/**; static/schemas/source/media-buy/create-media-buy-request.json (modified) matchesstatic/schemas/source/**; static/schemas/source/media-buy/create-media-buy-response.json (modified) matchesstatic/schemas/source/**; static/s
…(truncated)…
There was a problem hiding this comment.
Ladon verdict: Escalate to human review
Escalate — gated protocol-source paths require human/CODEOWNERS approval that is not yet recorded.
This is a subsequent pass on the shared-budgets / bidding-policy PR. Both prior Medium findings are now resolved:
- get_media_buys.mdx now documents packages[].pacing / min_spend_target / bidding (get_media_buys.mdx:674-681) matching get-media-buys-response.json.
- The package-request budget-removal is re-guarded by the create-media-buy-request anyOf fixed branch (create-media-buy-request.json:2008-2099) and the update-media-buy-request new_packages conditional (update-media-buy-request.json:2510-2535), with rejection tests at composed-schema-validation.test.cjs:2841/2859/2875.
Reviewer reports no new blocking or Medium findings in the delta. The diff is mechanically clean. However, this PR modifies/adds files under static/schemas/source/** — a hard, non-overridable approval gate — and review_decision is not APPROVED (unknown/none). Per decision-table row 2, the gate is not satisfied and the outcome must be escalate. A human/CODEOWNERS approval must be recorded before this can merge. This also carries new protocol surface (new fields, new bidding-policy / budget-allocation schemas, new conformance scenarios), which under the constitution's breaking-class posture likewise requires human ratification rather than auto-approval.
Escalation reasons
- Touches gated protocol source under static/schemas/source/** (e.g. bidding-policy.json, budget-allocation.json, media-buy.json, proposal.json, package.json) — hard approval gate; review_decision is not APPROVED. Human/CODEOWNERS review required.
- Adds new normative protocol surface (new fields, new schemas, new conformance scenarios) — spec ratification is a human act, not auto-approvable.
Why human review
- Touches gated protocol source under static/schemas/source/** (bidding-policy.json, budget-allocation.json, media-buy.json, proposal.json, package.json, and 20+ others) — hard approval gate; review_decision is not APPROVED (unknown/none). Human/CODEOWNERS review required before merge.
- Adds new normative protocol surface (new bidding-policy and budget-allocation schemas, new fields, new capability-gated conformance scenarios) — spec ratification is a human act and is never auto-approved absent an APPROVED review.
- This PR touches a path under a hard, non-overridable approval gate (static/schemas/source/core/bidding-policy.json (added) matches
static/schemas/source/**; static/schemas/source/core/budget-allocation.json (added) matchesstatic/schemas/source/**; static/schemas/source/core/media-buy-features.json (modified) matchesstatic/schemas/source/**; static/schemas/source/core/media-buy.json (modified) matchesstatic/schemas/source/**; static/schemas/source/core/optimization-goal.json (modified) matchesstatic/schemas/source/**; static/schemas/source/core/package.json (modified) matchesstatic/schemas/source/**; static/schemas/source/core/planned-delivery.json (modified) matchesstatic/schemas/source/**; static/schemas/source/core/pricing-option.json (modified) matchesstatic/schemas/source/**; static/schemas/source/core/product-allocation.json (modified) matchesstatic/schemas/source/**; static/schemas/source/core/proposal.json (modified) matchesstatic/schemas/source/**; static/schemas/source/enums/error-code.json (modified) matchesstatic/schemas/source/**; static/schemas/source/enums/media-buy-valid-action.json (modified) matchesstatic/schemas/source/**; static/schemas/source/index.json (modified) matchesstatic/schemas/source/**; static/schemas/source/media-buy/create-media-buy-request.json (modified) matchesstatic/schemas/source/**; static/schemas/source/media-buy/create-media-buy-response.json (modified) matchesstatic/schemas/source/**; static/schemas/source/media-buy/get-media-buy-delivery-response.json (modified) matchesstatic/schemas/source/**; static/schemas/s
…(truncated)…
There was a problem hiding this comment.
Ladon verdict: Escalate to human review
Escalate — gated protocol source under hard approval gate; human/CODEOWNERS review required.
This PR adds new normative protocol surface to static/schemas/source/** (new bidding-policy.json and budget-allocation.json schemas, new fields, new error codes, and new capability-gated conformance scenarios). Under this repo's constitution, adding new normative protocol surface — new schemas, new fields, new enum/error codes — is a spec-ratification act that is never auto-approved.
Decision-table trigger (row 2): gated_paths: true AND review_decision is not APPROVED (unknown/none). This is a hard, deterministic, code-enforced gate — Ladon cannot auto-approve until a human/CODEOWNERS approval is recorded, regardless of how clean the diff is.
Reviewer findings: none. The delta since the prior pass only adds two well-formed disposition entries (AMBIGUOUS_BIDDING_POLICY, BIDDING_PLACEMENT_CONFLICT) to scripts/error-code-drift-dispositions.json — both held-for-next-minor / target_version 3.2, present in the source enum, satisfying the lint contract. No new critical/high/medium findings. The prior escalate stands purely on the unsatisfied gate, not on a fresh defect.
Escalation reasons
- Touches gated protocol source under
static/schemas/source/**(bidding-policy.json, budget-allocation.json, media-buy.json, proposal.json, package.json, pricing-options/*, and 20+ others) — hard approval gate;review_decisionis not APPROVED. Human/CODEOWNERS review required before merge. - Adds new normative protocol surface (new schemas, new fields, new error codes, new conformance scenarios) — spec ratification is a human act and is never auto-approved absent an APPROVED review.
Once a human/CODEOWNERS APPROVED review is recorded, this clean diff can fall through to normal approval.
Why human review
- Touches gated protocol source under static/schemas/source/** (bidding-policy.json, budget-allocation.json, media-buy.json, proposal.json, package.json, pricing-options/*, and 20+ others) — hard approval gate; review_decision is not APPROVED (unknown/none). Human/CODEOWNERS review required before merge.
- Adds new normative protocol surface (new bidding-policy and budget-allocation schemas, new fields, new error codes, new capability-gated conformance scenarios) — spec ratification is a human act and is never auto-approved absent an APPROVED review.
- This PR touches a path under a hard, non-overridable approval gate (static/schemas/source/core/bidding-policy.json (added) matches
static/schemas/source/**; static/schemas/source/core/budget-allocation.json (added) matchesstatic/schemas/source/**; static/schemas/source/core/media-buy-features.json (modified) matchesstatic/schemas/source/**; static/schemas/source/core/media-buy.json (modified) matchesstatic/schemas/source/**; static/schemas/source/core/optimization-goal.json (modified) matchesstatic/schemas/source/**; static/schemas/source/core/package.json (modified) matchesstatic/schemas/source/**; static/schemas/source/core/planned-delivery.json (modified) matchesstatic/schemas/source/**; static/schemas/source/core/pricing-option.json (modified) matchesstatic/schemas/source/**; static/schemas/source/core/product-allocation.json (modified) matchesstatic/schemas/source/**; static/schemas/source/core/proposal.json (modified) matchesstatic/schemas/source/**; static/schemas/source/enums/error-code.json (modified) matchesstatic/schemas/source/**; static/schemas/source/enums/media-buy-valid-action.json (modified) matchesstatic/schemas/source/**; static/schemas/source/index.json (modified) matchesstatic/schemas/source/**; static/schemas/source/media-buy/create-media-buy-request.json (modified) matchesstatic/schemas/source/**; static/schemas/source/media-buy/create-media-buy-response.json (modified) matchesstatic/schemas/source/**; static/schemas/source/media-buy/get-media-buy-del
…(truncated)…
There was a problem hiding this comment.
Ladon verdict: Escalate to human review
Escalate — hard approval gate on protocol source, and Breaking-class/normative-surface ratification requires human review.
This PR touches gated protocol source under static/schemas/source/** (added bidding-policy.json, budget-allocation.json; modified media-buy.json, proposal.json, package.json, pricing-options/*, enums/error-code.json, and 20+ others). gated_paths: true and review_decision: REVIEW_REQUIRED (not APPROVED), so the deterministic hard gate (decision-table row 2) is not satisfied.
The reviewer found no blocking findings: the package-update bid_price/bidding mutual-exclusion delta is correct (null bidding may accompany bid_price or a legacy monetary optimization-goal target for atomic migration; a non-null canonical bidding block still conflicts), the not.anyOf/if-then guards correctly gate on bidding being type:object, update_media_buy.mdx matches with no schema↔docs drift, and four added schema tests isolate the two accept and two reject paths. A changeset is present. Clean pass on content.
However, this adds new normative protocol surface (new schemas, new fields, new error codes, new capability-gated conformance scenarios) — spec ratification is a human act and is never auto-approved absent an APPROVED review. Prior decision was also escalate for the same gate. A human/CODEOWNERS approval is required before merge.
Escalation reasons
- Gated file(s) under
static/schemas/source/**withreview_decision: REVIEW_REQUIRED(not APPROVED) — human/CODEOWNERS review required (decision row 2). - Adds new normative protocol surface (new bidding-policy/budget-allocation schemas, new fields, new error codes, new conformance scenarios) — spec ratification is a human act, never auto-approved absent an APPROVED review.
Why human review
- Gated protocol source under static/schemas/source/** (bidding-policy.json, budget-allocation.json, media-buy.json, proposal.json, package.json, pricing-options/*, error-code.json, and 20+ others) is under a hard, non-overridable approval gate and review_decision is REVIEW_REQUIRED, not APPROVED — human/CODEOWNERS review required before merge.
- Adds new normative protocol surface (new schemas, new fields, new error codes, new capability-gated conformance scenarios) — spec ratification is a human act and is never auto-approved absent an APPROVED review.
- This PR touches a path under a hard, non-overridable approval gate (static/schemas/source/core/bidding-policy.json (added) matches
static/schemas/source/**; static/schemas/source/core/budget-allocation.json (added) matchesstatic/schemas/source/**; static/schemas/source/core/media-buy-features.json (modified) matchesstatic/schemas/source/**; static/schemas/source/core/media-buy.json (modified) matchesstatic/schemas/source/**; static/schemas/source/core/optimization-goal.json (modified) matchesstatic/schemas/source/**; static/schemas/source/core/package.json (modified) matchesstatic/schemas/source/**; static/schemas/source/core/planned-delivery.json (modified) matchesstatic/schemas/source/**; static/schemas/source/core/pricing-option.json (modified) matchesstatic/schemas/source/**; static/schemas/source/core/product-allocation.json (modified) matchesstatic/schemas/source/**; static/schemas/source/core/proposal.json (modified) matchesstatic/schemas/source/**; static/schemas/source/enums/error-code.json (modified) matchesstatic/schemas/source/**; static/schemas/source/enums/media-buy-valid-action.json (modified) matchesstatic/schemas/source/**; static/schemas/source/index.json (modified) matchesstatic/schemas/source/**; static/schemas/source/media-buy/create-media-buy-request.json (modified) matchesstatic/schemas/source/**; static/schemas/source/media-buy/create-media-buy-response.json (modified) matchesstatic/schemas/source/**; static/schemas/source/media-buy/get-media-buy-delivery-response.jso
…(truncated)…
|
Issue #6106 proposes an explicit Generated by Claude Code |
Closes #6106
Summary
BudgetAllocationmodel with backward-compatible fixed allocation and seller-optimized shared budgetsBiddingPolicyat media-buy and package scope for manual bids, auction ceilings, average-cost controls, and ROAS controlsMotivation
AdCP 3.1 requires explicit package budgets and splits buyer price intent across package
bid_price, pricing-optionmax_bid, and monetaryoptimization_goalstargets. Platforms that optimize one campaign budget and strategy across multiple ad sets or line items cannot express that behavior without vendor extensions.This gives 3.2 one portable placement story: objective functions stay in
optimization_goals; budget allocation, pacing, and bidding execution policy live at the scope where they are authored.Budget semantics
total_budgetis the hard aggregate lifetime capbudgetremains a hard cap, never a current allocationmin_spend_targetis softadd_packagesupdates keep package budgets required; uncapped additions require explicit seller-optimized allocation contextBidding semantics
biddingis a complete inherited default; packagebiddingis a complete override, never a field mergebid_amountis a manual auction bid;max_bidis the only hard per-auction ceilingcost_perdistinguishes averagecapfromtarget;roasdistinguishesfloorfromtargetcost_perresolves against the primary optimization goal, whilebid_amount/max_bidresolve against the selected pricing option's auction unitBIDDING_PLACEMENT_CONFLICTAMBIGUOUS_BIDDING_POLICYmax_bid, packagebid_price, and monetary goal targets are deprecated with deterministic normalization rulesValidation
Notes
Daily/hourly caps remain out of scope; the new budget is a lifetime media-buy total. The bidding block represents numeric portfolio policy but not shared provider portfolio identity or lifecycle across media buys; that requires a future provider-neutral resource/reference.