Skip to content

Rename DSP → BuyerDealFlow across code, tests, and docs#81

Merged
atc964 merged 7 commits intomainfrom
feature/buyer-deal-flow-rename
Apr 13, 2026
Merged

Rename DSP → BuyerDealFlow across code, tests, and docs#81
atc964 merged 7 commits intomainfrom
feature/buyer-deal-flow-rename

Conversation

@atc964
Copy link
Copy Markdown
Collaborator

@atc964 atc964 commented Apr 13, 2026

Summary

Renames all misnamed "DSP" references to "BuyerDealFlow" throughout the buyer agent. The buyer agent negotiates deals with sellers — it is not itself a DSP. This rename clarifies the codebase for anyone working with or integrating against the buyer agent.

What changed:

Code (6 files renamed, 22 files updated):

  • dsp_agent.py → buyer_deal_specialist_agent.py
  • dsp_deal_flow.py → buyer_deal_flow.py
  • tools/dsp/ → tools/buyer_deals/
  • DSPDealFlow → BuyerDealFlow, DSPFlowState → BuyerDealFlowState
  • create_dsp_agent() → create_buyer_deal_specialist_agent()
  • Agent role: "DSP Deal Discovery Specialist" → "Buyer Deal Specialist"

Tests (3 files renamed):

  • test_dsp_deal_flow.py → test_buyer_deal_flow.py
  • test_dsp_tools.py → test_buyer_deal_tools.py
  • test_dsp_discovery_pricing.py → test_buyer_deal_discovery_pricing.py

Docs (11 files updated, 1 renamed):

  • dsp-deal-flow.md → buyer-deal-flow.md
  • MkDocs nav updated
  • All architecture, guide, and API docs updated

PROGRESS.md generator:

  • Added prefix filter to prevent ar-/seller- beads from leaking into buyer PROGRESS.md

Not changed (legitimate DSP references preserved):

  • DSP platform names (The Trade Desk, DV360, Amazon DSP, Xandr)
  • DSP seat IDs, DSP activation, X-DSP-Seat-ID headers
  • Descriptions of pushing Deal IDs to real DSPs

Test Results

  • Full suite: 2672 passed, 41 skipped, 0 failed
  • MkDocs build: clean
  • Cross-repo smoke test: all scenarios pass (imports, live seller, old imports fail)

Beads

  • Epic: ar-ce2c81bd (Rename DSP → BuyerDealFlow)
  • ar-v6ah (code), ar-k8ho (tests), ar-j7on (docs), ar-yocw (smoke test), ar-sl73 (PROGRESS.md)

🤖 Generated with Claude Code

atc964 and others added 7 commits April 13, 2026 15:34
…beads

The generator had no prefix-based filtering, relying solely on the JSONL
file containing only buyer- beads. This adds an explicit BEAD_PREFIX = "buyer-"
guard in load_issues() so ar- or seller- beads are rejected even if they
appear in the JSONL. Also regenerates PROGRESS.md and fixes stale Phase 4
assertions in end-to-end tests.

bead: ar-sl73

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
File renames:
- dsp_agent.py -> buyer_deal_specialist_agent.py
- dsp_deal_flow.py -> buyer_deal_flow.py
- tools/dsp/ -> tools/buyer_deals/

Class/function renames:
- DSPDealFlow -> BuyerDealFlow
- DSPFlowState -> BuyerDealFlowState
- DSPFlowStatus -> BuyerDealFlowStatus
- create_dsp_agent() -> create_buyer_deal_specialist_agent()
- run_dsp_deal_flow() -> run_buyer_deal_flow()

Agent role updated from "DSP Deal Discovery Specialist" to
"Buyer Deal Specialist". Backstory updated to remove "DSP specialist"
language. All imports, __init__.py exports, docstrings, test assertions,
and @patch targets updated across 22 files. Legitimate DSP references
(platform names, seat IDs, activation instructions) preserved.

All 2672 tests pass.

bead: ar-v6ah

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- test_dsp_deal_flow.py -> test_buyer_deal_flow.py
- test_dsp_tools.py -> test_buyer_deal_tools.py
- test_dsp_discovery_pricing.py -> test_buyer_deal_discovery_pricing.py
- Updated internal fixture names (dsp_flow -> buyer_flow)
- Updated docstrings and class names referencing DSP

