feat(reporting): negotiated contracts for automatic breakdowns - #6627
feat(reporting): negotiated contracts for automatic breakdowns#6627bokelley wants to merge 4 commits into
Conversation
by_creative, by_keyword, and by_catalog_item were returned automatically with no limit, sort, or truncation disclosure, so "top creatives by quartile_100" had no completeness contract. Including their keys in reporting_dimensions now upgrades them to the negotiated contract: limit/sort_by/sort_direction honored, by_X_truncated and the applied-sort echo become binding. Omitting the keys preserves the automatic behavior exactly — the MUSTs are scoped to request-key presence, so existing automatic emissions stay conformant. The new dimensions carry the full deterministic sort semantics (row-grain fallback, nulls-last, direction MUST). Implements RFC #6623. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
There was a problem hiding this comment.
Ladon verdict: Escalate to human review
Escalate — gated schema paths require human/CODEOWNERS approval.
This PR modifies two published protocol schema files under static/schemas/source/**:
get-media-buy-delivery-request.jsonget-media-buy-delivery-response.json
gated_paths is true and review_decision is not APPROVED (unknown/none), so the hard approval gate (decision rule row 2) fires: the outcome must be escalate, not approve.
The change itself looks clean per the reviewer: an additive, backward-compatible minor (RFC #6623) making automatic creative/keyword/catalog_item breakdowns optionally negotiable via reporting_dimensions, with a dual MUST/RECOMMENDED contract keyed to request-key presence. Schema↔docs coherence holds, reporting_dimensions is additionalProperties:true, echo/truncation MUSTs bind to request-key presence, and a correct minor changeset is present. No blocking or Medium findings were raised.
Nonetheless, the gated schema paths require an explicit human/CODEOWNERS approval before merge. Once review_decision becomes APPROVED, this PR can fall through to a normal approve on its clean diff.
Why human review
- Modifies gated schema file static/schemas/source/media-buy/get-media-buy-delivery-request.json — human/CODEOWNERS review required (review_decision is not APPROVED)
- Modifies gated schema file static/schemas/source/media-buy/get-media-buy-delivery-response.json — human/CODEOWNERS review required (review_decision is not APPROVED)
- This PR touches a path under a hard, non-overridable approval gate (static/schemas/source/media-buy/get-media-buy-delivery-request.json (modified) matches
static/schemas/source/**; static/schemas/source/media-buy/get-media-buy-delivery-response.json (modified) matchesstatic/schemas/source/**) and the current GitHub review decision is 'unknown', not APPROVED. This is a hard gate enforced in code — Ladon cannot auto-approve until a human/CODEOWNERS approval is recorded, regardless of how clean the diff is.
There was a problem hiding this comment.
Ladon verdict: Escalate to human review
Escalate — gated schema files touched without a recorded APPROVED review.
This PR modifies two files under the hard, non-overridable approval gate static/schemas/source/**:
static/schemas/source/media-buy/get-media-buy-delivery-request.jsonstatic/schemas/source/media-buy/get-media-buy-delivery-response.json
gated_paths is true and review_decision is not APPROVED (unknown/none). Per decision-table row 2, the outcome must be escalate until a human/CODEOWNERS approval is recorded. This is a mechanical, path-based gate — a clean diff cannot lift it.
Findings: none. The reviewer confirms the delta since the prior clean pass is description-only refinements to requested_metrics cross-referencing reporting-webhook.json and the delivery-request field. Descriptions match their schemas and each other; no wire-shape, required[], or enum changes; nothing blocking or Medium.
Escalation reasons: hard gated-path approval requirement, pending human review. Once review_decision becomes APPROVED, this clean diff falls through to approve.
Why human review
- Modifies gated schema file static/schemas/source/media-buy/get-media-buy-delivery-request.json — human/CODEOWNERS review required (review_decision is not APPROVED)
- Modifies gated schema file static/schemas/source/media-buy/get-media-buy-delivery-response.json — human/CODEOWNERS review required (review_decision is not APPROVED)
- This PR touches a path under a hard, non-overridable approval gate (static/schemas/source/media-buy/get-media-buy-delivery-request.json (modified) matches
static/schemas/source/**; static/schemas/source/media-buy/get-media-buy-delivery-response.json (modified) matchesstatic/schemas/source/**) and the current GitHub review decision is 'unknown', not APPROVED. This is a hard gate enforced in code — Ladon cannot auto-approve until a human/CODEOWNERS approval is recorded, regardless of how clean the diff is.
Verification review: two task-reference sentences stated unconditional
MUSTs ("whenever the corresponding breakdown array is present") that
the schema correctly scopes to request-key presence — the unconditional
form would retroactively bind automatic creative/keyword/catalog_item
emissions. Docs now match the schema contract.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
There was a problem hiding this comment.
Ladon verdict: Escalate to human review
Escalate — gated schema paths modified without an APPROVED review decision.
This PR modifies two files under static/schemas/source/**, which sit behind a hard, deterministic approval gate (gated_paths: true). The current review_decision is unknown/none, not APPROVED, so the gate is not satisfied and Ladon cannot auto-approve regardless of how clean the diff is (decision rule row 2).
The reviewer found no critical/high/medium issues: the delta since the prior clean pass is two prose/description clarifications. get_media_buy_delivery.mdx scopes the echo/truncation MUST to requested dimensions and marks automatic creative/keyword/catalog_item fields RECOMMENDED, coherent with the response schema verbatim. The webhook requested_metrics empty==omitted definition agrees with the get_media_buy_delivery cross-reference. No schema drift, no wire-shape change, changeset present. This mirrors the prior escalate, which persists here on the gate alone (not sticky row 6 — there are no fresh findings, but row 2 fires independently and deterministically).
Escalation reasons
- Modifies gated schema file
static/schemas/source/media-buy/get-media-buy-delivery-request.json— human/CODEOWNERS review required (review_decision not APPROVED). - Modifies gated schema file
static/schemas/source/media-buy/get-media-buy-delivery-response.json— human/CODEOWNERS review required (review_decision not APPROVED).
Once a human/CODEOWNERS approval is recorded, this PR can fall through to a normal approve on its clean diff.
Why human review
- Modifies gated schema file static/schemas/source/media-buy/get-media-buy-delivery-request.json under static/schemas/source/** — human/CODEOWNERS review required because review_decision is not APPROVED
- Modifies gated schema file static/schemas/source/media-buy/get-media-buy-delivery-response.json under static/schemas/source/** — human/CODEOWNERS review required because review_decision is not APPROVED
- This PR touches a path under a hard, non-overridable approval gate (static/schemas/source/media-buy/get-media-buy-delivery-request.json (modified) matches
static/schemas/source/**; static/schemas/source/media-buy/get-media-buy-delivery-response.json (modified) matchesstatic/schemas/source/**) and the current GitHub review decision is 'unknown', not APPROVED. This is a hard gate enforced in code — Ladon cannot auto-approve until a human/CODEOWNERS approval is recorded, regardless of how clean the diff is.
Summary
Top of the stack (#6618 → #6622 → #6626 → this; bases retarget as the stack merges). Implements RFC #6623.
by_creative,by_keyword, andby_catalog_itemwere returned automatically with nolimit,sort_by, or truncation disclosure — so "top creatives byquartile_100" (sortable as of #6618) had no completeness contract, and a seller returning 50 of 500 creative rows couldn't say which 50 or whether the list was complete.The dual contract
{}):limit/sort_by/sort_directionare honored, andby_X_truncated+ the applied-sort echo (by_X_sorted_by/by_X_sort_direction) become MUST.The per-review scoping matters: the echo/truncation MUSTs bind to request-key presence, not array presence — an unconditional MUST would have retroactively broken every existing automatic emission. Since
reporting_dimensionsisadditionalProperties: true, pre-3.2 sellers silently ignore the new keys; the applied-sort echo is therefore the capability-detection signal (its absence on a keyed request means the seller doesn't implement negotiation).The three dimensions carry the full deterministic sort semantics from #6622 (row-grain fallback, nulls-last ordering, direction MUST), and the schema-derived invariant test in the sort-contract suite automatically covers them — a sortable dimension can no longer ship without the echo contract.
Relationship: #5671 (breakdown continuation) remains the complement — sort+limit gets the top-N, continuation gets the rest; both share truncation semantics.
🤖 Generated with Claude Code