Skip to content

Commit e396ef5

Browse files
authored
Merge pull request #63 from IABTechLab/fix/progress-md-dealjockey-phases
Update PROGRESS.md generator for DealJockey phases
2 parents 5cc0320 + 91e4f83 commit e396ef5

25 files changed

Lines changed: 9838 additions & 64 deletions

.beads/PROGRESS.md

Lines changed: 79 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
# Buyer Agent V2 — Progress
22

3-
**34 open** | **0 in progress** | **10 closed** | **20 blocked** | 44 total
3+
**58 open** | **2 in progress** | **27 closed** | **42 blocked** | 87 total
44

5-
`[█████░░░░░░░░░░░░░░░] 23% (10/44)`
5+
`[█████░░░░░░░░░░░░░░] 31% (27/87)`
66

77
## Phase 1 — Seller Interoperability
88

@@ -43,35 +43,92 @@
4343
| \[!] | buyer-1o3 | 3F: Deployment & Operations Guide | P3 | buyer-j95 | |
4444
| \[ ] | buyer-j95 | 3G: Infrastructure-as-Code Deployment (CloudFormation/Terraform) | P3 || |
4545

46-
## Phase 5Deal Jockey
46+
## DealJockey Phase 1Foundation
4747

4848
| | ID | Task | Priority | Blockers | Done |
4949
|---|---|---|---|---|---|
50-
| \[ ] | buyer-e6a | 5A: Rename DSP Specialist to Deal Jockey Agent | P2 || |
51-
| \[ ] | buyer-1q3 | 5B: Rename DSPDealFlow to DealJockeyFlow | P2 || |
52-
| \[ ] | buyer-rsf | 5C: DealStore Schema v2 Migration | P2 || |
53-
| \[!] | buyer-1kn | 5D: DealStore Methods for New Tables | P2 | buyer-rsf | |
54-
| \[!] | buyer-aw4 | 5E: Deal Template and Supply Path Template Tools | P2 | buyer-1kn | |
55-
| \[!] | buyer-hik | 5F: Analyze Supply Path Tool | P2 | buyer-1kn | |
56-
| \[!] | buyer-4mt | 5G: Instantiate Deal From Template Tool | P2 | buyer-aw4 | |
57-
| \[!] | buyer-h3r | 5H: Bulk Deal Operation Tool | P2 | buyer-1kn | |
58-
| \[!] | buyer-shp | 5I: Get Deal Performance Tool | P2 | buyer-1kn | |
59-
| \[!] | buyer-5b7 | 5J: Wire Deal Jockey Tools into Agent | P2 | buyer-4mt, buyer-h3r, buyer-shp, buyer-e6a, buyer-hik | |
60-
| \[!] | buyer-8o3 | 5K: Track Cross-Platform Deal Tool | P2 | buyer-1kn | |
61-
| \[!] | buyer-c68 | 5L: Migrate Deals Tool | P2 | buyer-4mt | |
62-
| \[!] | buyer-omm | 5M: Expand DealJockeyFlow with Optimization Plugin Interface | P1 | buyer-5b7, buyer-1q3 | |
63-
| \[ ] | buyer-91l | 5N: Deal Jockey Event Types | P2 || |
64-
| \[!] | buyer-xgc | 5O: External Optimization Provider Registration | P2 | buyer-omm | |
65-
| \[ ] | buyer-ez3 | 5P: IAB Deals API v1.0 Push Receiver | P2 || |
66-
| \[!] | buyer-681 | 5Q: Curator Awareness in SPO | P2 | buyer-hik | |
67-
| \[!] | buyer-5gp | 5R: Deal Jockey Example and Documentation | P3 | buyer-omm | |
50+
| \[x] | buyer-te6b.1 | DealJockey Phase 1: Foundation | P1 | buyer-te6b | 2026-03-18 |
51+
| \[~] | buyer-087 | DealJockey Phase 1 demo dashboard | P1 || |
52+
| \[x] | buyer-5tg | Deal library schema v2 (hybrid approach per D-4) | P1 || 2026-03-18 |
53+
| \[x] | buyer-8ap | Portfolio inspection tools | P1 || 2026-03-18 |
54+
| \[ ] | buyer-jpd | DealJockey Phase 1: Foundation | P1 || |
55+
| \[x] | buyer-muf | Create DealJockey L2 agent in buyer hierarchy | P1 || 2026-03-18 |
56+
| \[x] | buyer-rna | Define DealJockey event types (Phase 1) | P1 || 2026-03-18 |
57+
| \[ ] | buyer-te6b.1.1 | Write DealJockey seller API contract (supply-chain, from-template, bulk, performance) | P1 || |
58+
| \[!] | buyer-te6b.1.10 | [seller-dj4] Add GET /api/v1/deals/{id}/performance endpoint | P1 | buyer-te6b.1.1 | |
59+
| \[x] | buyer-te6b.1.11 | [buyer-dj3] Deal library schema v2 (expanded per Section 6) | P1 || 2026-03-18 |
60+
| \[x] | buyer-te6b.1.12 | [buyer-dj4] Deal library CRUD operations | P1 || 2026-03-18 |
61+
| \[ ] | buyer-te6b.1.13 | [buyer-dj5] Deal template and supply path template CRUD | P1 || |
62+
| \[x] | buyer-te6b.1.2 | Create DealJockey L2 agent in buyer hierarchy | P1 || 2026-03-18 |
63+
| \[x] | buyer-te6b.1.3 | Implement CSV deal import parser | P1 || 2026-03-18 |
64+
| \[x] | buyer-te6b.1.4 | Add manual deal entry to DealJockey | P1 || 2026-03-18 |
65+
| \[x] | buyer-te6b.1.5 | Build portfolio inspection tools | P1 || 2026-03-18 |
66+
| \[ ] | buyer-te6b.1.6 | Organize internal deal-booking modules (consolidate per ar-fad) | P1 || |
67+
| \[x] | buyer-te6b.1.7 | Define DealJockey event types (Phase 1) | P1 || 2026-03-18 |
68+
| \[!] | buyer-te6b.1.8 | [seller-dj2] Add GET /api/v1/supply-chain endpoint | P1 | buyer-te6b.1.1 | |
69+
| \[!] | buyer-te6b.1.9 | [seller-dj3] Add POST /api/v1/deals/from-template endpoint | P1 | buyer-te6b.1.1 | |
70+
| \[x] | buyer-vbh | Manual deal entry | P1 || 2026-03-18 |
71+
| \[x] | buyer-vjc | Deal library CRUD operations | P1 || 2026-03-18 |
72+
| \[x] | buyer-ymj | CSV deal import parser | P1 || 2026-03-18 |
73+
74+
## DealJockey Phase 2 — Intelligence
75+
76+
| | ID | Task | Priority | Blockers | Done |
77+
|---|---|---|---|---|---|
78+
| \[!] | buyer-te6b.2 | DealJockey Phase 2: Intelligence | P2 | buyer-te6b | |
79+
| \[!] | buyer-te6b.2.1 | Implement deal portfolio gap analysis | P2 | buyer-te6b.2 | |
80+
| \[!] | buyer-te6b.2.10 | [buyer-dj9] GetDealPerformanceTool | P2 | buyer-te6b.2, buyer-te6b.1.10 | |
81+
| \[!] | buyer-te6b.2.11 | [buyer-dj12] Deal migration tool (MigrateDealsTool) | P2 | buyer-te6b.2, buyer-te6b.1.6, buyer-te6b.1.8 | |
82+
| \[!] | buyer-te6b.2.12 | Define DealJockey event types (Phase 2) | P2 | buyer-te6b.2 | |
83+
| \[!] | buyer-te6b.2.13 | [seller-dj5] Enhanced supply-chain with sellers.json and schain | P2 | buyer-te6b.2, buyer-te6b.1.8 | |
84+
| \[!] | buyer-te6b.2.14 | [seller-dj6] Add POST /api/v1/deals/bulk endpoint | P2 | buyer-te6b.2, buyer-te6b.1.1 | |
85+
| \[!] | buyer-te6b.2.2 | Build cross-path price comparison tool | P2 | buyer-te6b.2, buyer-te6b.1.8 | |
86+
| \[!] | buyer-te6b.2.3 | Implement deal duplication for new advertisers | P2 | buyer-te6b.2, buyer-te6b.1.13, buyer-te6b.1.6 | |
87+
| \[!] | buyer-te6b.2.4 | Build deal deprecation analysis and execution | P2 | buyer-te6b.2, buyer-te6b.1.10 | |
88+
| \[!] | buyer-te6b.2.5 | Implement portfolio health reporting | P2 | buyer-te6b.2, buyer-te6b.1.10 | |
89+
| \[!] | buyer-te6b.2.6 | Build human instructions adapter for manual deal migration | P2 | buyer-te6b.2 | |
90+
| \[!] | buyer-te6b.2.7 | [buyer-dj6] AnalyzeSupplyPathTool | P2 | buyer-te6b.2, buyer-te6b.1.13 | |
91+
| \[!] | buyer-te6b.2.8 | [buyer-dj7] InstantiateDealFromTemplateTool | P2 | buyer-te6b.2, buyer-te6b.1.13, buyer-te6b.1.6 | |
92+
| \[!] | buyer-te6b.2.9 | [buyer-dj8] BulkDealOperationTool | P2 | buyer-te6b.2, buyer-te6b.2.14 | |
93+
94+
## DealJockey Phase 3 — Platform Integrations
95+
96+
| | ID | Task | Priority | Blockers | Done |
97+
|---|---|---|---|---|---|
98+
| \[!] | buyer-te6b.3 | DealJockey Phase 3: Platform Integrations | P3 | buyer-te6b | |
99+
| \[!] | buyer-te6b.3.1 | TTD API connector for deal import | P3 | buyer-te6b.3 | |
100+
| \[!] | buyer-te6b.3.2 | DV360 API connector for deal import | P3 | buyer-te6b.3 | |
101+
| \[!] | buyer-te6b.3.3 | Xandr API connector for deal import | P3 | buyer-te6b.3 | |
102+
| \[!] | buyer-te6b.3.4 | Amazon DSP API connector for deal import | P3 | buyer-te6b.3 | |
103+
| \[!] | buyer-te6b.3.5 | Mediaocean Prisma export parser | P3 | buyer-te6b.3 | |
104+
| \[!] | buyer-te6b.3.6 | Mediaocean Lumina export parser | P3 | buyer-te6b.3 | |
105+
| \[!] | buyer-te6b.3.7 | [buyer-dj11] Cross-platform deal activation tracker | P3 | buyer-te6b.3 | |
106+
| \[!] | buyer-te6b.3.8 | Cross-platform deal deduplication | P3 | buyer-te6b.3, buyer-te6b.2.2 | |
107+
108+
## DealJockey Phase 4 — External Model Integration
109+
110+
| | ID | Task | Priority | Blockers | Done |
111+
|---|---|---|---|---|---|
112+
| \[!] | buyer-te6b.4 | DealJockey Phase 4: Agent Range Integration | P3 | buyer-te6b, buyer-te6b.2 | |
113+
| \[!] | buyer-te6b.4.1 | [buyer-dj14] Event system (Phase 4: optimization events) | P3 | buyer-te6b.4 | |
114+
| \[!] | buyer-te6b.4.2 | [buyer-dj15] Receive IAB Deals API v1.0 push updates | P3 | buyer-te6b.4 | |
115+
| \[!] | buyer-te6b.4.3 | [buyer-dj16] Curator awareness in SPO | P3 | buyer-te6b.4 | |
116+
| \[!] | buyer-te6b.4.4 | Add Agent Range optimization hooks to DealJockey | P3 | buyer-te6b.4, buyer-te6b.2.5, buyer-te6b.2.11 | |
117+
| \[!] | buyer-te6b.4.5 | ML-tuned supply path scoring | P3 | buyer-te6b.4, buyer-te6b.2.7 | |
118+
| \[!] | buyer-te6b.4.6 | [seller-dj7] Curator support (OpenDirect 3.0) | P3 | buyer-te6b.4, buyer-te6b.1.8 | |
68119