bead: ar-k8ho

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Renames documentation references from DSP-centric naming to
buyer-centric naming to better reflect the agent's role:
- DSP Deal Flow -> Buyer Deal Flow
- DSPDealFlow -> BuyerDealFlow
- DSP Specialist -> Buyer Deal Specialist
- DSP Tools -> Buyer Deal Tools
- tools/dsp/ -> tools/buyer_deals/
- dsp_deal_flow -> buyer_deal_flow
- dsp_agent -> buyer_deal_specialist_agent

Legitimate DSP platform references (DSP activation, DSP seat IDs,
DSP platforms like TTD/DV360/Amazon DSP) are preserved.

bead: ar-j7on

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@atc964 atc964 merged commit cc9c4d7 into main Apr 13, 2026
0 of 3 checks passed
atc964 added a commit that referenced this pull request Apr 26, 2026
* Vendor IAB taxonomies into buyer data/

bead: ar-8doh

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* Fix §1: reproducible agentic composite hash + helper script

Aligns buyer-side agentic spec hashing with the seller-side
approach so cross-repo drift detection works consistently.
Per Quinn ar-8doh review.

bead: ar-8doh

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* Add AudienceRef + AudiencePlan models + taxonomy loader + TaxonomyLookupTool

Per proposal §5.2 (data model) and §5.5 (tools).

bead: ar-50cm

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* Migrate CampaignBrief.target_audience + CampaignPlan to AudiencePlan

Adds compat shim for legacy list[str] rows (first -> primary,
rest -> extensions, source=inferred). Adds audience_strictness
policy. Adds Content Taxonomy 2.x->3.x deletion validation at
brief ingestion. Per proposal §6 row 4.

bead: ar-fe0h

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* Add audience_plan to InventoryRequirements/DealParams/QuoteRequest/DealBookingRequest

Threads the audience surface through the orchestrator data classes
with backward-compatible None default. Per proposal §5.2 + §6 row 5.

bead: ar-9nwu

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* Wire Audience Planner into CampaignPipeline + relocate UCP tools

- Audience Planner agent now instantiated between brief ingest
  and orchestrator handoff; produces stub AudiencePlan (full
  reasoning loop is bead §7).
- Three UCP audience tools moved from Research Agent to Audience
  Planner where they belong.
- Mock EmbeddingMintTool added (delegates to existing UCPClient
  mock embedding generator).
- UCP modules carry "Agentic Audiences (UCP)" rename header
  comments per §5.6 locked decision.

bead: ar-fgyq

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* Implement Audience Planner reasoning loop

Per proposal §5.5: classify → pick primary → add constraints/
extensions → validate → emit plan + rationale. Pure-Python core
with CrewAI shell for rationale. Graceful degradation when
discovery unavailable.

bead: ar-9u25

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* Wire typed AudiencePlan through channel-crew invocation path (Path B)

Channel-crew factories now accept typed AudiencePlan; the audience-
context formatter renders all 4 roles + rationale. Backward compat
for legacy dict input preserved. Per proposal §5.3 + §6 row 19.

bead: ar-5y8v

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* Wire audience_plan into BuyerDealFlow (Path B)

BuyerDealFlow now invokes the audience planner step alongside
CampaignPipeline; AudiencePlan threads through any seller-bound
data classes / HTTP calls. Per proposal §5.3 + §6 row 18.

bead: ar-ts30

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* Add E2E integration test for Path B (BuyerDealFlow + channel-crew)

Covers happy-path with all 3 audience types, legacy migration,
serialization parity at flow→seller boundary, mocked capability-
degradation scenario, and pre-set state.audience_plan precedence.
Per proposal §6 row 20.

bead: ar-6ipo

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* docs: rewrite Audience Planner section for 3-type extension (§8/§5.6)

Replaces the dead-code "Audience Planner (UCP)" section in
docs/architecture/agent-hierarchy.md with the §8 drop-in MkDocs block
from the audience-extension proposal:

- Renames the agent to "Audience Planner (Agentic Audiences / UCP)"
  per §5.6 dual-naming policy
- Adds the three-audience-types table (Standard / Contextual / Agentic)
- Documents the composable overlay model (primary + constraints +
  extensions + exclusions) with set semantics
