Conversation
There was a problem hiding this comment.
Ladon verdict: Approve
Approve — AdCP 3.2 proposal negotiation added as a transitional forward surface with correct minor changeset, official MCP client usage, and ~1,500 lines of tests covering retry-key reuse, CAS double-hold prevention, immutable snapshots, and reason-code precedence.
Medium findings (non-blocking):
- src/lib/utils/jcs.ts:141 — JCS canonicalize now throws on lone surrogates; shared by idempotency hashing and signing
- src/lib/negotiation/verification.ts:359 — Response verifier enforces closed key sets while types declare open [key: string]: unknown
Decision trace: No critical/high findings (row 1 n/a). gated_paths is false (row 2 n/a). high_risk false, no deletions (rows 3, 5 n/a). Both medium findings are category verification/hashing logic — not data-loss/schema/infra (row 4 n/a). No prior decision (row 6 n/a). No no-auto-approve team match (row 7 n/a). Only 2 medium findings, below the 3-medium threshold (row 8 n/a). Falls through to row 9 → approve.
Note: review_decision is REVIEW_REQUIRED, but since gated_paths is false, row 2 does not apply and standard GitHub branch protection (not Ladon) governs the required-reviewer gate. The two medium findings are worth a maintainer glance — the JCS surrogate change and the closed-key-set verifier both have blast radius beyond the proposal path — but neither is blocking.
Medium findings
- src/lib/utils/jcs.ts:141 — JCS canonicalize now throws on lone surrogates; shared by idempotency hashing and signing
- src/lib/negotiation/verification.ts:359 — Response verifier enforces closed key sets while types declare open [key: string]: unknown
There was a problem hiding this comment.
Ladon verdict: Approve
Approve — delta since prior approve is clean.
This subsequent review looks at the schemas-ensure / sync-schemas delta backing the AdCP 3.2 proposal-negotiation feature. The new hasProposalNegotiationCache guard mirrors the existing STABLE_3_0 pattern (early-exit conjunction + conditional sync push), and the final pointLatestAtCurrent restore keeps the latest symlink pinned to ADCP_VERSION. No new correctness, security, wire-shape, or changeset issues in the delta.
The two prior medium findings (jcs.ts:141 lone-surrogate throw; verification.ts:359 closed key-set enforcement) are outside this delta and were not re-surfaced; the changeset (.changeset/add-proposal-negotiation.md) is present for the src/lib/** changes.
No blocking findings, no medium findings in the current run. gated_paths false, high_risk false, no no-auto-approve team match. Falls through to row 9.
There was a problem hiding this comment.
Ladon verdict: Approve
Approve — clean diff, no blocking or medium findings.
This is a subsequent review after a prior approve. The only delta since the prior head is a single cosmetic change in scripts/schemas-ensure.ts: the six-operand if (currentV3Ok && stableV30Ok && ...) guard collapsed from six lines to one, with the same operands in the same order and no behavior change.
Checks confirmed:
- No critical/high/medium findings in this run.
- Changeset present (
.changeset/add-proposal-negotiation.md) covering thesrc/lib/**changes, so changeset-vs-wire-impact is satisfied. - No no-auto-approve team match;
gated_pathsis false;high_riskis false.
None of decision-table rows 1–8 fire, so the outcome falls through to row 9 (approve).
There was a problem hiding this comment.
Ladon verdict: Approve
Approve.
Checked the delta scoping of JCS strictness: the shared canonicalize in jcs.ts is restored to main's lone-surrogate-preserving behavior (net change vs main is comment-only), and strict I-JSON validation is correctly relocated to the proposal boundary via assertIJsonString/canonicalProposalTerms. verification.ts now canonicalizes commercial_terms once for both the digest comparison and the distinctness set, closing a real accessor-getter TOCTOU. types.ts index-signature removals are compile-time-only with no runtime/witness impact.
Gate checks: no no-auto-approve team match; gated_paths is false; high_risk is false. Changeset present (.changeset/add-proposal-negotiation.md) covering the src/lib/** changes. No witness-not-translator or transport-client concerns. Prior decision was also approve.
No critical, high, or medium findings. Falls through to row 9.
Summary
refine_proposalsbuyer APIs with capability-aware preflight and verified resultsget_productsrefinement and provide runnable buyer/seller examplesWhy
AdCP 3.2 moves structured proposal negotiation into
refine_proposals. The SDK needs a safe default path that preserves idempotency, tenant isolation, immutable proposal lineage, and all-or-nothing finalization for both buyer and seller agents.Closes #2542.
Validation
npm run typechecknpm run typecheck:examplesnpm run build:libnpm run test:protocolsnpm run test:node:fast(13,177 passing, 7 skipped)Review
Protocol, code-quality, security, and adopter-DX expert passes were run before publication. Their convergent findings drove the first-class server pipeline, authenticated scope, CAS finalization, complete runtime validation, successor identity, and Unicode digest hardening in this revision.