69120
## Other
70121

71122
| | ID | Task | Priority | Blockers | Done |
72123
|---|---|---|---|---|---|
124+
| \[x] | buyer-9js | Architecture review: reconcile Phase 2 buyer plan with DealJockey strategic plan | P1 || 2026-03-18 |
125+
| \[ ] | buyer-fcq | Coordinate schema migration versioning across DealJockey and Phase 2 | P1 || |
126+
| \[!] | buyer-e6f | DealJockey Epic | P1 | buyer-jpd | |
73127
| \[ ] | buyer-brn | Epic: Buyer reporting agent | P3 || |
128+
| \[~] | buyer-nm8 | Migrate ar-te6b DealJockey beads from parent repo to buyer repo | P0 || |
74129
| \[ ] | buyer-nz9 | Order Status & Audit API Integration | P2 || |
130+
| \[ ] | buyer-0no | Schedule ar-te6b.1.6 (deal-booking modules consolidation) before buyer-8ih | P1 || |
131+
| \[x] | buyer-e3f | Session pickup - 2026-03-17: Docs revamp needs tab fix, Deal Jockey design in progress | P1 || 2026-03-17 |
75132

76133
---
77-
*Last updated: 2026-03-18 12:16 UTC — auto-generated by beads*
134+
*Last updated: 2026-03-19 01:07 UTC — auto-generated by beads*

