Skip to content

feat(media-buy): add committed collection selection to targeting - #7079

Merged
bokelley merged 3 commits into
mainfrom
collection-selection-echo
Aug 31, 2026
Merged

feat(media-buy): add committed collection selection to targeting#7079
bokelley merged 3 commits into
mainfrom
collection-selection-echo

Conversation

@bokelley

Copy link
Copy Markdown
Contributor

What

Adds targeting_overlay.collection_selection, mirroring placement_selection, plus domain-qualified identity on resolved collection-list rows.

  • core/collection-selection.jsonmode: "selected" names the complete required collection set as domain-qualified selectors with explicit collection_ids (partial selection gated by product collection_targeting_allowed; exact full-bundle restatement is an inherent match; the domain-only bulk-grant selector form stays authorization-only). mode: "default" accepts the product's full bundle.
  • Package readback: sellers MUST echo the committed selection in collection_selection, materializing the result of any collection_list composition — making the existing package.targeting_overlay collection-echo obligation satisfiable. For a channel buy this is the audit surface for the axis that makes the product distinct.
  • Resolved list rows (get-collection-list-response) can carry publisher_domain + collection_id, so a row whose only host identifier is a platform_channel_id stays matchable ((publisher_domain, collection_id) tuple identity).

Why

Closes #7050package.targeting_overlay said sellers MUST echo collection selection, but targeting.json had no field to write it in; buyers of collection-scoped products (notably kind: "channel" from #6897) could not audit what they bought without re-fetching the product catalog. Partially addresses #7051 (resolved-row identity; the tuple-carrying exclusion arm remains open for WG discussion).

Budget note (deliberate)

The shared inventory-selection graph bundles ~0.7 KiB into each targeting-bearing media-buy request schema. Two budget lines move as measured, commented increases (not headroom): model-context ceiling 400 → 405 KiB, compact four-tool discovery bound 133 → 135 KiB. Schema-analysis pins advance accordingly (601→611 instances, 157→159 unique defs, 113→115 repeated).

Testing

  • New tests/collection-selection-echo.test.cjs (5 spec-anchored schema tests: selected/default modes, bulk-grant rejection in selection, empty-set/unknown-mode rejection, resolved-row identity), wired into the main chain.
  • MCP projection suite 27/27, targeting overlay vectors, targeting-aware discovery, update-media-buy lint, storyboard doc parity, json-schema (278), composed, oneof — all green. Typecheck clean.

🤖 Generated with Claude Code

targeting_overlay.collection_selection mirrors placement_selection:
mode selected names the complete required collection set as
domain-qualified selectors with explicit collection_ids (partial
selection gated by product collection_targeting_allowed; the domain-only
bulk-grant selector form stays authorization-only), and mode default
accepts the product's full bundle. On package readback sellers MUST
echo the committed selection here, materializing the result of any
collection_list composition — which makes the existing package
collection-echo obligation satisfiable and gives channel buys an audit
surface for the axis that makes them distinct.

Resolved collection-list rows can now carry the domain-qualified
identity (publisher_domain + collection_id) so a row stays matchable
when no platform-independent distribution identifier exists.

The shared inventory-selection graph adds ~0.7 KiB to each
targeting-bearing media-buy request schema. Two measured, commented
budget increases carry it: the model-context ceiling moves 400 → 405
KiB and the compact four-tool discovery bound moves 133 → 135 KiB;
schema-analysis pins advance accordingly.

Closes #7050. Partially addresses #7051 (resolved-row identity; the
tuple-carrying exclusion arm remains open).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Comment thread static/schemas/source/core/collection-selection.json Outdated
@aao-secretariat aao-secretariat Bot added the ladon/needs-human-review Ladon has escalated this PR for human review. label Aug 30, 2026

@aao-secretariat aao-secretariat Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ladon verdict: Escalate to human review

Escalate — gated schema paths require human/CODEOWNERS review.

This PR is a clean additive Normative change: it adds targeting_overlay.collection_selection (mirroring placement_selection) and adds (publisher_domain, collection_id) identity on resolved collection-list rows. The reviewer verified changeset scope/type (minor, correct), a properly discriminated oneOf (on mode), schema↔docs coherence, immutable artifacts, and confirmed no wire break. Only one non-blocking Low finding was noted inline (collection_selection.collections omits the uniqueItems constraint its placement_refs mirror enforces) — not a blocker.

