Skip to content

feat(negotiation): complete proposal refinement API gaps - #38

Open
garvitkaushik-123 wants to merge 3 commits into
adcontextprotocol:mainfrom
garvitkaushik-123:feat/negotiation-gaps
Open

feat(negotiation): complete proposal refinement API gaps#38
garvitkaushik-123 wants to merge 3 commits into
adcontextprotocol:mainfrom
garvitkaushik-123:feat/negotiation-gaps

Conversation

@garvitkaushik-123

Copy link
Copy Markdown

Summary

  • Adds TotalBudgetConstraint, RefinementConstraints composite type, and missing constraints/productChanges/alternatives fields to ProposalRefinement — closing the typed-constraint gap tracked in epic: make proposal negotiation easy to implement, teach, and verify adcp#6556
  • Enforces protocol max 10 alternatives and seller-advertised ceiling in the request builder
  • Adds verifyConstraintSatisfaction to ResponseVerifier — checks budget bounds and CPM ceiling on revised outcomes
  • Adds server-side ProposalSuccessor utility for stamping immutable successor proposals with lineage and recomputed terms_digest
  • 15 new tests across 4 test files

Test plan

  • ./gradlew build passes (all 8 modules)
  • ./gradlew :adcp:test :adcp-server:test — all new and existing tests green
  • Budget/CPM constraint violation detection verified
  • Alternatives count validation (2-10 protocol max, seller ceiling)
  • ProposalSuccessor lineage + digest stamping verified

Closes adcontextprotocol/adcp#6556 (Java SDK track)

🤖 Generated with Claude Code

garvitkaushik-123 and others added 3 commits August 16, 2026 01:22
Introduces the `negotiation` package across adcp, adcp-server, and
adcp-testing modules for the refine_proposals tool surface (AdCP 3.2).

Client (adcp module):
- Sealed RefinementResult with four outcomes (revised/partial/finalized/unable)
  supporting exhaustive pattern matching
- Capability-aware RefineProposalsRequest builder enforcing batch size
  ceilings, unique proposal IDs, and finalize-only homogeneity
- Three typed constraints from the 3.2 delta: CpmConstraint,
  ImpressionsConstraint, FlightConstraint
- TermsDigest utility implementing RFC 8785 JCS canonicalization for
  SHA-256 digest computation and verification
- ResponseVerifier checking result ordering, lineage (parent_proposal_id),
  finalize atomicity, outcome structural constraints, partial invariant,
  unique alternatives, and digest integrity
- AdcpClient.refineProposals() convenience method
- UnsupportedRefinementDetails for typed UNSUPPORTED_FEATURE error recovery
- RefinementCapability with product_changes dimension key (post-rename)

Server (adcp-server module):
- ProposalHandler interface with capability declaration, batch preflight
  hook, and refine callback — commercial decisions stay in the application

Testing (adcp-testing module):
- NegotiationFixtures with factory methods for common scenarios: single
  revise, batch finalize, constraint objects, draft/committed proposals

Covers the unsatisfied_constraints-is-open-strings design, reason code
precedence (constraint_unsatisfiable > commercially_declined), lineage
verification, and the hold_unavailable/batch_aborted reason codes from
the post-red-team protocol delta.

Ref: adcontextprotocol#36
- TermsDigest: remove unused MAPPER field and three unused imports
  (JsonProcessingException, Iterator, Map)
- TermsDigest: add @nullable to verify() digest parameter — the method
  handles null but the @NullMarked package default says non-null
- TermsDigest: fix JCS exponent formatting — strip ".0" before 'e' so
  1.0E-7 becomes "1e-7" per ES2015/RFC 8785 (was producing "1.0e-7")
- TermsDigest: replace per-character OutputStreamWriter allocation in
  writeCanonicalString with direct String.valueOf(c).getBytes()
- RefineProposalsRequest: remove unused Collections import and dead
  supportedDimensions builder field (stored but never validated)
- AdcpClient: fix import ordering — negotiation imports grouped with
  other org.adcontextprotocol imports, not after slf4j
- Add serialization round-trip test for RefinementResult
- Add test coverage for JCS exponent edge cases
Add missing typed constraints, alternatives validation, and server-side
successor utilities to close the proposal negotiation gaps tracked in
adcontextprotocol/adcp#6556.

- TotalBudgetConstraint: budget bounds (min/max/currency) per schema
- RefinementConstraints: composite of all four constraint dimensions
- ProposalRefinement: add constraints, productChanges, alternatives
  fields + builder; rename instructions→ask to match wire schema;
  enforce alternatives.count 2-10 (protocol max)
- RefinementCapability: add maxAlternatives field
- RefineProposalsRequest.Builder: validate alternatives against seller
  ceiling
- ResponseVerifier: add verifyConstraintSatisfaction checking budget
  bounds and CPM ceiling on revised outcomes
- ProposalSuccessor (server): stamp immutable successors with lineage
  and recomputed terms_digest
- 15 new tests across constraints, alternatives, verification, and
  successor stamping

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@aao-ipr-bot

aao-ipr-bot Bot commented Aug 27, 2026

Copy link
Copy Markdown

⚠️ Argus review could not complete

The automated review encountered an issue (possibly reached max turns, timed out, or failed to post the final gh pr review). A human reviewer should take this PR.

View workflow run

This is an automated message from the Argus AI review workflow.

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.

epic: make proposal negotiation easy to implement, teach, and verify

1 participant