.beads/generate_progress.py

Lines changed: 75 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,20 @@
1111
JSONL_PATH = BEADS_DIR / "issues.jsonl"
1212
OUTPUT_PATH = BEADS_DIR / "PROGRESS.md"
1313

14-
# Phase grouping by title prefix
14+
# Phase grouping by title prefix (numbered phases like "1A:", "2B:")
1515
PHASE_MAP = {
1616
"1": ("Phase 1", "Seller Interoperability"),
1717
"2": ("Phase 2", "Campaign Automation"),
1818
"3": ("Phase 3", "Platform & Infrastructure"),
1919
"4": ("Phase 4", "Production Hardening"),
20-
"5": ("Phase 5", "Deal Jockey"),
20+
}
21+
22+
# DealJockey phases mapped by bead ID pattern (buyer-te6b.N.*)
23+
DJ_PHASE_MAP = {
24+
"1": ("DealJockey Phase 1", "Foundation"),
25+
"2": ("DealJockey Phase 2", "Intelligence"),
26+
"3": ("DealJockey Phase 3", "Platform Integrations"),
27+
"4": ("DealJockey Phase 4", "External Model Integration"),
2128
}
2229

2330

@@ -166,11 +173,55 @@ def generate():
166173
blocked = len([i for i in issues if i.get("status") not in ("closed",) and is_blocked(i, closed_ids, all_ids)])
167174
open_count = total - closed - in_progress
168175