- Documents the reasoning loop, configuration, and tools
- Cross-references the parent-repo capability-negotiation guide,
  naming explainer, and wire-format spec
- Updates the mermaid diagram label and the channel-crew "Audience
  context" callout to use the dual name

bead: ar-nd3i

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* Add buyer-side degrade_plan_for_seller + retry-on-audience_plan_unsupported

Per proposal §5.7 layer 2 + §6 row 12. Composable with bead §13's
pre-flight integration (the two together implement full capability
negotiation per §5.7).

bead: ar-0w48

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* Add audience_audit_log SQLite table + emitter for degradation events

Per proposal §5.7 + §6 row 13a. Append-only audit trail keyed by
audience_plan_id; emits degradation, capability_rejection,
snapshot_honor events.

bead: ar-q2uh

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* Buyer: emit dual content-type on deal booking + log plan_id hash

Per proposal §5.6 + §6 row 14b. Buyer now emits both
application/vnd.ucp.embedding+json; v=1 and the new
application/vnd.iab.agentic-audiences+json; v=1; logs
audience_plan_id at INFO for audit-trail correlation.

bead: ar-y6ki

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* Add buyer pre-flight capability discovery + audience_strictness gating

Per proposal §5.7 layers 1+2 + §6 row 13. Orchestrator now calls
/.well-known/agent.json before booking (TTL <=1h cache, honors
Cache-Control), applies degrade_plan_for_seller per audience_strictness,
composes with §12's retry path for stale-cache cases.

bead: ar-gkbr

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* Buyer: OpenRTB carrier mapping for audience_plan

Per proposal §5.1 Step 4 + §6 row 15. Builder maps Standard→
user.data[].segment[].id, Contextual→site.cat/cattax=7, Agentic
→user.ext.iab_agentic_audiences.refs[] (feature-flagged).

bead: ar-8vzg

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* Add E2E Path A integration test scaffolding + happy path

Per proposal §6 row 16 (part 1 of 2). Scenarios 2-4 follow.

bead: ar-lk23

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* Add E2E Path A scenarios 2-4: degradation + hard-reject + JSON round-trip

Part 2 of 2 for §16. Adds capability degradation (mocked legacy
seller), hard-reject on zero standard overlap, and cross-repo
AudiencePlan JSON round-trip schema-drift backstop.

bead: ar-lk23

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* Implement real embedding model (E2-2) with hybrid strategy

Per E2-1's locked decision (docs/decisions/EMBEDDING_STRATEGY_2026-04-25.md).
EMBEDDING_MODE switch in UCPClient (mock|local|advertiser|hybrid);
sentence-transformers/all-MiniLM-L6-v2 for local; advertiser-supplied
vectors accepted verbatim; mock fallback for CI. Adds embedding_provenance
to ComplianceContext per E2-7 Gap 6.

- Settings: new embedding_mode field (default hybrid; override via
  EMBEDDING_MODE env var)
- UCPClient: new create_query_embedding_with_provenance() returns
  QueryEmbeddingResult(embedding, provenance, dimension); existing
  create_query_embedding() preserved as backward-compat wrapper
- Lazy local model load with graceful fallback if sentence-transformers
  not installed
- Out-of-range advertiser vectors (dim < 256 or > 1024) rejected with
  warning; falls back to local/mock per mode
- Adds 10 unit tests covering all 4 modes + provenance + backward compat

bead: ar-0abx

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* Update UI/log labels for real embedding model (E2-5)

Per E2-2's hybrid strategy. EmbeddingMintTool now reads
settings.embedding_mode and renders a per-mode descriptive string
(MOCK/LOCAL/ADVERTISER-SUPPLIED/HYBRID). EMBEDDING_MODE_LABEL_MOCK
preserved as a static constant for backward compat with existing
imports. _format_ref pulls the dynamic label so audit-trail entries
record the actual provenance per booking.

bead: ar-c2vp

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* Update audience-planner MkDocs page for real embedding model (E2-9)

Per E2-2 + E2-1. Replaces "256-1024 dim, cosine similarity" generic
language with the locked hybrid strategy:
sentence-transformers/all-MiniLM-L6-v2 local + advertiser-supplied +
mock CI fallback. Adds Embedding Provenance subsection cross-linking
the strategy decision and the E2-7 consent review.

bead: ar-espk

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* Add embedding evaluation harness (E2-3)

