Detect breaking changes in API contracts across REST, GraphQL, and gRPC interfaces.
Detects breaking changes in REST, GraphQL, and gRPC API contracts.
/plugin marketplace add jmagly/aiwg/plugin install sdlc@aiwgThis skill inherits all available tools. When active, it can use any tool Claude has access to.
Detect breaking changes in API contracts across REST, GraphQL, and gRPC interfaces.
This skill detects API contract regressions by:
When triggered, this skill:
Identifies API contract scope:
Compares contracts to baseline:
Classifies changes by severity:
Validates semantic versioning:
Runs consumer contract tests:
Generates compatibility report:
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_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_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"
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_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
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
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
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:
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
**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
password_policy field optional with default valuecreated_at_unix alongside created_at stringemail field - deprecate with timeline insteadPENDING → AWAITING_CONFIRMATION enum mapping// 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`);
// 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',
};
$ 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:
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:
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:
Output: "GraphQL Schema Compatibility
Status: BREAKING CHANGES DETECTED Breaking: 2 Dangerous: 3 Safe: 8
Breaking Changes:
Dangerous Changes:
Recommendation: Review breaking changes before deployment"
### Consumer Contract Verification
User: "Run consumer contract tests"
Skill executes:
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:
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
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_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_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
.aiwg/api/baselines/{api-name}-{version}.{yaml|graphql|proto}.aiwg/api/compatibility/report-{date}.md.aiwg/api/compatibility/diff-{baseline}-to-{current}.md.aiwg/api/pact-results/.aiwg/api/migration/{version}/MIGRATION.mdActivates when the user asks about AI prompts, needs prompt templates, wants to search for prompts, or mentions prompts.chat. Use for discovering, retrieving, and improving prompts.
Search, retrieve, and install Agent Skills from the prompts.chat registry using MCP tools. Use when the user asks to find skills, browse skill catalogs, install a skill for Claude, or extend Claude's capabilities with reusable AI agent components.
Creating algorithmic art using p5.js with seeded randomness and interactive parameter exploration. Use this when users request creating art using code, generative art, algorithmic art, flow fields, or particle systems. Create original algorithmic art rather than copying existing artists' work to avoid copyright violations.