169-
# Group by phase
176+
# Filter out LEGACY beads
177+
issues = [i for i in issues if "[LEGACY]" not in i.get("title", "")]
178+
179+
# Recalculate stats after filtering
180+
total = len(issues)
181+
closed = len([i for i in issues if i.get("status") == "closed"])
182+
in_progress = len([i for i in issues if i.get("status") == "in_progress"])
183+
closed_ids = {i["id"] for i in issues if i.get("status") == "closed"}
184+
all_ids = {i["id"] for i in issues}
185+
blocked = len([i for i in issues if i.get("status") not in ("closed",) and is_blocked(i, closed_ids, all_ids)])
186+
open_count = total - closed - in_progress
187+
188+
# Group by phase (numbered) or DealJockey phase (by bead ID)
170189
phases = {}
190+
dj_phases = {}
191+
dj_epics = [] # top-level DealJockey epics
171192
ungrouped = []
172193
for issue in issues:
173-
phase = get_phase(issue.get("title", ""))
194+
iid = issue.get("id", "")
195+
title = issue.get("title", "")
196+
197+
# DealJockey beads: buyer-te6b, buyer-te6b.N, buyer-te6b.N.M
198+
if iid.startswith("buyer-te6b"):
199+
# Top-level epic or phase epic
200+
if iid == "buyer-te6b":
201+
dj_epics.append(issue)
202+
elif re.match(r"buyer-te6b\.\d+$", iid):
203+
# Phase epic like buyer-te6b.2
204+
phase_num = iid.split(".")[-1]
205+
dj_phases.setdefault(phase_num, []).insert(0, issue)
206+
elif re.match(r"buyer-te6b\.\d+\.\d+", iid):
207+
# Task like buyer-te6b.2.3
208+
phase_num = iid.split(".")[1]
209+
dj_phases.setdefault(phase_num, []).append(issue)
210+
else:
211+
ungrouped.append(issue)
212+
continue
213+
214+
# DealJockey Phase 1 execution beads (buyer-5tg, buyer-muf, etc.)
215+
# These are grouped under DealJockey Phase 1 by checking title/description
216+
dj_p1_titles = ["Deal library schema", "DealJockey L2 agent", "DealJockey event types",
217+
"Deal library CRUD", "CSV deal import", "Manual deal entry",
218+
"Portfolio inspection", "DealJockey Phase 1"]
219+
if any(t.lower() in title.lower() for t in dj_p1_titles):
220+
dj_phases.setdefault("1", []).append(issue)
221+
continue
222+
223+
# Numbered phase tasks (1A:, 2B:, etc.)
224+
phase = get_phase(title)
174225
if phase:
175226
phases.setdefault(phase, []).append(issue)
176227
else:
@@ -233,6 +284,26 @@ def generate():
233284