New `ad_buyer.eval` package with `evaluate_embedding_modes()` function
that runs a fixed corpus of audience briefs through each EMBEDDING_MODE
and reports per-mode metrics (determinism, dimension, distinctiveness,
provenance). Used by §17 release-gate audits and informs E2-4 threshold
recalibration.

Cosine-distance distinctiveness over pairwise fixture comparisons
surfaces the difference between mock SHA256 and real sentence-transformers
embeddings on semantically related-but-distinct briefs.

bead: ar-f2y2

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* Per-mode similarity thresholds (E2-4)

Per E2-3's eval harness — mock SHA256 vectors saturate quickly so the
"strong" threshold has to be tighter (≥0.85) to avoid false matches.
Real sentence-transformers vectors live in a smoother semantic space
and tolerate the original 0.70 strong threshold. Advertiser and hybrid
modes follow the local convention.

UCPClient.validate_audience_with_seller now reads thresholds from
_similarity_thresholds_for_mode() (which honors settings.embedding_mode).
MkDocs configuration table updated.

Re-derive via ad_buyer.eval.evaluate_embedding_modes() when the model swaps.

bead: ar-318x

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* Buyer-side schema-drift assertion against canonical snapshot (E2-10)

bead: ar-tuac

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* Add E2E test on real-model path (E2-8)

Exercises EMBEDDING_MODE=local + hybrid through the buyer's UCPClient,
asserting: local model produces 384-dim or falls back gracefully (no
crash), per-mode threshold tightening per E2-4, dynamic label per E2-5,
eval harness reports real provenance per E2-3, embedding_provenance
field on ComplianceContext per E2-7 Gap 6, full AudiencePlan round-trip
through JSON.

bead: ar-zyqd

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* Fix timezone-naive flake in test_deal_uses_default_flight_dates (ar-szs0)

Production code uses datetime.now(timezone.utc); test was comparing
datetime.now() (local) which fails after local-time midnight passes
UTC midnight. Match production by using UTC in the test.

bead: ar-szs0

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* Parametrize seller-src path in test_path_a_audience_e2e (ar-840n)

Per Quinn's note during ar-lk23 review. The cross-repo round-trip test
hard-coded `.worktrees/audience-extension/src`; now derives the path
from the buyer worktree name (so any worktree name works) with an
AD_SELLER_SRC_PATH env-var override and a graceful fallback to the
seller repo's main src/ when no companion worktree exists.

bead: ar-840n

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* Add reject_global_agentic brief-ingestion validator (ar-ei0s)

