Skip to content

Commit e20e36d

Browse files
authored
Merge pull request #3637 from PolicyEngine/migration-pr1-contract-harness
Add migration stage 1 contracts and AI harness
2 parents 424f3d6 + 71b6a2c commit e20e36d

34 files changed

Lines changed: 2794 additions & 2 deletions

.github/copilot-instructions.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
# Copilot Instructions
2+
3+
Follow the repository's canonical engineering skills under
4+
`docs/engineering/skills/`.
5+
6+
For API v2 migration contract, route-group metadata, generated migration docs,
7+
or migration guard changes, read
8+
`docs/engineering/skills/migration_contracts.md`.
9+
10+
For tests, read `docs/engineering/skills/testing.md` before adding, moving, or
11+
reviewing test files.
12+
13+
For pull requests, read `docs/engineering/skills/github-prs.md` before opening,
14+
replacing, or sharing a PR.

.github/workflows/pr.yml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,18 @@ jobs:
1818
run: pip install ruff>=0.9.0
1919
- name: Format check with ruff
2020
run: ruff format --check .
21+
quality-guards:
22+
name: Quality guards
23+
runs-on: ubuntu-latest
24+
steps:
25+
- name: Checkout repo
26+
uses: actions/checkout@v4
27+
- name: Setup Python
28+
uses: actions/setup-python@v5
29+
with:
30+
python-version: "3.12"
31+
- name: Run quality guards
32+
run: python scripts/run_quality_guards.py
2133
check-changelog:
2234
name: Check changelog fragment
2335
runs-on: ubuntu-latest

AGENTS.md

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
# Agent Instructions
2+
3+
These instructions apply repository-wide.
4+
5+
## Skills System
6+
7+
Canonical AI-facing engineering skills live under `docs/engineering/skills/`.
8+
Use those files as the source of truth across Codex, Claude, Copilot, and other
9+
AI tools.
10+
11+
When changing API v2 migration contracts, route-group migration metadata, PR
12+
cutover plans, generated migration docs, or migration guard scripts, read
13+
`docs/engineering/skills/migration_contracts.md`.
14+
15+
When adding, moving, or reviewing tests, read
16+
`docs/engineering/skills/testing.md`.
17+
18+
## GitHub PRs
19+
20+
Read `docs/engineering/skills/github-prs.md` before opening, replacing, or
21+
sharing any pull request.
22+
23+
Before creating or sharing a migration PR, run the focused migration guards:
24+
25+
```bash
26+
python scripts/run_quality_guards.py
27+
python scripts/export_migration_contracts.py
28+
```

CLAUDE.md

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
# Claude Instructions
2+
3+
These instructions apply repository-wide.
4+
5+
## Canonical Guidance
6+
7+
Repository-wide AI-facing engineering guidance lives in `AGENTS.md`.
8+
Canonical skills live under `docs/engineering/skills/`.
9+
10+
Use those files as the source of truth. This file is a Claude adapter and should
11+
stay thin; do not duplicate detailed testing, CI, formatting, or architecture
12+
rules here.
13+
14+
## Required Skill Lookup
15+
16+
Before opening, replacing, or sharing a PR, read
17+
`docs/engineering/skills/github-prs.md`.
18+
19+
When changing API v2 migration contracts, route-group migration metadata,
20+
generated migration docs, or migration guard scripts, read
21+
`docs/engineering/skills/migration_contracts.md`.
22+
23+
When adding, moving, or reviewing tests, read
24+
`docs/engineering/skills/testing.md`.
25+
26+
## Safety Boundaries
27+
28+
Do not claim a route, database table, compute path, or deployment surface has
29+
migrated unless the relevant contract tests, migration flags, and generated
30+
migration docs identify that state.

Makefile

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,11 @@ test-env-vars:
1111
pytest tests/env_variables
1212

1313
test:
14-
MAX_HOUSEHOLDS=1000 coverage run -a --branch -m pytest tests/to_refactor tests/unit tests/integration/test_budget_window_in_flight_dedupe.py --disable-pytest-warnings
15-
coverage xml -i
14+
MAX_HOUSEHOLDS=1000 python -m coverage run -a --branch -m pytest tests/to_refactor tests/unit tests/contract tests/integration/test_budget_window_in_flight_dedupe.py --disable-pytest-warnings
15+
python -m coverage xml -i
16+
17+
quality-guards:
18+
python scripts/run_quality_guards.py
1619

