Repository navigation
fix(reporting): read each package offering snapshot from get_media_buys - #1765
Conversation
Without a buy_offerings hook, the managed path treated an empty packages[].reporting_delivery_offering_ids snapshot as absent and reported the package by every registered offering. In 3.3.0-beta.3 a seller serving subscriptions includes the snapshot on every package, fixed at confirmation, and [] means no offering applies. The snapshot is now honoured as served, including [], and only a package served without one falls back to every registered offering, matching the TypeScript SDK. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Ladon verdict: Approve
Approve — clean, correct bug fix.
This PR fixes the managed seller path where package.get("reporting_delivery_offering_ids") or every collapsed a present-but-empty snapshot [] into "every registered offering." The new _package_offering_ids helper uses an isinstance(..., (list, tuple)) guard so an explicit [] is honored as "no offering" and only a missing snapshot falls back to every. This aligns managed.py with coverage.py's existing semantics and matches AdCP 3.3.0-beta.3 / the TS SDK.
Checked:
fix:prefix is correct — no public model-shape change, no semver signal issue.- Covered by a parametrized test over all three snapshot cases plus the missing-snapshot fallback.
- Docs updated consistently.
- No high-risk paths, no gated paths, no author team gate.
No blocking or medium findings. Falls through to row 9 → approve.
The producer row-upload test stamps its worker lease with the settling harness clock, fixed at 2026-11-01T02:10Z, while the row store checks the lease against the database's clock_timestamp. Once the wall clock passed that instant plus the lease, every run failed with STATE_UNAVAILABLE: no live worker lease covers this row upload, on next and on every pull request. The test now runs its turn at the wall clock, so the lease lies in the real future. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> (cherry picked from commit ae15bab)
There was a problem hiding this comment.
Ladon verdict: Approve
Approve — clean test-only fix, no blocking or medium findings.
This PR's delta is a 5-line, test-only change in tests/conformance/reporting/test_reporting_row_storage_object_pg.py: the object-staging test now stamps the injected clock at datetime.now(timezone.utc) before run_worker(), because the worker lease is validated against the database's clock_timestamp() and the harness's fixed instant could sit in the past. The reviewer confirms this is the correct fix, with a load-bearing explanatory comment and no downstream time-advancement logic depending on the fixed instant in this single-turn test.
Checks:
- No critical/high/medium findings (rows 1, 4, 5, 8 do not fire).
- gated_paths: false and review_decision: APPROVED (row 2 n/a).
- high_risk: false; no deleted/modified high-risk entries (rows 3, 5 n/a).
- No no-auto-approve team match (row 7 n/a).
- Prior decision was
approve, notescalate(row 6 n/a).
Falls through to row 9 → approve.
Loose end from the reporting-subscriptions DX plan.
Problem
On the managed seller path, without a
SubscriptionOptions.buy_offeringshook, each package's offering set came frompackages[].reporting_delivery_offering_ids or every. An empty snapshot ([]) was treated as absent, so the package was reported by every offering the service registered.In AdCP 3.3.0-beta.3,
get_media_buyscarries this snapshot on every package of a seller that servesmedia_buy.reporting_subscriptions. It is fixed when the package is confirmed, and[]means no offering applies.Fix
[].Array.isArray(snapshot) ? snapshot : every).SubscriptionOptionsdocstring and the two seller guides now describe the snapshot.Tests
tests/test_reporting_subscription_managed.py:22 passed. ruff and mypy are clean.
🤖 Generated with Claude Code