feat(negotiation): add first-class buyer and seller proposal APIs - #37
Open
garvitkaushik-123 wants to merge 2 commits into
Open
feat(negotiation): add first-class buyer and seller proposal APIs#37garvitkaushik-123 wants to merge 2 commits into
garvitkaushik-123 wants to merge 2 commits into
Conversation
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
garvitkaushik-123
requested review from
MichielDean and
bokelley
as code owners
August 15, 2026 19:53
|
The automated review encountered an issue (possibly reached max turns, timed out, or failed to post the final This is an automated message from the Argus AI review workflow. |
- 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
|
The automated review encountered an issue (possibly reached max turns, timed out, or failed to post the final This is an automated message from the Argus AI review workflow. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Implements the foundation for #36 — first-class proposal negotiation types for the
refine_proposalstool surface introduced in AdCP 3.2.This covers the three modules referenced in the issue's acceptance criteria:
Client (
adcpmodule)RefinementResultwith four outcome variants (Revised,Partial,Finalized,Unable) supporting Java 21 exhaustive pattern matching and Jackson polymorphic deserialization on theoutcomediscriminatorRefineProposalsRequestbuilder enforcing batch size ceilings, unique proposal IDs, finalize-only homogeneity, and idempotency key format — all validated before transportCpmConstraint(max CPM + currency),ImpressionsConstraint(minimum summed impressions),FlightConstraint(start/end bounds with the "asap never satisfies start" rule noted in the spec)TermsDigest— self-contained RFC 8785 JCS canonicalization + SHA-256 digest computation and verification. Recomputes and compares rather than trusting the string, per the 3.2 normative spec. Also providesareDistinct()for alternative distinctness checksResponseVerifierchecking result ordering against the request, lineage (parent_proposal_id==source_proposal_id), finalize atomicity, outcome-specific structural constraints (status/expires_at/reason/notes), partial invariant (unsatisfied_constraints must be present), unique proposal IDs, and digest integrityRefinementCapabilitywith the post-renameproduct_changesdimension keyUnsupportedRefinementDetailsfor typedUNSUPPORTED_FEATUREerror recoveryAdcpClient.refineProposals()convenience method delegating tocallNamedToolServer (
adcp-servermodule)ProposalHandlerinterface with capability declaration, optional preflight hook for cross-entry validation, andrefine()callback. Framework does batch validation; commercial decisions stay in the application callbackTesting (
adcp-testingmodule)NegotiationFixtureswith factory methods for single revise, batch finalize, draft/committed proposals, constraint objects, and JSON response fragments forrevisedandunableoutcomesDesign decisions
unsatisfied_constraintsisList<String>(open strings), not an enum — per the 3.2 delta commentorg.webpki.jcsfor the common case. The risky JCS number formatting follows ES2015 rulesProposalRefinementfactory methods cover the four common patterns (revise with instructions, revise with criteria, finalize, cancel)Not in this PR
adcp-testing)ProposalHandlerintoAdcpServerBuildertool registration (needs the codegen track to emit the input schema)Test plan
RefineProposalsRequestTest— builder validation: valid requests, null/short idempotency keys, empty refinements, mixed finalize/revise rejection, duplicate proposal IDs, batch size ceiling, immutable list, cancellation refinementsRefinementResultTest— sealed interface permits, Jackson round-trip for all four outcomes, pattern matching exhaustivenessTermsDigestTest— sha256 prefix, determinism, key-order independence, verify/tamper detection, null/wrong-prefix rejection, distinctness, JCS canonicalization of nested objects/strings/numbers/booleans/nullsResponseVerifierTest— valid response passes, count mismatch, ordering mismatch, mixed finalize, missing lineage, wrong proposal_status for finalized, async skip, digest mismatch detectionConstraintsTest— validation for all three constraint types, rejection of invalid inputs, Jackson round-trip serialization./gradlew buildpasses (all 55 tasks, all existing tests still green)Closes #36 (partial — see "Not in this PR" above; reactive/Kotlin surfaces and integration tests tracked separately)