1720
debug-test:
1821
MAX_HOUSEHOLDS=1000 FLASK_DEBUG=1 pytest -vv --durations=0 tests
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Added migration contract tests, typed migration registries, no-op source flags, migration-context logging, baseline capture tooling, and model-agnostic AI harness docs for the API v2 migration.
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
# Migration Contracts
2+
3+
Generated from `policyengine_api/migration_registry.py` and `tests/contract/registry.py`.
4+
5+
## Summary
6+
7+
| Metric | Count |
8+
| --- | ---: |
9+
| route group count | 10 |
10+
| workflow count | 7 |
11+
| request count | 14 |
12+
| db entity count | 6 |
13+
| sim flow count | 3 |
14+
15+
## Route Groups
16+
17+
| Route group | Path segments | DB entity | Simulation flow |
18+
| --- | --- | --- | --- |
19+
| `metadata` | `metadata` | `metadata` | `none` |
20+
| `policy` | `policy`, `policies`, `user-policy` | `policy` | `none` |
21+
| `household` | `household`, `calculate`, `calculate-full` | `household` | `household` |
22+
| `economy` | `economy` | `simulation` | `economy` |
23+
| `simulation` | `simulation`, `simulations` | `simulation` | `economy` |
24+
| `report` | `report` | `report` | `report` |
25+
| `user_profile` | `user-profile` | `user` | `none` |
26+
| `simulation_analysis` | `simulation-analysis` | `none` | `none` |
27+
| `tracer_analysis` | `tracer-analysis` | `none` | `none` |
28+
| `ai` | `ai-prompts` | `none` | `none` |
29+
30+
## App V2 Workflow Contracts
31+
32+
### `policy_save_search`
33+
34+
- Current contract: `api_v1_compatible`
35+
- Future owner: PR 10: Policy Migration
36+
37+
| Method | Path | Status | Route group | Stable response fields |
38+
| --- | --- | ---: | --- | --- |
39+
| `POST` | `/us/policy` | 201 | `policy` | `status`, `message`, `result.policy_id` |
40+
| `GET` | `/us/policy/{policy_id}` | 200 | `policy` | `status`, `message`, `result` |
41+
| `GET` | `/us/policies` | 200 | `policy` | `result` |
42+
43+
### `household_save_edit_read`
44+
45+
- Current contract: `api_v1_compatible`
46+
- Future owner: PR 11: Household Migration
47+
48+
| Method | Path | Status | Route group | Stable response fields |
49+
| --- | --- | ---: | --- | --- |
50+
| `POST` | `/us/household` | 201 | `household` | `status`, `message`, `result.household_id` |
51+
| `PUT` | `/us/household/{household_id}` | 200 | `household` | `status`, `message`, `result.household_id` |
52+
| `GET` | `/us/household/{household_id}` | 200 | `household` | `status`, `message`, `result` |
53+
54+
### `household_calculate`
55+
56+
- Current contract: `api_v1_compatible`
57+
- Future owner: PR 13: Household Calculation Compute Cutover
58+
59+
| Method | Path | Status | Route group | Stable response fields |
60+
| --- | --- | ---: | --- | --- |
61+
| `POST` | `/us/calculate` | 200 | `household` | `status`, `message`, `result` |
62+
63+
### `region_selection`
64+
65+
- Current contract: `api_v1_compatible`
66+
- Future owner: PR 9: v2 Metadata, Regions, Datasets, Parameters, and Variables
67+
68+
| Method | Path | Status | Route group | Stable response fields |
69+
| --- | --- | ---: | --- | --- |
70+
| `GET` | `/us/metadata` | 200 | `metadata` | `status`, `result.current_law_id`, `result.economy_options.region`, `result.economy_options.time_period` |
71+
| `GET` | `/uk/metadata` | 200 | `metadata` | `status`, `result.current_law_id`, `result.economy_options.region`, `result.economy_options.time_period` |
72+
73+
### `simulation_submit_poll`
74+
75+
- Current contract: `api_v1_compatible`
76+
- Future owner: PR 13: Household Calculation Compute Cutover
77+
78+
| Method | Path | Status | Route group | Stable response fields |
79+
| --- | --- | ---: | --- | --- |
80+
| `POST` | `/us/simulation` | 201 | `simulation` | `status`, `message`, `result.id`, `result.status` |
81+
| `GET` | `/us/simulation/{simulation_id}` | 200 | `simulation` | `status`, `message`, `result` |
82+
83+
### `report_create_poll`
84+
85+
- Current contract: `api_v1_compatible`
86+
- Future owner: PR 14: Economy Simulation and Economic Impact Compute Cutover
87+
88+
| Method | Path | Status | Route group | Stable response fields |
89+
| --- | --- | ---: | --- | --- |
90+
| `POST` | `/us/report` | 201 | `report` | `status`, `message`, `result.id`, `result.status` |
91+
| `GET` | `/us/report/{report_id}` | 200 | `report` | `status`, `message`, `result` |
92+
93+
### `budget_window_submit_poll`
94+
95+
- Current contract: `api_v1_compatible`
96+
- Future owner: PR 15: Budget-Window and Remaining Simulation API Migration
97+
98+
| Method | Path | Status | Route group | Stable response fields |
99+
| --- | --- | ---: | --- | --- |
100+
| `GET` | `/us/economy/{policy_id}/over/{baseline_policy_id}/budget-window?region=us&start_year=2026&window_size=1` | 200 | `economy` | `status`, `result.kind`, `progress`, `completed_years`, `computing_years`, `queued_years`, `error` |