234285
lines.append("")
235286

287+
# Render DealJockey phases
288+
if dj_phases or dj_epics:
289+
for phase_num in sorted(dj_phases.keys()):
290+
phase_name, phase_desc = DJ_PHASE_MAP.get(phase_num, (f"DealJockey Phase {phase_num}", ""))
291+
lines.append(f"## {phase_name}{phase_desc}\n")
292+
lines.append("| | ID | Task | Priority | Blockers | Done |")
293+
lines.append("|---|---|---|---|---|---|")
294+
295+
for issue in dj_phases[phase_num]:
296+
icon = status_icon(issue, closed_ids, all_ids)
297+
iid = issue["id"]
298+
title = issue.get("title", "")
299+
priority = f"P{issue.get('priority', '?')}"
300+
blockers = get_blocker_ids(issue, all_ids)
301+
unresolved = [b for b in blockers if b not in closed_ids]
302+
blocker_str = ", ".join(unresolved) if unresolved else "—"
303+
done = format_date(issue.get("closed_at", ""))
304+
lines.append(f"| {icon} | {iid} | {title} | {priority} | {blocker_str} | {done} |")
305+
lines.append("")
306+
236307
# Ungrouped issues
237308
if ungrouped:
238309
lines.append("## Other\n")

src/ad_buyer/agents/level2/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
from .linear_tv_agent import create_linear_tv_agent
1010
from .performance_agent import create_performance_agent
1111
from .dsp_agent import create_dsp_agent
12+
from .deal_jockey_agent import create_deal_jockey_agent
1213