The diff modifies multiple files under static/schemas/source/**, which the repo declares as gated paths (hard approval gate). gated_paths: true and review_decision: REVIEW_REQUIRED (not APPROVED), so decision rule row 2 fires: the gate is not satisfied and the outcome must be escalate until a human/CODEOWNERS approval lands.

Escalation reasons

  • Modifies gated schema source files under static/schemas/source/** (get-collection-list-response.json, core/collection-selection.json [added], core/package.json, core/product.json, core/targeting.json, media-buy/get-media-buys-response.json) while review_decision is REVIEW_REQUIRED. Human/CODEOWNERS approval required before merge.

No blocking (critical/high) findings exist; the escalation is purely the deterministic gated-paths gate.

Why human review

  • Gated paths touched (static/schemas/source/**) with review_decision REVIEW_REQUIRED, not APPROVED — human/CODEOWNERS approval required before merge (decision rule row 2).
  • This PR touches a path under a hard, non-overridable approval gate (static/schemas/source/collection/get-collection-list-response.json (modified) matches static/schemas/source/**; static/schemas/source/core/collection-selection.json (added) matches static/schemas/source/**; static/schemas/source/core/package.json (modified) matches static/schemas/source/**; static/schemas/source/core/product.json (modified) matches static/schemas/source/**; static/schemas/source/core/targeting.json (modified) matches static/schemas/source/**; static/schemas/source/media-buy/get-media-buys-response.json (modified) matches static/schemas/source/**) and the current GitHub review decision is 'REVIEW_REQUIRED', 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.

Mirror placement_selection.placement_refs: uniqueItems alongside
minItems, so an exact-duplicate selector fails at schema level instead
of delegating dedup entirely to the seller. Overlapping (non-identical)
selectors remain seller-rejected per the selection contract.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

@aao-secretariat aao-secretariat Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ladon verdict: Escalate to human review

Escalate — gated schema paths touched and no human/CODEOWNERS approval recorded.

This PR modifies/adds files under static/schemas/source/**, which is a hard, deterministic approval gate (gated_paths: true). The current review_decision is unknown/none — not APPROVED — so decision rule row 2 fires: the gate is not satisfied and Ladon cannot auto-approve regardless of how clean the diff is.

The delta since the prior clean pass is additive and correct: it adds uniqueItems: true (plus minItems: 1 parity) to the collections array in the new collection-selection.json and a test asserting exact-duplicate selectors are rejected, bringing it into parity with placement-selection.json. This is on a not-yet-released 3.2 schema with its minor changeset already present. The reviewer found no Critical/High/Medium findings and no schema↔docs drift.

Blocking findings: none.

Medium findings: none.

Escalation reasons:

  • Gated paths touched (static/schemas/source/**) with review_decision not APPROVED — human/CODEOWNERS approval required before merge (decision rule row 2). Gated files include static/schemas/source/core/collection-selection.json (added) and static/schemas/source/core/product.json, targeting.json, package.json, get-collection-list-response.json, get-media-buys-response.json (modified).

Once a human/CODEOWNERS approval is recorded, this clean diff can fall through to approve.

Why human review

  • Gated paths touched (static/schemas/source/**) with review_decision not APPROVED — human/CODEOWNERS approval required before merge (decision rule row 2). Gated files: static/schemas/source/core/collection-selection.json (added), plus product.json, targeting.json, package.json, get-collection-list-response.json, get-media-buys-response.json (modified).
  • This PR touches a path under a hard, non-overridable approval gate (static/schemas/source/collection/get-collection-list-response.json (modified) matches static/schemas/source/**; static/schemas/source/core/collection-selection.json (added) matches static/schemas/source/**; static/schemas/source/core/package.json (modified) matches static/schemas/source/**; static/schemas/source/core/product.json (modified) matches static/schemas/source/**; static/schemas/source/core/targeting.json (modified) matches static/schemas/source/**; static/schemas/source/media-buy/get-media-buys-response.json (modified) matches static/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.

…echo

# Conflicts:
#	package.json
#	tests/mcp-schema-analysis.test.cjs

@aao-secretariat aao-secretariat Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ladon verdict: Escalate to human review

Escalate — gated paths touched without an APPROVED review decision.

This PR modifies/adds files under static/schemas/source/**, which are under a hard, non-overridable approval gate (gated_paths: true). The current review_decision is unknown/none — not APPROVED — so decision rule row 2 forces escalation. A human/CODEOWNERS approval must be recorded before this can merge.

Blocking findings

  • None.

Medium findings

  • None. The reviewer reports a clean pass: head e231fdb is a merge-only update (parents = prior-reviewed head 57fc1f5 + main tip 877f6a2). The collection_selection schema contribution is unchanged and intact; the delta is pure main catch-up already reviewed on merge.

Escalation reasons

  • Gated paths touched (static/schemas/source/**) with review_decision not APPROVED — human/CODEOWNERS approval required. Gated files: static/schemas/source/core/collection-selection.json (added), plus product.json, targeting.json, package.json, collection/get-collection-list-response.json, media-buy/get-media-buys-response.json (modified).

Note: the prior decision was also escalate for the identical gate reason. No fresh critical/high/medium findings exist, but the gate itself is a deterministic path-based hard gate independent of findings — it persists until an APPROVED review is recorded.

Why human review

  • Gated paths touched (static/schemas/source/**) with review_decision not APPROVED — human/CODEOWNERS approval required before merge (decision rule row 2). Gated files: static/schemas/source/core/collection-selection.json (added), plus product.json, targeting.json, package.json, get-collection-list-response.json, get-media-buys-response.json (modified).
  • This PR touches a path under a hard, non-overridable approval gate (static/schemas/source/collection/get-collection-list-response.json (modified) matches static/schemas/source/**; static/schemas/source/core/collection-selection.json (added) matches static/schemas/source/**; static/schemas/source/core/package.json (modified) matches static/schemas/source/**; static/schemas/source/core/product.json (modified) matches static/schemas/source/**; static/schemas/source/core/targeting.json (modified) matches static/schemas/source/**; static/schemas/source/media-buy/get-media-buys-response.json (modified) matches static/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.

@bokelley
bokelley merged commit 93d39c0 into main Aug 31, 2026
62 checks passed
@bokelley
bokelley deleted the collection-selection-echo branch August 31, 2026 06:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ladon/needs-human-review Ladon has escalated this PR for human review.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Package readback: targeting has no collections field, making the collection-echo MUST unsatisfiable

1 participant