docs/engineering/skills/README.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
# Engineering Skills
2+
3+
This directory is the canonical source for AI-facing engineering rules.
4+
5+
Tool-specific instruction files such as `AGENTS.md`, `CLAUDE.md`, and
6+
`.github/copilot-instructions.md` should point here instead of duplicating
7+
implementation-specific guidance. When a rule changes, update the skill here
8+
first, then keep adapters thin.
9+
10+
Current skills:
11+
12+
- `github-prs.md`: PR workflow and migration PR handoff expectations.
13+
- `migration_contracts.md`: API v2 migration route contracts, route-group
14+
metadata, generated migration artifacts, and quality guards.
15+
- `testing.md`: focused test commands and dependency boundaries for migration
16+
work.
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
# GitHub PRs
2+
3+
Use this skill before opening, replacing, or sharing a pull request.
4+
5+
## Migration PRs
6+
7+
Migration PRs should keep the user experience stable unless the PR explicitly
8+
declares an API contract change. If a PR changes migration route contracts,
9+
route-group metadata, generated migration artifacts, or the cutover guardrails,
10+
it should:
11+
12+
1. Include a changelog fragment.
13+
2. Refresh generated migration artifacts with
14+
`python scripts/export_migration_contracts.py`.
15+
3. Run `python scripts/run_quality_guards.py`.
16+
4. Run the focused contract or unit tests that cover the changed surface.
17+
18+
## PR Descriptions
19+
20+
For migration work, identify:
21+
22+
- which route groups or workflows are covered;
23+
- what remains on the Flask/API v1 path;
24+
- what is newly prepared for FastAPI, SQLAlchemy/Alembic, Supabase, Cloud Run,
25+
or Modal migration;
26+
- which user-visible API contract changes are intentionally introduced.
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
# Migration Contracts
2+
3+
Use this skill when changing API v2 migration contracts, route-group migration
4+
metadata, generated migration docs, or guard scripts.
5+
6+
## Sources Of Truth
7+
8+
- `policyengine_api/migration_registry.py` defines route groups, path segments,
9+
database entities, and simulation flows used by migration flags and request
10+
logging.
11+
- `tests/contract/registry.py` defines app-v2 user workflows and stable route
12+
response fields that must be preserved while the migration is staged.
13+
- `scripts/export_migration_contracts.py` merges those sources into:
14+
- `docs/generated/migration_contracts.json`
15+
- `docs/engineering/migration-contracts.md`
16+
17+
Generated migration artifacts are checked-in review material. If a PR changes a
18+
route group, workflow contract, stable response field, or future owner PR, run
19+
the exporter and commit the regenerated files in the same PR.
20+
21+
## Update Workflow
22+
23+
```bash
24+
python scripts/export_migration_contracts.py
25+
python scripts/run_quality_guards.py
26+
python -m pytest tests/contract tests/unit/test_migration_contract_artifacts.py -q
27+
```
28+
29+
The migration-contracts guard checks that workflow names and route requests are
30+
unique, every contract route group is declared in the migration registry, stable
31+
response fields are present, and generated artifacts match the current
32+
registry.
33+
34+
## Annotation Rules
35+
36+
Keep contract metadata explicit and durable:
37+
38+
- Use stable route-group names that match the migration flag environment
39+
surface.
40+
- Record the current user-facing contract, not an aspirational target.
41+
- Keep `future_owner_pr` at the granularity of the migration plan so reviewers
42+
can tell which later PR owns each workflow.
43+
- Add only response fields that are meaningful user-facing compatibility
44+
anchors.
45+
- If a route intentionally changes its API contract, update the generated docs
46+
and call that out in the PR description.

0 commit comments

Comments
 (0)