Detect and warn about breaking API/schema changes before implementation. Auto-trigger when modifying API routes, database schemas, or public interfaces. Validates changes against api-strategy.md versioning rules. Suggests migration paths for breaking changes. Prevents removing endpoints, changing request/response formats, dropping database columns, modifying function signatures without deprecation.
Breaking changes destroy trust and break client applications:
This skill acts as a safety gate that:
The result: Zero unintentional breaking changes, smooth API evolution, maintained client trust. </objective>
<quick_start> <trigger_pattern> Auto-trigger when detecting these modification patterns:
API modifications:
Database modifications:
Interface modifications:
<basic_workflow> Step 1: Detect modification type
Step 2: Analyze breaking change risk
Step 3: Determine severity
Step 4: Suggest safe migration path
Step 5: Validate against api-strategy.md
Step 6: Block or warn
<immediate_value> Without breaking-change-detector:
Developer: "Let me remove this old /api/users endpoint"
*Removes endpoint*
*Deploys*
Result: 15 mobile apps break, support tickets flood in, emergency rollback
With breaking-change-detector:
Developer: "Let me remove this old /api/users endpoint"
Detector: "🚨 BREAKING CHANGE DETECTED
Removing: GET /api/users
Severity: CRITICAL
Impact: 15 active clients (iOS app, Android app, web dashboard)
This will break:
- Mobile app v2.1-2.5 (500K users)
- Partner integrations (3 companies)
Safe migration path:
1. Deprecate endpoint (add X-Deprecated header)
2. Announce removal timeline (90 days)
3. Monitor usage (track who's still calling it)
4. Version API (v2 without endpoint, v1 keeps it)
5. Remove after 90 days when usage drops to 0
Cannot proceed without migration plan. Would you like me to implement the deprecation strategy?"
Developer: "Yes, let's deprecate it properly"
Result: Smooth transition, zero broken clients, maintained trust
</immediate_value> </quick_start>
<workflow> <step number="1"> **Detect modification intent**Parse user request to identify change type:
API endpoint changes:
Database schema changes:
Interface/contract changes:
See references/change-detection-patterns.md for complete patterns. </step>
<step number="2"> **Classify breaking change type**Categorize the detected change:
Type 1: Hard breaking changes (always break clients):
Type 2: Soft breaking changes (may break some clients):
Type 3: Non-breaking changes (safe):
See references/breaking-change-taxonomy.md for full classification. </step>
<step number="3"> **Assess impact scope**Determine who/what will be affected:
For API changes:
Find endpoint usage:
Estimate client count:
Determine criticality:
For database changes:
Find column usage:
Assess data impact:
For interface changes:
Find function usage:
Determine coupling:
Assign severity based on impact:
CRITICAL (blocks deployment):
HIGH (requires approval):
MEDIUM (requires documentation):
LOW (informational):
Read project's API versioning policy from docs/project/api-strategy.md:
Common strategies:
URL versioning: /api/v1/users, /api/v2/users
Header versioning: Accept: application/vnd.app.v1+json
No versioning (deprecation only):
Example api-strategy.md:
# API Versioning Strategy
**Strategy**: URL versioning (/api/v1, /api/v2)
**Breaking change policy**:
- Major version bump required (v1 → v2)
- Old version supported for 6 months minimum
- Deprecation notice 90 days before removal
- Monitor usage, remove when <1% traffic
**Backward compatibility requirements**:
- New fields are optional
- Removed fields are deprecated first (90 days)
- Response format changes require new version
If api-strategy.md doesn't exist, use conservative defaults:
Provide options based on change type and versioning strategy:
For endpoint removal:
Option A: Deprecation strategy
1. Add X-Deprecated header to endpoint
2. Add warning to API docs
3. Email clients (if known)
4. Monitor usage for 90 days
5. Remove when usage drops to 0
Option B: API versioning
1. Keep endpoint in /api/v1
2. Remove from /api/v2
3. Redirect v1 → v2 replacement (if exists)
4. Sunset v1 after 6 months
Option C: Soft delete
1. Return 410 Gone instead of 404
2. Include migration instructions in response
3. Log attempts for monitoring
For schema changes:
Option A: Additive migration
1. Add new column (don't drop old)
2. Dual-write to both columns
3. Migrate existing data
4. Update code to use new column
5. Drop old column in future version
Option B: Versioned schema
1. Create new table (users_v2)
2. Dual-write to both tables
3. Migrate readers to new table
4. Drop old table after migration
Option C: Nullable transition
1. Make column nullable (don't drop)
2. Update code to handle null
3. Backfill default values
4. Make required again if needed
For interface changes:
Option A: Deprecate + replace
1. Mark function as @deprecated
2. Create new function with new signature
3. Update call sites gradually
4. Remove deprecated function in major version
Option B: Overload
1. Add new overload with new signature
2. Keep old overload functional
3. Route to implementation
4. Remove old overload later
Option C: Default parameters
1. Add new parameters with defaults
2. Backward compatible (old calls still work)
3. No breaking change
See references/migration-strategies.md for complete playbook. </step>
<step number="7"> **Block or warn**Based on severity, take action:
CRITICAL → BLOCK:
🚨 BREAKING CHANGE BLOCKED
Cannot proceed with this change without migration plan.
Change: Remove GET /api/users
Severity: CRITICAL
Impact: 500K users (mobile app), 3 partner integrations
Required before proceeding:
[ ] Migration plan documented
[ ] Stakeholders notified
[ ] Deprecation timeline agreed
[ ] Monitoring in place
[ ] Rollback plan ready
Would you like me to implement the recommended deprecation strategy?
HIGH → WARN:
⚠️ BREAKING CHANGE DETECTED
This change will break existing clients.
Change: Add required field "country" to POST /api/users
Severity: HIGH
Impact: Web app, mobile apps will fail validation
Recommended migration:
1. Make field optional initially
2. Update all clients to send field
3. Make field required in v2.0
Proceed anyway? [y/N]
MEDIUM → LOG:
ℹ️ Breaking change detected (MEDIUM severity)
Change: Change validation error format
Impact: Clients parsing error messages
Document this change in:
- CHANGELOG.md
- API migration guide
- Release notes
Proceeding with implementation...
</step>
</workflow>
<detection_rules> <api_endpoint_changes> Removal detection:
// Grep patterns
"router\\.delete.*'[^']*'" → Endpoint removal
"app\\..*\\.delete" → Express route removal
"// TODO: remove|// deprecated" → Marked for removal
// File deletions
routes/*.ts deleted → Endpoint removal
controllers/*.ts deleted → Controller removal
Modification detection:
// Request schema changes
"interface.*Request.*{" (before/after diff)
"@Body.*:" (parameter changes)
"validate.*schema" (validation changes)
// Response schema changes
"interface.*Response.*{" (before/after diff)
"res.json({" (response format changes)
// HTTP method changes
"router.get" → "router.post" (method change)
Examples:
// BREAKING: Endpoint removal
- router.get('/api/users/:id', ...) // Removed
// Severity: CRITICAL
// BREAKING: Required field added
interface CreateUserRequest {
name: string;
email: string;
+ country: string; // NEW REQUIRED FIELD
}
// Severity: HIGH
// BREAKING: Response field removed
interface UserResponse {
id: string;
name: string;
- email: string; // REMOVED
}
// Severity: HIGH
</api_endpoint_changes>
<database_schema_changes> Column removal detection:
-- Prisma schema
- email String // Removed
// Severity: CRITICAL (data loss)
-- SQL migration
ALTER TABLE users DROP COLUMN email;
// Severity: CRITICAL (data loss)
Type changes:
-- Changing column type
ALTER TABLE users ALTER COLUMN age TYPE varchar; // was integer
// Severity: HIGH (data conversion required)
Constraint changes:
-- Adding NOT NULL to existing column
ALTER TABLE users ALTER COLUMN email SET NOT NULL;
// Severity: HIGH (existing nulls will fail)
-- Removing constraint
ALTER TABLE users DROP CONSTRAINT users_email_unique;
// Severity: MEDIUM (behavior change)
Table changes:
DROP TABLE users;
// Severity: CRITICAL (data loss + code breaks)
ALTER TABLE users RENAME TO customers;
// Severity: CRITICAL (all queries break)
</database_schema_changes>
<interface_changes> Function signature changes:
// Parameter removal
- function getUser(id: string, includeDeleted: boolean)
+ function getUser(id: string)
// Severity: HIGH (callers passing 2 params break)
// Parameter type change
- function processOrder(id: string)
+ function processOrder(id: number)
// Severity: HIGH (type mismatch)
// Return type change
- function getUsers(): User[]
+ function getUsers(): Promise<User[]> // Now async
// Severity: CRITICAL (breaks all callers)
Method removal:
class UserService {
- async deleteUser(id: string) { } // Removed
}
// Severity: HIGH (callers break)
Required property addition:
interface Config {
apiKey: string;
+ environment: string; // NEW REQUIRED
}
// Severity: HIGH (existing configs invalid)
</interface_changes>
<authentication_changes> Auth scheme changes:
// Changing auth method
- @UseGuards(JwtAuthGuard) // Was JWT
+ @UseGuards(OAuth2Guard) // Now OAuth2
// Severity: CRITICAL (clients locked out)
// Adding auth to public endpoint
- router.get('/api/public')
+ router.get('/api/public', authMiddleware)
// Severity: CRITICAL (public → authenticated)
Permission changes:
// Changing required role
- @RequireRole('user')
+ @RequireRole('admin')
// Severity: HIGH (users lose access)
</authentication_changes> </detection_rules>
<auto_trigger_conditions> <when_to_trigger> File modification triggers:
**/routes/**/*.ts → Check for endpoint changes**/schema/*.prisma → Check for schema changes**/*.migration.sql → Check for database changes**/interfaces/**/*.ts → Check for contract changes**/controllers/**/*.ts → Check for API changesCode pattern triggers:
User intent triggers:
<when_not_to_trigger> Safe changes (don't trigger):
Explicitly marked safe:
**/internal/** (not public API)// SAFE: backward compatible<proactive_detection> Before modification: When user says "Remove GET /api/users":
During code review: Before creating PR/commit:
Detection:
Change type: API endpoint removal
File: routes/stats.ts
Line: router.get('/api/v1/stats', ...)
Action: DELETE
Impact analysis:
# Search for endpoint usage
grep -r "/api/v1/stats" --include="*.ts" --include="*.js"
Found:
- Frontend: src/services/api.ts (1 call)
- Mobile app: Documented in integration guide
- API logs: 450 requests/day
Clients:
- Web dashboard (internal, can update)
- Mobile app v2.3 (external, 10K users)
- Unknown clients (logged as "curl/7.0", "Python requests")
Severity determination:
Traffic: 450 requests/day → Moderate usage
Clients: External mobile app → Cannot force update
Unknown clients: Present → Unpredictable impact
Severity: CRITICAL
Reason: External clients depend on endpoint
Migration suggestion:
🚨 BREAKING CHANGE BLOCKED
Cannot remove /api/v1/stats - active external usage detected.
Impact:
- Mobile app v2.3 (10K users)
- Unknown clients (curl, Python scripts)
- 450 requests/day
Safe migration path (RECOMMENDED):
Phase 1: Deprecation (Days 0-90)
1. Add response header: X-Deprecated: "true; sunset=2025-03-01; replacement=/api/v2/analytics"
2. Add deprecation notice to API docs
3. Email known clients (mobile team)
4. Log warnings when endpoint called
Phase 2: Monitoring (Days 0-90)
1. Track usage metrics
2. Identify remaining clients (log User-Agent)
3. Reach out to high-volume clients
Phase 3: Removal (Day 90+)
1. Wait until usage < 10 requests/day
2. Return 410 Gone with migration instructions
3. Monitor for spikes (indicates missed client)
4. Remove code after 30 days at 410
Estimated timeline: 4 months
Would you like me to implement Phase 1 (deprecation)?
Implementation (if approved):
// routes/stats.ts (DEPRECATE, don't remove)
router.get('/api/v1/stats',
deprecationMiddleware({
sunset: '2025-03-01',
replacement: '/api/v2/analytics',
message: 'This endpoint is deprecated and will be removed on 2025-03-01'
}),
statsController.getStats // Keep working
);
// middleware/deprecation.ts (NEW)
export function deprecationMiddleware(options: DeprecationOptions) {
return (req, res, next) => {
res.header('X-Deprecated', 'true');
res.header('Sunset', options.sunset);
res.header('Link', `<${options.replacement}>; rel="successor-version"`);
logger.warn('Deprecated endpoint called', {
endpoint: req.path,
client: req.get('User-Agent'),
ip: req.ip,
sunset: options.sunset
});
next();
};
}
See examples/api-endpoint-removal-full.md for complete example. </example>
<example name="database-schema-change"> **Request**: "Drop the 'phone' column from users table, we're using email only now"Detection:
Change type: Database column removal
Table: users
Column: phone
Action: DROP COLUMN
Impact analysis:
# Search for column usage
grep -r "\.phone\|phone:" --include="*.ts"
Found:
- models/User.ts: phone: string
- services/UserService.ts: user.phone (3 references)
- controllers/UserController.ts: req.body.phone (1 reference)
- Database: 15,000 users have phone numbers (non-null)
Data at risk: 15,000 phone numbers
Code impact: 5 files, 10 references
Severity determination:
Data loss: 15,000 records → CRITICAL
Code breakage: 5 files → HIGH
Rollback difficulty: Cannot recover deleted data → CRITICAL
Severity: CRITICAL
Reason: Irreversible data loss
Migration suggestion:
🚨 BREAKING CHANGE BLOCKED
Cannot drop users.phone column - data loss risk.
Impact:
- 15,000 users have phone numbers (data loss)
- 5 files reference phone column (code breaks)
- No backup of phone data
Safe migration path (RECOMMENDED):
Option A: Soft delete (SAFEST)
1. Rename column: phone → phone_deprecated
2. Make column nullable
3. Update code to not use phone
4. Keep data for 6 months
5. Drop column after verification period
Option B: Archive before delete
1. Export phone data to archive table
2. Create users_phone_archive(user_id, phone, archived_at)
3. Copy data: INSERT INTO users_phone_archive SELECT id, phone FROM users
4. Verify archive: Check row counts match
5. Drop column from users table
6. Keep archive table indefinitely
Option C: Make nullable (don't drop)
1. ALTER TABLE users ALTER COLUMN phone DROP NOT NULL
2. Update code to handle null
3. Set existing phones to null (or keep them)
4. Column exists but unused (no data loss)
Which option do you prefer? I recommend Option B (archive).
See examples/database-column-removal.md for complete example. </example>
<example name="function-signature-change"> **Request**: "Change getUserById to return Promise<User | null> instead of Promise<User>"Detection:
Change type: Function signature modification
Function: getUserById
Return type change: Promise<User> → Promise<User | null>
Impact analysis:
// Search for function calls
grep -r "getUserById" --include="*.ts"
Found 23 call sites:
- controllers/UserController.ts (3 calls)
- services/OrderService.ts (5 calls)
- services/NotificationService.ts (2 calls)
- ... (13 more files)
None handle null return:
const user = await getUserById(id);
user.name // Will throw if null
Severity determination:
Call sites: 23 locations
Null handling: 0/23 handle null
Impact: Runtime errors (Cannot read 'name' of null)
Severity: HIGH
Reason: Breaks existing code with runtime errors
Migration suggestion:
⚠️ BREAKING CHANGE DETECTED
Changing getUserById return type to nullable breaks 23 call sites.
Current: Promise<User> (never null)
Proposed: Promise<User | null> (can be null)
Impact:
- 23 call sites assume non-null
- Will throw "Cannot read property of null" at runtime
- Requires updating all callers
Safe migration path:
Option A: Deprecate + replace (RECOMMENDED)
1. Keep getUserById as-is (throws if not found)
2. Create findUserById that returns User | null
3. Update callers gradually to findUserById
4. Mark getUserById as @deprecated
5. Remove getUserById in v2.0
Option B: Update all callers first
1. Find all 23 call sites
2. Add null checks: if (!user) throw new NotFoundError()
3. Then change return type
4. Runtime-safe, but large changeset
Option C: Overload (TypeScript only)
1. Add overload: getUserById(id, options: { throwIfNotFound: false }): Promise<User | null>
2. Keep default: getUserById(id): Promise<User>
3. Backward compatible
Recommended: Option A (new function)
**Implementation
<!-- Content truncated for initial SEO render. Open the source file tab for the full file. -->npx skills add marcusgoll/breaking-change-detector下载完整 Skill 目录,包含 SKILL.md 及所有相关文件
Search for places (restaurants, cafes, etc.) via Google Places API proxy on localhost.
Interact with GitHub using the `gh` CLI. Use `gh issue`, `gh pr`, `gh run`, and `gh api` for issues, PRs, CI runs, and advanced queries.
Create or update AgentSkills. Use when designing, structuring, or packaging skills with scripts, references, and assets.
Start voice calls via the OpenClaw voice-call plugin.
Notion API for creating and managing pages, databases, and blocks.
Gemini CLI for one-shot Q&A, summaries, and generation.
Category:developer