1314
__all__ = [
1415
"create_branding_agent",
@@ -17,4 +18,5 @@
1718
"create_linear_tv_agent",
1819
"create_performance_agent",
1920
"create_dsp_agent",
21+
"create_deal_jockey_agent",
2022
]
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
# Author: Green Mountain Systems AI Inc.
2+
# Donated to IAB Tech Lab
3+
4+
"""DealJockey agent - deal portfolio management specialist.
5+
6+
DealJockey is an L2 agent in the buyer hierarchy that manages deal portfolios:
7+
importing, cataloging, inspecting, organizing, migrating, and optimizing deals
8+
across publishers, SSPs, and DSPs.
9+
10+
L1 Routing Heuristics
11+
---------------------
12+
The L1 Portfolio Manager routes requests to DealJockey vs. Campaign flow using
13+
these heuristics (from DEAL_JOCKEY_STRATEGIC_PLAN.md Section 5.4):
14+
15+
-> DealJockey:
16+
"portfolio", "existing deals", "my deals", "migrate", "clone",
17+
"deprecate", "compare prices", "import", "catalog", "gap analysis",
18+
"sunset"
19+
20+
-> Campaign flow (channel specialists):
21+
"campaign", "book for campaign", "budget", "target audience",
22+
"pacing", "flight dates", "launch"
23+
24+
-> Ambiguous (both signals or unclear intent):
25+
L1 asks for clarification: "Are you looking to manage your existing
26+
deal portfolio, or book deals for a specific campaign?"
27+
28+
-> Specific deal ID referenced:
29+
Status check / inspection -> DealJockey
30+
Activate for campaign -> Campaign flow
31+
"""
32+
33+
from typing import Any
34+
35+
from crewai import Agent, LLM
36+
37+
from ...config.settings import settings
38+
39+
40+
def create_deal_jockey_agent(
41+
tools: list[Any] | None = None,
42+
verbose: bool = True,
43+
) -> Agent:
44+
"""Create the DealJockey agent.
45+
46+
The DealJockey agent focuses on deal portfolio management:
47+
- Deal portfolio organization and cataloging
48+
- CSV and bulk deal import/normalization
49+
- Deal template creation and management
50+
- Supply path analysis and optimization
51+
- Cross-platform deal tracking (TTD, DV360, Xandr, Amazon DSP)
52+
- Deal migration and deprecation workflows
53+
- Price comparison across supply paths
54+
- Gap analysis for portfolio coverage
55+
56+
Args:
57+
tools: Optional list of tools for the agent
58+
verbose: Whether to enable verbose logging
59+
60+
Returns:
61+
Configured DealJockey Agent
62+
"""
63+
return Agent(
64+
role="Deal Jockey - Portfolio Manager",
65+
goal="""Manage deal portfolios — import, catalog, inspect, organize,
66+
migrate, and optimize deals across publishers, SSPs, and DSPs. Treat deals
67+
as a managed asset class, ensuring the agency's deal inventory is current,
68+
well-organized, and aligned with campaign needs.""",
69+
backstory="""You are a portfolio management specialist with deep expertise
70+
in programmatic deal operations across the ad tech ecosystem.
71+
72+
Your expertise includes:
73+
- Deal portfolio organization and cataloging
74+
- CSV and bulk deal import/normalization
75+
- Deal template creation and management
76+
- Supply path analysis and optimization
77+
- Cross-platform deal tracking (TTD, DV360, Xandr, Amazon DSP)
78+
- Deal migration and deprecation workflows
79+
- Price comparison across supply paths
80+
- Gap analysis for portfolio coverage
81+
82+
You work alongside channel specialists (Branding, CTV, Performance, Linear TV,
83+
DSP). You receive portfolio-related requests from the L1 Portfolio Manager. You
84+
delegate deal booking to internal deal-booking modules — your role is portfolio
85+
management, not campaign execution.
86+
87+
When a deal needs to be booked for a campaign, you hand off to the appropriate
88+
campaign flow. When you detect underperforming deals or better supply paths, you
89+
propose changes that the campaign flow can execute.""",
90+
llm=LLM(
91+
model=settings.default_llm_model,
92+
temperature=0.3,
93+
),
94+
tools=tools or [],
95+
allow_delegation=True,
96+
verbose=verbose,
97+
memory=True,
98+
)

src/ad_buyer/demo/__init__.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
# Author: Green Mountain Systems AI Inc.
2+
# Donated to IAB Tech Lab
3+
4+
"""Demo tools for the ad buyer system."""

src/ad_buyer/demo/__main__.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# Author: Green Mountain Systems AI Inc.
2+
# Donated to IAB Tech Lab
3+
4+
"""Allow running the demo dashboard via ``python -m ad_buyer.demo``."""
5+
6+
from .dealjockey_dashboard import main
7+
8+
main()

0 commit comments

Comments
 (0)