Skip to content

feat(schema): add brief stage context to get_products#5521

Closed
bokelley wants to merge 1 commit into
mainfrom
intent-horizon-date-range
Closed

feat(schema): add brief stage context to get_products#5521
bokelley wants to merge 1 commit into
mainfrom
intent-horizon-date-range

Conversation

@bokelley

@bokelley bokelley commented Jun 14, 2026

Copy link
Copy Markdown
Contributor

Summary

Adds optional brief_stage to get_products requests so buyers can declare where a brief sits in the pre-buy lifecycle without using the overloaded intent language.

The new context includes:

  • phase: exploratory, planning, or active_sourcing
  • planning_horizon: advisory ISO date range for the opportunity
  • response_deadline: advisory seller response/proposal update deadline

The schema and docs make absence mean unknown, scope the field to brief/refine requests, require sellers to ignore it for wholesale, and prohibit using brief_stage for price, rate card, product eligibility, inventory availability, or buyability.

Expert review follow-up

Ran protocol, product/operator, and docs expert review. Follow-up changes tightened:

  • response_deadline so it cannot imply firm pricing, availability confirmation, inventory hold, finalization, or commitment
  • active_sourcing so it only means requesting seller responses/proposals
  • commitment wording so seller proposal finalization and buyer execution via create_media_buy stay separate
  • schema wording so wholesale ignore semantics are explicit
  • regression fixtures for valid full/minimal brief_stage, missing phase, and empty planning_horizon

Final expert confirmation found no remaining protocol, product/operator, or docs clarity issues.

Validation

  • npm run test:schemas
  • npm run test:examples
  • npm run test:json-schema
  • npm run build:schemas
  • npm run test:json-schema -- --file docs/media-buy/task-reference/get_products.mdx
  • npx --yes @changesets/cli@^2.31.0 status --since=origin/main
  • node scripts/check-pr-title.cjs "feat(schema): add brief stage context to get_products"
  • Push hook passed: version sync, changeset check, schema-link convention, Mintlify broken-links check

Notes:

  • npm run test:snippets -- --file docs/media-buy/task-reference/get_products.mdx still fails on pre-existing executable snippets in that page: missing local Python adcp package, an existing CommonJS named-export issue, an existing TypeScript non-null assertion parsed as JavaScript, and an existing property_list snippet timeout. The new JSON example is schema-backed and passed test:json-schema.
  • The original pre-commit hook was bypassed after npm run test:unit failed in unrelated server/tests/unit/conformance-end-to-end.test.ts (evicts the session when the adopter disconnects, expected session to be undefined after 100ms).

@mintlify

mintlify Bot commented Jun 14, 2026

Copy link
Copy Markdown

Preview deployment for your docs. Learn more about Mintlify Previews.

Project Status Preview Updated (UTC)
adcp 🟢 Ready View Preview Jun 14, 2026, 2:12 PM

💡 Tip: Enable Workflows to automatically generate PRs for you.

@bokelley bokelley force-pushed the intent-horizon-date-range branch from a16a4f4 to 2ea41a2 Compare June 14, 2026 13:52
@bokelley bokelley marked this pull request as ready for review June 14, 2026 14:02

@aao-release-bot aao-release-bot 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.

Clean additive change. Optional field on additionalProperties: true request, scoped to brief/refine with wholesale-ignore in prose — old clients and old sellers both stay valid, so minor is the right shape.

Things I checked

  • Wire impact matches the changeset. brief_stage is an optional property; the request top level is additionalProperties: true and only buying_mode is required. No existing field, enum, or required-list touched. minor is correct (playbook L331: "add optional fields"). ad-tech-protocol-expert: sound.
  • Schema construction. planning_horizon uses anyOf: [{required:[start]},{required:[end]}] + additionalProperties:false as siblings — additionalProperties doesn't reach into the anyOf branches (which carry only required, no properties), so they compose cleanly. Empty planning_horizon: {} correctly fails both branches. code-reviewer: clean.
  • Test assertions are valid for the AJV in use. Missing-phase asserts substring phase (from must have required property 'phase' at /brief_stage); empty-horizon asserts must match a schema in anyOf — both AJV v8 defaults. Both expectInvalid cases fail purely on brief_stage constraints, not on the brief-required rule (which is prose-only, not schema-enforced), so neither passes for the wrong reason.
  • Schema↔docs coherence. get_products.mdx table (phase Yes, start/end No*, response_deadline No), the footnote, the enum prose, and the MUST/MUST NOT seller rules match the schema one-to-one. The docs JSON example is byte-for-byte the passing validateExample fixture.
  • No oneOf concern. Top level is allOf + one wholesale if/then; brief_stage is a plain nested object, no discriminated union added. No baseline ratchet needed.
  • Right boundary on commitment. Field text keeps advisory metadata out of pricing/eligibility/availability and points commitment back at proposal finalize and create_media_buy. Mirrors the existing push_notification_config scoping precedent in the same file.

Follow-ups (non-blocking — file as issues)

  • Docs row types the field as BriefStage (a named type), but the schema defines it inline. AdCP convention for reusable typed objects is a $ref (BrandRefaccount-ref.json). It's not reused yet, so inline is fine — but if another task is expected to reference brief stage later, extract to /schemas/core/brief-stage.json now to match prior art (ad-tech-protocol-expert).
  • The "buyer intent" → "product discovery mode" rewording is partial: the top-level and buying_mode descriptions were changed, but the refine description still says "the buyer expressing intent to commit." Cosmetic, but if retiring the overloaded term was the goal, the pass is incomplete.

Minor nits (non-blocking)

  1. Loose error-substring assertion. tests/example-validation-simple.test.cjs missing-phase case asserts ['phase'] — would also match an unrelated error mentioning phase. ["must have required property 'phase'"] is tighter. Non-blocking.

On test-plan honesty: the PR notes test:snippets still fails on that page, but the failures are pre-existing (missing local adcp Python package, a CJS named-export issue, a TS-parsed-as-JS assertion, a property_list timeout) — not the new field, which is schema-backed and passes test:json-schema. Worth noting the pre-commit hook was bypassed on an unrelated conformance-end-to-end flake; the wire-touching path here is covered by the schema and example tests.

LGTM. Follow-ups noted below.

@bokelley

Copy link
Copy Markdown
Contributor Author

Closing because this narrower brief-stage shape has been subsumed by PR #5523. The replacement model uses optional opportunity context across get_products and create_media_buy, so the same planning-cycle identifier can connect exploratory briefs, refinement, proposal outcomes, accepted buys, and closed opportunities.

@bokelley bokelley closed this Jun 15, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant