Aiwg regression-api-contract
Detect breaking changes in API contracts across REST, GraphQL, and gRPC interfaces with semver enforcement
git clone https://github.com/jmagly/aiwg
T=$(mktemp -d) && git clone --depth=1 https://github.com/jmagly/aiwg "$T" && mkdir -p ~/.claude/skills && cp -r "$T/agentic/code/frameworks/sdlc-complete/skills/regression-api-contract" ~/.claude/skills/jmagly-aiwg-regression-api-contract-504d82 && rm -rf "$T"
agentic/code/frameworks/sdlc-complete/skills/regression-api-contract/SKILL.mdregression-api-contract
Detect breaking changes in API contracts across REST, GraphQL, and gRPC interfaces.
Triggers
Alternate expressions and non-obvious activations (primary phrases are matched automatically from the skill description):
- "breaking change" → API contract regression
- "schema compatibility" → contract validation
- "Pact" / "Swagger diff" → contract testing tool names
Purpose
This skill detects API contract regressions by:
- Identifying breaking changes in REST API endpoints
- Detecting schema changes in request/response contracts
- Validating GraphQL schema compatibility
- Checking gRPC/protobuf definition changes
- Enforcing semantic versioning compliance
- Integrating consumer contract testing (Pact, Spring Cloud Contract)
Behavior
When triggered, this skill:
-
Identifies API contract scope:
- Discover API definition files (OpenAPI, GraphQL, protobuf)
- Identify baseline version for comparison
- Determine API type (REST, GraphQL, gRPC)
- Locate consumer contract tests
-
Compares contracts to baseline:
- Load current API definition
- Load baseline API definition
- Run compatibility analysis using appropriate tools
- Generate detailed diff of changes
-
Classifies changes by severity:
- BREAKING: Removed endpoints, fields, or enum values; type changes; new required fields
- NON-BREAKING: New optional fields, new endpoints, extended enums
- DEPRECATED: Marked for future removal
- INTERNAL: Implementation changes with no contract impact
-
Validates semantic versioning:
- Check if version increment matches change type
- Ensure breaking changes trigger major version bump
- Verify non-breaking changes use minor/patch versions
- Flag version mismatches
-
Runs consumer contract tests:
- Execute Pact or Spring Cloud Contract tests
- Validate against consumer expectations
- Identify consumers affected by changes
- Generate compatibility matrix
-
Generates compatibility report:
- List all breaking changes with locations
- Document affected consumers
- Recommend version bump strategy
- Suggest migration paths for consumers
Breaking Change Categories
REST API Breaking Changes
rest_breaking_changes: removed: - endpoint: "DELETE /api/v1/users/{id}" severity: BREAKING reason: "Endpoint removed entirely" - field: "email" from "User" response severity: BREAKING reason: "Required field removed from response" - enum_value: "PENDING" from "OrderStatus" severity: BREAKING reason: "Enum value removed" modified: - field: "created_at" from_type: "string" to_type: "integer" severity: BREAKING reason: "Field type changed" - field: "email" from_required: false to_required: true severity: BREAKING reason: "Optional field made required in request" - constraint: "password" from: "minLength: 6" to: "minLength: 12" severity: BREAKING reason: "Stricter validation on request field" renamed: - endpoint: "GET /api/v1/user/{id}" to: "GET /api/v1/users/{id}" severity: BREAKING reason: "Path renamed without redirect/alias" - parameter: "userId" to: "user_id" severity: BREAKING reason: "Parameter renamed without backward compatibility"
GraphQL Schema Breaking Changes
graphql_breaking_changes: removed: - field: "User.email" severity: BREAKING reason: "Field removed from type" - argument: "Query.users(filter: UserFilter)" severity: BREAKING reason: "Required argument removed" - type: "Address" severity: BREAKING reason: "Type removed from schema" modified: - field: "User.age" from_type: "Int" to_type: "String" severity: BREAKING reason: "Field type changed" - field: "User.email" from_nullable: true to_nullable: false severity: BREAKING reason: "Field made non-nullable" - argument: "Query.user(id: ID)" from_optional: true to_optional: false severity: BREAKING reason: "Argument made required" interface_changes: - interface: "Node" removed_implementation: "User" severity: BREAKING reason: "Type no longer implements interface"
gRPC/Protobuf Breaking Changes
grpc_breaking_changes: removed: - field: "UserMessage.email" field_number: 3 severity: BREAKING reason: "Field removed from message" - service: "UserService" severity: BREAKING reason: "Service removed" - rpc: "UserService.GetUser" severity: BREAKING reason: "RPC method removed" modified: - field: "UserMessage.age" from_type: "int32" to_type: "string" severity: BREAKING reason: "Field type changed" - field: "UserMessage.name" from_label: "optional" to_label: "required" severity: BREAKING reason: "Field made required" - field_number: 5 from_reserved: false to_reserved: true severity: BREAKING reason: "Field number reserved (deletion)" renamed: - message: "User" to: "UserAccount" severity: BREAKING reason: "Message type renamed" - enum: "Status" to: "OrderStatus" severity: BREAKING reason: "Enum renamed"
API Contract Tools Integration
OpenAPI/REST
openapi_tools: primary: openapi-diff alternatives: - oasdiff - swagger-diff - api-diff usage: install: "npm install -g openapi-diff" compare: | openapi-diff \ .aiwg/api/baselines/openapi-v1.yaml \ .aiwg/api/current/openapi.yaml \ --format markdown \ --breaking-only output: ".aiwg/api/compatibility/openapi-diff.md" configuration: strict_mode: true ignore_descriptions: true treat_as_breaking: - removed_endpoints - removed_fields - type_changes - required_field_additions - enum_value_removals
GraphQL
graphql_tools: primary: graphql-inspector alternatives: - apollo-cli (schema:check) - graphql-schema-diff usage: install: "npm install -g @graphql-inspector/cli" compare: | graphql-inspector diff \ .aiwg/api/baselines/schema-v1.graphql \ .aiwg/api/current/schema.graphql \ --onComplete report.json output: ".aiwg/api/compatibility/graphql-diff.json" configuration: fail_on_breaking: true include_dangerous: true schema_extensions: true
gRPC/Protobuf
protobuf_tools: primary: buf alternatives: - prototool - protoc-gen-validate usage: install: "brew install buf" # or "go install github.com/bufbuild/buf/cmd/buf@latest" setup: | # Create buf.yaml version: v1 breaking: use: - FILE lint: use: - DEFAULT compare: | buf breaking \ .aiwg/api/current \ --against .aiwg/api/baselines/v1 output: "Breaking change detection via buf CLI" configuration: breaking_rules: - FIELD_SAME_TYPE - FIELD_NO_DELETE - ENUM_VALUE_NO_DELETE - RPC_NO_DELETE - MESSAGE_NO_DELETE
Semantic Versioning Compliance
semver_validation: rules: breaking_change: requires: major_version_bump examples: - "v1.2.3 → v2.0.0" violations: - detected: breaking_change version_change: "v1.2.3 → v1.3.0" verdict: VIOLATION message: "Breaking change detected but only minor version bumped" non_breaking_addition: requires: minor_version_bump examples: - "v1.2.3 → v1.3.0" acceptable: - "v1.2.3 → v2.0.0" # Major bump also acceptable bug_fix: requires: patch_version_bump examples: - "v1.2.3 → v1.2.4" acceptable: - "v1.2.3 → v1.3.0" # Minor/major also acceptable enforcement: block_deployment: true # Block if version mismatch require_override: true # Allow manual override with justification
Consumer Contract Testing
Pact Integration
pact_integration: provider: api-service consumers: - name: web-frontend pact_file: ".aiwg/api/pacts/web-frontend.json" criticality: high - name: mobile-app pact_file: ".aiwg/api/pacts/mobile-app.json" criticality: high - name: partner-api pact_file: ".aiwg/api/pacts/partner-api.json" criticality: medium verification: run: | npm run test:pact # Verifies provider meets all consumer contracts on_failure: action: block_deployment notification: consumers_affected compatibility_matrix: provider_version: v2.0.0 consumers: - consumer: web-frontend version: v1.5.0 compatible: true tests_passing: 45/45 - consumer: mobile-app version: v2.1.0 compatible: false tests_passing: 38/42 failing_tests: - "POST /api/users - email field type mismatch" - "GET /api/users/{id} - missing 'phone' field" - consumer: partner-api version: v1.0.0 compatible: true tests_passing: 12/12
Spring Cloud Contract
spring_cloud_contract: contracts_location: ".aiwg/api/contracts/" consumers: - name: order-service contracts: "contracts/order-service/**/*.groovy" - name: payment-service contracts: "contracts/payment-service/**/*.groovy" verification: run: "./mvnw clean test" stub_generation: true publish_stubs: true compatibility_check: baseline: v1.0.0 current: v2.0.0 results: - consumer: order-service compatible: true contracts_verified: 8/8 - consumer: payment-service compatible: false contracts_verified: 5/7 failures: - "User schema missing 'email' field" - "Order status enum missing 'PENDING'"
API Compatibility Report
# API Compatibility Report **Date**: 2026-01-28 **Baseline**: v1.5.0 (OpenAPI) **Current**: v2.0.0 **API Type**: REST (OpenAPI 3.0) ## Executive Summary **Status**: ⚠️ BREAKING CHANGES DETECTED **Severity**: HIGH **Breaking Changes**: 5 **Non-Breaking Changes**: 12 **Version Compliance**: ✅ CORRECT (major bump) **Consumer Impact**: 2 of 4 consumers affected ## Version Validation | Aspect | Baseline | Current | Required | Status | |--------|----------|---------|----------|--------| | Version | v1.5.0 | v2.0.0 | v2.x.x | ✅ CORRECT | | Reason | - | Breaking changes detected | Major bump | ✅ VALID | ## Breaking Changes ### 1. Removed Endpoint **Endpoint**: `DELETE /api/v1/users/{id}` **Severity**: BREAKING **Impact**: HIGH **Details**: - Endpoint removed entirely from API - No replacement or redirect provided - Used by 2 consumers: `web-frontend`, `admin-panel` **Consumer Impact**: - web-frontend: 3 call sites affected - admin-panel: 1 call site affected **Recommendation**: - Provide migration path: Use `POST /api/v1/users/{id}/deactivate` instead - Update consumer documentation - Consider deprecation period instead of immediate removal ### 2. Field Removed: `User.email` **Resource**: `User` (GET /api/v1/users/{id} response) **Field**: `email` **Severity**: BREAKING **Impact**: CRITICAL **Details**: - Required field `email` removed from User response - Breaking for consumers expecting this field - No alternative field provided **Consumer Impact**: - web-frontend: AFFECTED (displays user email in profile) - mobile-app: AFFECTED (uses email for contact) - partner-api: NOT AFFECTED (does not use email) **Recommendation**: - DO NOT REMOVE - Add deprecation warning instead - Or provide migration: Add `contactInfo.email` as replacement - Document migration path clearly ### 3. Field Type Changed: `created_at` **Field**: `created_at` **From**: `string` (ISO-8601) **To**: `integer` (Unix timestamp) **Severity**: BREAKING **Impact**: HIGH **Details**: - Field type incompatible change - All consumers parsing as ISO-8601 will break - No backward compatibility layer **Consumer Impact**: - ALL CONSUMERS AFFECTED (4/4) - Requires code changes in all consumers **Recommendation**: - Add `created_at_unix` as new field (non-breaking) - Deprecate `created_at` string format - Maintain both for 2 versions before removing string format ### 4. New Required Field: `password_policy` **Endpoint**: `POST /api/v1/users` **Field**: `password_policy` **Severity**: BREAKING **Impact**: MEDIUM **Details**: - New field added as required in request body - Consumers not sending this field will get 400 errors - Breaking for existing integrations **Consumer Impact**: - web-frontend: AFFECTED (user registration form) - mobile-app: AFFECTED (sign-up flow) **Recommendation**: - Make field optional with sensible default - Or add default value if not provided - Document new requirement clearly ### 5. Enum Value Removed: `OrderStatus.PENDING` **Enum**: `OrderStatus` **Value**: `PENDING` **Severity**: BREAKING **Impact**: HIGH **Details**: - Enum value removed without replacement - Consumers comparing against `PENDING` will break - Orders in `PENDING` state require migration **Consumer Impact**: - order-service: CRITICAL (manages pending orders) - payment-service: AFFECTED (checks pending status) **Recommendation**: - DO NOT REMOVE - Deprecate instead - Or provide mapping: `PENDING` → `AWAITING_CONFIRMATION` - Migrate existing data before API deployment ## Non-Breaking Changes ### Safe Additions | Change | Type | Impact | |--------|------|--------| | New endpoint: `GET /api/v2/users/search` | Addition | None | | New optional field: `User.avatar_url` | Addition | None | | New enum value: `OrderStatus.CANCELLED` | Addition | None | | New query parameter: `?include_inactive` | Addition | None | ### Deprecations | Item | Deprecated In | Remove In | Replacement | |------|---------------|-----------|-------------| | `GET /api/v1/users/list` | v2.0.0 | v3.0.0 | `GET /api/v2/users` | | Field `User.phone` | v2.0.0 | v3.0.0 | `User.contactInfo.phone` | ## Consumer Contract Test Results ### Pact Verification | Consumer | Version | Compatible | Tests | Failures | |----------|---------|------------|-------|----------| | web-frontend | v1.5.0 | ❌ NO | 38/45 | 7 | | mobile-app | v2.1.0 | ❌ NO | 40/42 | 2 | | partner-api | v1.0.0 | ✅ YES | 12/12 | 0 | | admin-panel | v0.9.0 | ❌ NO | 15/18 | 3 | ### Failing Contract Tests **web-frontend failures**: 1. `GET /api/v1/users/{id}` - Missing `email` field in response 2. `POST /api/v1/users` - Missing required field `password_policy` 3. `DELETE /api/v1/users/{id}` - Endpoint not found (404) **mobile-app failures**: 1. `GET /api/v1/users/{id}` - Field type mismatch: `created_at` 2. `POST /api/v1/users` - Validation error: `password_policy` required **admin-panel failures**: 1. `DELETE /api/v1/users/{id}` - Endpoint removed 2. `GET /api/v1/orders` - Enum value `PENDING` not recognized 3. `GET /api/v1/users/{id}` - Missing `email` field ## Backward Compatibility Analysis ```yaml compatibility_assessment: backward_compatible: false reason: "5 breaking changes detected" migration_effort: web-frontend: HIGH (7 changes required) mobile-app: MEDIUM (2 changes required) partner-api: NONE (no changes needed) admin-panel: HIGH (3 changes required) recommended_strategy: option_1: name: "Parallel API versions" description: "Maintain v1 and v2 simultaneously" effort: HIGH timeline: "6 months dual support" option_2: name: "Phased migration" description: "Reduce breaking changes, migrate in phases" effort: MEDIUM timeline: "3 months migration window" preferred: true option_3: name: "Hard cutover" description: "Deploy v2, deprecate v1 immediately" effort: LOW timeline: "1 month notice" risk: HIGH
Recommendations
Immediate Actions
- Revert breaking changes or provide backward compatibility layer
- Make
field optional with default valuepassword_policy - Add
alongsidecreated_at_unix
stringcreated_at - Do not remove
field - deprecate with timeline insteademail - Provide
→PENDING
enum mappingAWAITING_CONFIRMATION
Consumer Migration
- Notify all consumers of breaking changes
- Provide migration guide with code examples
- Offer migration support timeline (3 months)
- Update consumer contract tests
- Coordinate deployment across consumers
Process Improvements
- Add contract testing to CI/CD pipeline
- Require compatibility report in PR template
- Enforce semantic versioning in release process
- Implement API deprecation policy (6-month notice)
- Add breaking change review gate
Migration Guide
For web-frontend
// User profile display - const email = user.email; + const email = user.contactInfo?.email || user.email; // User registration const userData = { username: form.username, password: form.password, + password_policy: 'default', }; // Delete user - await api.delete(`/api/v1/users/${id}`); + await api.post(`/api/v1/users/${id}/deactivate`);
For mobile-app
// Timestamp parsing - const createdAt = new Date(user.created_at); // ISO string + const createdAt = user.created_at_unix + ? new Date(user.created_at_unix * 1000) + : new Date(user.created_at); // User registration const userData = { ... + password_policy: 'default', };
Tool Output
OpenAPI Diff
$ openapi-diff baseline.yaml current.yaml --breaking-only BREAKING CHANGES DETECTED (5): 1. DELETE /api/v1/users/{id} - Endpoint removed 2. GET /api/v1/users/{id} - Response schema changed - Field 'email' removed 3. POST /api/v1/users - Request schema changed - Field 'password_policy' now required 4. OrderStatus enum - Value 'PENDING' removed 5. Multiple endpoints - Field 'created_at' type changed: string → integer See full report: openapi-diff-report.md
## Usage Examples ### Detect REST API Regression
User: "Check API contract for breaking changes"
Skill executes:
- Locate OpenAPI spec files
- Load baseline (v1.5.0)
- Load current (v2.0.0)
- Run openapi-diff
- Classify changes
- Check semantic versioning
- Run Pact tests
Output: "API Compatibility Report
Status: BREAKING CHANGES DETECTED Breaking: 5 Non-Breaking: 12 Version: v1.5.0 → v2.0.0 (CORRECT major bump) Consumer Impact: 3 of 4 consumers affected
Critical Issues:
- Field removed: User.email (affects web-frontend, mobile-app)
- Endpoint removed: DELETE /api/v1/users/{id}
- Type change: created_at string → integer
See full report: .aiwg/api/compatibility/report-2026-01-28.md
Recommendation: Revert breaking changes or add compatibility layer"
### Detect GraphQL Schema Regression
User: "API breaking change check for GraphQL"
Skill executes:
- Locate GraphQL schema files
- Load baseline schema
- Load current schema
- Run graphql-inspector diff
- Identify breaking vs safe changes
Output: "GraphQL Schema Compatibility
Status: BREAKING CHANGES DETECTED Breaking: 2 Dangerous: 3 Safe: 8
Breaking Changes:
- Field 'User.email' removed
- Type 'Address' removed
Dangerous Changes:
- Field 'User.age' type changed: Int → String
- Argument 'Query.users(limit)' default changed: 10 → 100
- Enum 'Status' value 'ACTIVE' description changed
Recommendation: Review breaking changes before deployment"
### Consumer Contract Verification
User: "Run consumer contract tests"
Skill executes:
- Locate Pact contracts
- Run provider verification tests
- Generate compatibility matrix
Output: "Consumer Contract Verification
Status: INCOMPATIBLE CONSUMERS DETECTED Compatible: 1/4 Failing: 3/4
Results: ✅ partner-api (12/12 tests passing) ❌ web-frontend (38/45 passing, 7 failures) ❌ mobile-app (40/42 passing, 2 failures) ❌ admin-panel (15/18 passing, 3 failures)
Common Failures:
- Missing field: User.email (3 consumers)
- Endpoint not found: DELETE /api/v1/users/{id} (2 consumers)
Action Required: Update consumers or revert breaking changes"
## Integration This skill uses: - `regression-baseline`: Store API contract baselines - `regression-bisect`: Find commit that introduced breaking change - `regression-report`: Generate comprehensive regression report - `project-awareness`: Detect API framework (OpenAPI, GraphQL, gRPC) ## Agent Orchestration ```yaml agents: detection: agent: api-designer focus: Identify and classify API changes analysis: agent: architecture-designer focus: Assess impact and recommend migration testing: agent: test-engineer focus: Run consumer contract tests approval: agent: tech-lead focus: Approve breaking changes or require fixes
Configuration
Detection Settings
api_contract_detection: api_types: - rest_openapi - graphql - grpc_protobuf tools: rest: openapi-diff graphql: graphql-inspector grpc: buf baselines: storage: .aiwg/api/baselines/ naming: "{api-name}-{version}.{ext}" strict_mode: true # Fail on any breaking change semver_enforcement: true
Breaking Change Rules
breaking_rules: rest: - removed_endpoints - removed_fields - type_changes - new_required_fields - enum_value_removals - stricter_validations graphql: - removed_fields - removed_types - type_changes - non_nullable_additions - argument_removals grpc: - removed_services - removed_rpcs - removed_fields - type_changes - required_field_additions
Consumer Contract Testing
consumer_contracts: enabled: true framework: pact # or spring-cloud-contract pact: broker_url: https://pact-broker.example.com publish_verification: true contracts_location: .aiwg/api/contracts/ fail_on_incompatibility: true
Output Locations
- Baselines:
.aiwg/api/baselines/{api-name}-{version}.{yaml|graphql|proto} - Reports:
.aiwg/api/compatibility/report-{date}.md - Diffs:
.aiwg/api/compatibility/diff-{baseline}-to-{current}.md - Pact Results:
.aiwg/api/pact-results/ - Migration Guides:
.aiwg/api/migration/{version}/MIGRATION.md
References
- @$AIWG_ROOT/agentic/code/frameworks/sdlc-complete/schemas/testing/regression.yaml
- @$AIWG_ROOT/agentic/code/frameworks/sdlc-complete/agents/api-designer.md
- @$AIWG_ROOT/agentic/code/frameworks/sdlc-complete/skills/regression-baseline/SKILL.md
- @$AIWG_ROOT/agentic/code/frameworks/sdlc-complete/skills/regression-bisect/SKILL.md
- @.aiwg/research/findings/REF-013-metagpt.md
- @$AIWG_ROOT/agentic/code/frameworks/sdlc-complete/rules/executable-feedback.md