Skip to content

Commit a32971a

Browse files
bokelleyclaude
andauthored
refactor: Move AdCP schemas from tests/e2e/ to project root (#614)
PROBLEM: The official AdCP JSON schemas were buried in tests/e2e/schemas/v1/, creating confusion about their role as the source of truth for the entire project. This location suggested they were test-specific artifacts rather than core project infrastructure. SOLUTION: Moved schemas to schemas/v1/ at project root to clarify their purpose: - Source of truth for entire project (not just tests) - Used by schema generator (src/core/schemas_generated/) - Used by schema validator (tests/e2e/adcp_schema_validator.py) - Used by pre-commit hooks for compliance checking CHANGES: - Moved tests/e2e/schemas/ → schemas/ - Updated all script references: - scripts/generate_schemas.py - scripts/refresh_schemas.py - scripts/validate_pydantic_against_adcp_schemas.py - scripts/check_schema_sync.py - Updated test file paths: - tests/unit/test_adapter_schema_compliance.py - tests/e2e/adcp_schema_validator.py - Updated documentation: - docs/schema-updates.md - docs/schema-caching-strategy.md - docs/testing/adapter-schema-compliance.md - docs/development/schema-auto-generation.md - CLAUDE.md - Updated .pre-commit-config.yaml file patterns - Updated src/core/schemas_generated/__init__.py header - Added comprehensive schemas/README.md documenting purpose and usage BENEFITS: ✅ Clear that schemas are project-wide source of truth ✅ Easier to understand: 'these are OUR schemas' ✅ No confusion about test vs production schemas ✅ Generator script reads from obvious location ✅ Better project organization TESTING: - Verified schema validator finds new path - Verified generator script works with new path - All references updated and validated 🤖 Generated with Claude Code (https://claude.com/claude-code) Co-authored-by: Claude <noreply@anthropic.com>
1 parent 6c33370 commit a32971a

File tree

189 files changed

+274
-123
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

189 files changed

+274
-123
lines changed

.pre-commit-config.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,7 @@ repos:
176176
name: Validate adapter schemas match AdCP spec
177177
entry: uv run pytest tests/unit/test_adapter_schema_compliance.py -v --tb=short
178178
language: system
179-
files: '^(src/core/schema_adapters\.py|tests/e2e/schemas/v1/.*\.json)$'
179+
files: '^(src/core/schema_adapters\.py|schemas/v1/.*\.json)$'
180180
pass_filenames: false
181181
always_run: true
182182

@@ -185,7 +185,7 @@ repos:
185185
name: Pydantic model alignment with AdCP schemas (REGRESSION PREVENTION)
186186
entry: uv run pytest tests/unit/test_pydantic_schema_alignment.py::TestSpecificFieldValidation -v --tb=short
187187
language: system
188-
files: '^(src/core/schemas\.py|tests/e2e/schemas/v1/.*\.json)$'
188+
files: '^(src/core/schemas\.py|schemas/v1/.*\.json)$'
189189
pass_filenames: false
190190
always_run: true
191191

CLAUDE.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

88
**Schema Hierarchy:**
99
1. **Official Spec** (https://adcontextprotocol.org/schemas/v1/) - Primary source of truth
10-
2. **Cached Schemas** (`tests/e2e/schemas/v1/`) - Checked into git for offline validation
10+
2. **Cached Schemas** (`schemas/v1/`) - Checked into git for offline validation
1111
3. **Pydantic Schemas** (`src/core/schemas.py`) - MUST match official spec exactly
1212

1313
**Rules:**
@@ -33,7 +33,7 @@ pytest tests/e2e/test_adcp_compliance.py -v
3333
pytest tests/unit/test_adcp_contract.py -v
3434

3535
# If schemas are out of date, cached files are auto-updated on next run
36-
# Commit any schema file changes that appear in tests/e2e/schemas/v1/
36+
# Commit any schema file changes that appear in schemas/v1/
3737
```
3838

3939
**Current Schema Version:**

docs/development/schema-auto-generation.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ This project now supports **automatic generation of Pydantic models** from the o
99
### 1. Schema Resolution
1010

1111
The generation script handles the AdCP schema structure:
12-
- **Cached Schemas**: Uses locally cached schemas from `tests/e2e/schemas/v1/`
12+
- **Cached Schemas**: Uses locally cached schemas from `schemas/v1/`
1313
- **Flattened Naming**: Handles the flattened file naming (e.g., `_schemas_v1_core_budget_json.json`)
1414
- **$ref Resolution**: Automatically resolves JSON Schema `$ref` references
1515
- **Auto-Download**: Downloads missing schemas from https://adcontextprotocol.org/schemas/v1/
@@ -24,7 +24,7 @@ python scripts/generate_schemas.py
2424
```
2525

2626
The script:
27-
1. Loads all JSON schemas from `tests/e2e/schemas/v1/`
27+
1. Loads all JSON schemas from `schemas/v1/`
2828
2. Downloads any missing referenced schemas from AdCP website
2929
3. Resolves all `$ref` references recursively
3030
4. Generates clean Pydantic v2 models using `datamodel-code-generator`

docs/schema-caching-strategy.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ else:
8686
### File Organization
8787

8888
```
89-
tests/e2e/schemas/v1/
89+
schemas/v1/
9090
├── index.json # Schema registry
9191
├── index.json.meta # ETag metadata for index
9292
├── _schemas_v1_core_package_json.json # Schema content
@@ -264,10 +264,10 @@ pytest tests/e2e/ --offline-schemas
264264
### Cache inconsistencies
265265
```bash
266266
# Check metadata files
267-
ls -la tests/e2e/schemas/v1/*.meta
267+
ls -la schemas/v1/*.meta
268268

269269
# View ETag for specific schema
270-
cat tests/e2e/schemas/v1/index.json.meta
270+
cat schemas/v1/index.json.meta
271271
```
272272

273273
### Debugging ETag behavior

docs/schema-updates.md

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ This document describes how to keep our locally cached AdCP schemas synchronized
44

55
## Overview
66

7-
We maintain local cached copies of AdCP schemas in `tests/e2e/schemas/v1/` for:
7+
We maintain local cached copies of AdCP schemas in `schemas/v1/` for:
88
- Offline development and testing
99
- Schema validation in CI
1010
- Pydantic model generation via `scripts/generate_schemas.py`
@@ -60,7 +60,7 @@ uv run python scripts/check_schema_sync.py
6060
uv run python scripts/generate_schemas.py
6161

6262
# Commit changes
63-
git add tests/e2e/schemas/ src/core/schemas_generated/
63+
git add schemas/ src/core/schemas_generated/
6464
git commit -m "Update AdCP schemas to latest from registry"
6565
```
6666

@@ -71,14 +71,14 @@ If you need to update a specific schema:
7171
```bash
7272
# Download specific schema
7373
curl -s https://adcontextprotocol.org/schemas/v1/media-buy/package-request.json > \
74-
tests/e2e/schemas/v1/_schemas_v1_media-buy_package-request_json.json
74+
schemas/v1/_schemas_v1_media-buy_package-request_json.json
7575

7676
# Download dependencies (e.g., format-id.json)
7777
curl -s https://adcontextprotocol.org/schemas/v1/core/format-id.json > \
78-
tests/e2e/schemas/v1/_schemas_v1_core_format-id_json.json
78+
schemas/v1/_schemas_v1_core_format-id_json.json
7979

8080
# Verify schema structure
81-
cat tests/e2e/schemas/v1/_schemas_v1_media-buy_package-request_json.json | \
81+
cat schemas/v1/_schemas_v1_media-buy_package-request_json.json | \
8282
jq '.properties.format_ids.items'
8383

8484
# Should show: {"$ref": "/schemas/v1/core/format-id.json"}
@@ -137,7 +137,7 @@ uv run python scripts/check_schema_sync.py --update
137137
uv run python scripts/generate_schemas.py
138138

139139
# Commit both schema cache and generated code
140-
git add tests/e2e/schemas/ src/core/schemas_generated/
140+
git add schemas/ src/core/schemas_generated/
141141
git commit -m "Update AdCP schemas to v{version}"
142142
```
143143

@@ -150,7 +150,7 @@ git commit -m "Update AdCP schemas to v{version}"
150150
**Fix:**
151151
```bash
152152
# 1. Verify cached schema has $ref
153-
cat tests/e2e/schemas/v1/_schemas_v1_media-buy_package-request_json.json | \
153+
cat schemas/v1/_schemas_v1_media-buy_package-request_json.json | \
154154
jq '.properties.format_ids.items'
155155

156156
# Should output: {"$ref": "/schemas/v1/core/format-id.json"}
@@ -172,11 +172,11 @@ This means the cached `package-request.json` is outdated.
172172
```bash
173173
# Download latest schema
174174
curl -s https://adcontextprotocol.org/schemas/v1/media-buy/package-request.json > \
175-
tests/e2e/schemas/v1/_schemas_v1_media-buy_package-request_json.json
175+
schemas/v1/_schemas_v1_media-buy_package-request_json.json
176176

177177
# Download format-id definition
178178
curl -s https://adcontextprotocol.org/schemas/v1/core/format-id.json > \
179-
tests/e2e/schemas/v1/_schemas_v1_core_format-id_json.json
179+
schemas/v1/_schemas_v1_core_format-id_json.json
180180

181181
# Regenerate models
182182
uv run python scripts/generate_schemas.py
@@ -213,7 +213,7 @@ graph TD
213213
- **AdCP GitHub:** https://github.com/adcontextprotocol/adcp
214214
- **Schema Checker:** `scripts/check_schema_sync.py`
215215
- **Schema Generator:** `scripts/generate_schemas.py`
216-
- **Cached Schemas:** `tests/e2e/schemas/v1/`
216+
- **Cached Schemas:** `schemas/v1/`
217217
- **Generated Models:** `src/core/schemas_generated/`
218218

219219
## Recent Changes

docs/testing/adapter-schema-compliance.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ This document explains how we ensure `schema_adapters.py` stays in sync with the
88

99
We have three schema layers:
1010

11-
1. **Official AdCP JSON Schemas** (`tests/e2e/schemas/v1/*.json`) - Source of truth from https://adcontextprotocol.org
11+
1. **Official AdCP JSON Schemas** (`schemas/v1/*.json`) - Source of truth from https://adcontextprotocol.org
1212
2. **Base Pydantic Schemas** (`src/core/schemas.py`) - Generated from JSON schemas, domain data only
1313
3. **Adapter Schemas** (`src/core/schema_adapters.py`) - Wrap base schemas, add `__str__()` for protocol abstraction
1414

@@ -66,7 +66,7 @@ def test_list_authorized_properties_response_matches_spec(self):
6666
name: Validate adapter schemas match AdCP spec
6767
entry: uv run pytest tests/unit/test_adapter_schema_compliance.py -v --tb=short
6868
language: system
69-
files: '^(src/core/schema_adapters\.py|tests/e2e/schemas/v1/.*\.json)$'
69+
files: '^(src/core/schema_adapters\.py|schemas/v1/.*\.json)$'
7070
pass_filenames: false
7171
always_run: true
7272
```
@@ -251,7 +251,7 @@ class MyModel(Base):
251251
1. **Verify field exists in official AdCP spec first:**
252252
```bash
253253
# Check cached schema
254-
cat tests/e2e/schemas/v1/_schemas_v1_media-buy_list-authorized-properties-response_json.json
254+
cat schemas/v1/_schemas_v1_media-buy_list-authorized-properties-response_json.json
255255
```
256256

257257
2. **Add field to adapter schema:**
@@ -290,7 +290,7 @@ Missing: implementation_date (required=False)
290290
```
291291
292292
**How to fix:**
293-
1. Check official schema: `tests/e2e/schemas/v1/_schemas_v1_media-buy_update-media-buy-response_json.json`
293+
1. Check official schema: `schemas/v1/_schemas_v1_media-buy_update-media-buy-response_json.json`
294294
2. Verify field is in spec (lines 60-65 show `implementation_date`)
295295
3. Add field to `schema_adapters.py`:
296296
```python
@@ -323,7 +323,7 @@ Generate adapter schemas from JSON schemas:
323323
```bash
324324
# Generate adapter schema from official spec
325325
python scripts/generate_adapter_schema.py \
326-
--spec tests/e2e/schemas/v1/_schemas_v1_media-buy_list-authorized-properties-response_json.json \
326+
--spec schemas/v1/_schemas_v1_media-buy_list-authorized-properties-response_json.json \
327327
--output src/core/schema_adapters.py \
328328
--class-name ListAuthorizedPropertiesResponse
329329
```

schemas/README.md

Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
# AdCP Schema Cache
2+
3+
This directory contains cached copies of official AdCP JSON schemas from https://adcontextprotocol.org/schemas/
4+
5+
## Purpose
6+
7+
These cached schemas serve as the **source of truth** for the entire project:
8+
9+
1. **Offline Development** - Work without internet access
10+
2. **Schema Validation** - Validate requests/responses in tests (see `tests/e2e/adcp_schema_validator.py`)
11+
3. **Pydantic Generation** - Auto-generate type-safe Pydantic models (see `src/core/schemas_generated/`)
12+
4. **CI/CD Stability** - Ensure consistent schemas across all environments
13+
14+
## Directory Structure
15+
16+
```
17+
schemas/
18+
├── README.md # This file
19+
├── v1/ # AdCP v1 schemas
20+
│ ├── *.json # Cached schema files
21+
│ ├── *.json.meta # Metadata (ETag, Last-Modified)
22+
│ └── SCHEMAS_INFO.md # Schema registry info
23+
└── compliance_report.json # Last compliance check results
24+
```
25+
26+
## Schema Naming Convention
27+
28+
Schema files use a flattened naming convention to avoid directory nesting:
29+
30+
```
31+
/schemas/v1/media-buy/create-media-buy-request.json
32+
→ _schemas_v1_media-buy_create-media-buy-request_json.json
33+
```
34+
35+
This allows simpler file management while preserving the logical structure.
36+
37+
## Updating Schemas
38+
39+
### Automatic Update (Recommended)
40+
41+
```bash
42+
# Download all schemas from official registry
43+
uv run python scripts/refresh_schemas.py
44+
45+
# Regenerate Pydantic models
46+
uv run python scripts/generate_schemas.py
47+
48+
# Commit changes
49+
git add schemas/ src/core/schemas_generated/
50+
git commit -m "Update AdCP schemas to latest from registry"
51+
```
52+
53+
### Manual Update (Specific Schema)
54+
55+
```bash
56+
# Download specific schema
57+
curl -s https://adcontextprotocol.org/schemas/v1/media-buy/create-media-buy-request.json > \
58+
schemas/v1/_schemas_v1_media-buy_create-media-buy-request_json.json
59+
60+
# Regenerate Pydantic models
61+
uv run python scripts/generate_schemas.py
62+
```
63+
64+
## Schema Validation
65+
66+
The `tests/e2e/adcp_schema_validator.py` module uses these cached schemas to validate:
67+
68+
- Request payloads before sending to external systems
69+
- Response payloads from external AdCP agents
70+
- E2E test data for compliance
71+
72+
## ETag-Based Caching
73+
74+
Each schema file has a corresponding `.meta` file containing:
75+
76+
```json
77+
{
78+
"etag": "W/\"abc123\"",
79+
"last-modified": "Mon, 01 Jan 2024 12:00:00 GMT",
80+
"downloaded_at": "2024-01-01T12:00:00",
81+
"schema_ref": "/schemas/v1/media-buy/create-media-buy-request.json"
82+
}
83+
```
84+
85+
The schema validator uses ETags for conditional GET requests:
86+
- If schema hasn't changed on server (304 Not Modified), use cached version
87+
- If schema updated, download and cache new version
88+
- Falls back to cache if server unavailable
89+
90+
## Related Files
91+
92+
- **Schema Generator**: `scripts/generate_schemas.py`
93+
- **Schema Validator**: `tests/e2e/adcp_schema_validator.py`
94+
- **Schema Sync Checker**: `scripts/check_schema_sync.py`
95+
- **Generated Pydantic Models**: `src/core/schemas_generated/`
96+
- **Manual Pydantic Schemas**: `src/core/schemas.py` (hand-written)
97+
98+
## Pre-commit Hooks
99+
100+
Pre-commit hooks automatically check:
101+
102+
1. **Schema Sync** - Ensures cached schemas match official registry
103+
2. **Pydantic Alignment** - Ensures hand-written schemas match official spec
104+
3. **Adapter Compliance** - Ensures adapter schemas use correct structure
105+
106+
If schemas are out of sync, the commit is blocked with instructions to update.
107+
108+
## Version History
109+
110+
- **v1** - Initial AdCP specification (current)
111+
- **v2** - Future version (when released)
112+
113+
## Official Sources
114+
115+
- **Registry**: https://adcontextprotocol.org/schemas/v1/
116+
- **Documentation**: https://adcontextprotocol.org/docs/
117+
- **GitHub**: https://github.com/adcontextprotocol/adcp
118+
119+
## FAQ
120+
121+
### Why cache schemas locally?
122+
123+
1. **Offline Development** - Work without internet
124+
2. **Deterministic Builds** - CI doesn't depend on external services
125+
3. **Fast Tests** - No network overhead during test runs
126+
4. **Version Control** - Track schema changes in git
127+
128+
### How often should I update schemas?
129+
130+
- **Development**: When you need new features or notice missing fields
131+
- **Production**: Before each major release
132+
- **CI**: Pre-commit hooks check automatically
133+
134+
### What if schemas are out of sync?
135+
136+
Pre-commit hooks will block commits and show:
137+
138+
```
139+
❌ Schema out of sync: create-media-buy-request.json
140+
Run: uv run python scripts/refresh_schemas.py
141+
```
142+
143+
Just run the suggested command and commit the changes.
144+
145+
### Why both cached schemas AND generated Pydantic models?
146+
147+
- **Cached JSON**: Source of truth for validation (runtime)
148+
- **Generated Pydantic**: Type-safe models for development (compile-time)
149+
150+
Both serve different purposes and are generated from the same official schemas.
File renamed without changes.

tests/e2e/schemas/v1/_schemas_v1_adagents_json.json renamed to schemas/v1/_schemas_v1_adagents_json.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,4 +72,4 @@
7272
"last_updated": "2025-01-10T15:30:00Z"
7373
}
7474
]
75-
}
75+
}

0 commit comments

Comments
 (0)