Per consent surface review (E2-7) Gap 5 + proposal §7. Single
ComplianceContext can't honestly express per-region consent for global
agentic campaigns. Until per-jurisdiction fan-out lands as a follow-up
to E2-2, brief ingestion rejects agentic refs declared with
jurisdiction='GLOBAL'. Standard / Contextual GLOBAL refs are allowed
(they don't carry per-region consent semantics).

New validate_no_global_agentic() validator + GlobalAgenticUnsupported
exception. Wired into CampaignBrief's model_validator alongside the
existing Content Taxonomy 2.x→3.x check.

bead: ar-ei0s

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* Replace deprecated datetime.utcnow() across buyer codebase (ar-4e9b)

Per Quinn's flag during ar-ts30 verification. Adds a small `time_utils.utc_now()`
helper that returns naive UTC datetime (matching the prior datetime.utcnow()
semantic) without the Python 3.12+ deprecation warning. Updates 23 call
sites across 8 files: events/models, flows/dsp_deal_flow,
interfaces/api/main, models/{flow_state,state_machine,ucp},
negotiation/{models,strategy}.

Tightens the obsolete §22-in-label assertion in test_audience_planner_wiring
that E2-5 superseded with the dynamic per-mode label.

bead: ar-4e9b

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* Fix mkdocs --strict broken anchors + cross-page links (ar-w9xv)

Per Quinn's flag during UAT 2026-04-25 (mkdocs build --strict aborts).

Anchor fixes (deployment-ops-guide.md): replace '&' in 4 H2 headings
with 'and' so the auto-generated slugs match the TOC link targets
(`#environment-variables-and-configuration` etc.). The default
slugifier dropped '&' producing inconsistent dash counts.

Cross-page link fixes: 8 missing-target links in event-bus/overview.md,
state-machines/order-lifecycle.md, and architecture/mcp-server.md
referenced docs/pages that were never written (`deal-store.md`,
`state-machine.md`, `booking-flow.md`, `event-bus.md`,
`ai-assistant/overview.md`). Replaced with plain-text source-file
references so mkdocs --strict passes without losing the information.

Also fixed the embedding-strategy link I introduced in E2-9 (cross-mkdocs
relative path was wrong-depth; now described in plain text).

bead: ar-w9xv

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* Complete dsp_deal_flow file/class rename to BuyerDealFlow (ar-62g7)

Per Quinn's flag during ar-ts30 verification. PR #81 was advertised as
"DSP → BuyerDealFlow rename" but missed the file `flows/dsp_deal_flow.py`,
class `DSPDealFlow`, state model `DSPFlowState`, and status enum
`DSPFlowStatus`. This commit completes that rename:

- File: src/ad_buyer/flows/dsp_deal_flow.py → buyer_deal_flow.py
- Class: DSPDealFlow → BuyerDealFlow
- State: DSPFlowState → BuyerDealFlowState
- Status enum: DSPFlowStatus → BuyerDealFlowStatus
- Updated all 89 reference sites across 9 files (src/ + tests/)
- Updated import paths and __init__ exports

Out of scope: `agents/level2/dsp_agent.py` and `tools/dsp/` directory
(separate followups; bead description scoped to flow + state).

Full buyer suite 3013/3013 passing post-rename.

bead: ar-62g7

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* Robust _tool_to_natural_language mapping (ar-yt4)

Replace string-comparison if/elif chain with a registry dict keyed by
Tool class. Unknown tools fall back to .description / .name rather
than producing empty strings. Each registered audience/dsp/research
tool tested for a non-empty mapping or fallback.

bead: ar-yt4

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* Fix Settings instantiated at module import time (ar-le3)

Replace the eager module-top `settings = Settings()` with a lazy
`get_settings()` cached factory + `_LazySettings` proxy alias for
existing import sites. Tests that need to override env vars now see
the override on first attribute access rather than fighting the
import-time instantiation.

bead: ar-le3

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* Regression test for tool _run/_arun return type hints (ar-gsd)

Audit found all 44 existing methods already have return annotations
(22 sync + 22 async). This parametrized regression test walks
ad_buyer.tools.* for BaseTool subclasses and asserts every _run/_arun
declares a return type — locks in the property going forward.

bead: ar-gsd

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* DRY channel crew factory functions (ar-w5g)

Extracted the 4 nearly-identical create_*_crew bodies into a single
_build_channel_crew helper parameterized by frozen _ChannelCrewSpec
dataclasses. Public signatures preserved; existing callers
(CampaignPipeline, BuyerDealFlow, channel-crew tests) unaffected.

Per-channel variation (manager-agent factory, research/recommendation
task descriptions, expected_output strings) lives in 4 spec instances.
Task descriptions now use .format() with named keys for clarity.

Line count: 636 → 563 (~12% reduction). All 44 channel-crew tests
still green; full buyer suite 3076/3077 (1 unrelated flake = ar-0isf).

bead: ar-w5g

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* Add tests/README.md for buyer agent test suite (ar-7p3)

Documents the unit/integration/smoke tier layout, run commands,
conventions (PYTHONPATH, worktree venv, AD_SELLER_SRC_PATH, ANTHROPIC_API_KEY,
EMBEDDING_MODE), the regression-guard tests that lock in invariants,
known flakes, and an audience-extension-tests-by-epic index.

bead: ar-7p3

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* Add headless/JSON mode to buyer demo script (ar-jzek)

`python -m ad_buyer.demo.campaign_demo --headless` drives all 6 stages
(submit-brief → approve-plan → approve-booking → approve-creative →
activate → report) via Flask test client without binding a port. Emits
one JSON object per stage to stdout (default) or `--summary` for a short
human-readable line per stage.

Stage sequence proven against the actual sample-brief #0; exits non-zero
on any stage failure or invalid --sample-index. Useful for CI smoke,
demo canaries, and one-shot validation without a browser.

4 new tests cover summary mode, JSON mode, default-is-JSON, and invalid
sample-index → non-zero exit.

bead: ar-jzek

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* Fix stale ad_buyer.tools.dsp imports after PR #81 rename

Origin's PR #81 renamed src/ad_buyer/tools/dsp/ → src/ad_buyer/tools/buyer_deals/.
Two test files added locally on the pre-rename base still imported from the
old path; the merge picked up the rename via git's rename detection but the
hard-coded `from ad_buyer.tools.dsp.request_deal import ...` lines did not
update. Point them at `tools.buyer_deals.request_deal` to match the renamed
module.

bead: ar-z40x

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* Fix order-dependent flake in test_lookup_per_mode (ar-0isf)

The test imported `settings` at module level and then used
`patch.object(settings, "embedding_mode", mode)`. That pattern is fine in
isolation, but `tests/unit/test_settings_lazy_init.py` deletes
`ad_buyer.config.settings` from `sys.modules` and reimports it to verify
lazy construction. After that reload, the module's `settings` symbol is a
new `_LazySettings` proxy backed by a fresh `lru_cache`, while the
threshold test's captured `settings` symbol still points at the old
proxy backed by the old cache. `_similarity_thresholds_for_mode` does
`from ..config.settings import settings` at call time, so it reads the
new proxy — meaning our patch wrote to the wrong cached `Settings` and
the threshold lookup returned the default ("hybrid") instead of the
patched mode.

Fix: resolve `settings` dynamically each iteration via
`sys.modules["ad_buyer.config.settings"].settings`, and add an explicit
side-effect import of the settings module so the entry exists in
`sys.modules` even when the threshold test runs in isolation. Production
code is unchanged.

bead: ar-0isf

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* Fix stale audience-extension worktree path in cross-repo test (ar-e2rj)

The cross-repo AudiencePlan JSON round-trip test resolved the seller
src path via parents[2] from the test file, which assumed the file
lived inside `ad_buyer_system/.worktrees/<name>/...`. When the test
ran from the canonical buyer repo path (no worktree), the math
walked too high, producing nonexistent sibling paths and a
ModuleNotFoundError on `ad_seller`.

Replace the parent-index math with explicit ancestry search for
`ad_buyer_system`, then look for a matching seller worktree only
when the test itself is running inside a buyer worktree, falling
back to `ad_seller_system/src` otherwise. Honors the existing
`AD_SELLER_SRC_PATH` override.

bead: ar-e2rj

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* Fix CrewAI 1.10.1 read-only flow.state in buyer DealBookingFlow (ar-x34o)

Mirrors seller-side fix 5df5c38. CrewAI 1.10.1 made Flow.state read-only;
buyer POST /bookings and CLI were assigning to flow.state and crashing with:
  ValueError: property 'state' of 'DealBookingFlow' object has no setter

Both call sites fixed:
- src/ad_buyer/interfaces/api/main.py:549 — POST /bookings background task
- src/ad_buyer/interfaces/cli/main.py:103 — CLI booking command

Fix: DealBookingFlow.__init__ now accepts **state_kwargs forwarded to
Flow.__init__(**state_kwargs). Call sites pass campaign_brief= at construction
instead of assigning flow.state = BookingState(...) post-construction.

Regression tests added in TestCrewAI110FlowStateRegression:
- construction with no state (defaults)
- construction with campaign_brief kwargs
- state setter raises AttributeError/ValueError guard

Also updated test_get_booking_status_after_creation to accept
"awaiting_approval" as a valid terminal status now that the flow runs.

bead: ar-x34o

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* Document canonical buyer MCP URL path /mcp/sse/sse (ar-yptd)

Starlette sub-app routing causes \`/mcp/sse\` to 307→404; the working
URL for AI clients (Claude Desktop, ChatGPT, Cursor, Windsurf) is
\`/mcp/sse/sse\`. Update all setup guides, config examples, and the
architecture reference to use the canonical path.

Files updated:
- docs/claude-desktop-setup.md: remote URL, local config, troubleshooting heading
- docs/multi-client-setup.md: all ChatGPT, Codex, Cursor, Windsurf config examples
- docs/architecture/mcp-server.md: canonical URL note, Mermaid diagram label
- docs/ai-assistant/developer-setup.md: hand-off URL and verify curl command
- docs/guides/deployment-ops-guide.md: MCP endpoint box, claude_desktop_config example, Python client snippet

bead: ar-yptd

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
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