From lazy
Detects backward-incompatible changes to public APIs, function signatures, endpoints, and data schemas before they break production. Suggests migration paths.
npx claudepluginhub joshuarweaver/cascade-ai-ml-agents-misc-1 --plugin macroman5-claude-code-workflow-pluginsThis skill uses the workspace's default tool permissions.
**Purpose**: Catch breaking changes early, not after customers complain.
Guides Next.js Cache Components and Partial Prerendering (PPR) with cacheComponents enabled. Implements 'use cache', cacheLife(), cacheTag(), revalidateTag(), static/dynamic optimization, and cache debugging.
Guides building MCP servers enabling LLMs to interact with external services via tools. Covers best practices, TypeScript/Node (MCP SDK), Python (FastMCP).
Generates original PNG/PDF visual art via design philosophy manifestos for posters, graphics, and static designs on user request.
Purpose: Catch breaking changes early, not after customers complain.
Trigger Words: API, endpoint, route, public, schema, model, interface, contract, signature, rename, remove, delete
def is_breaking_change(change: dict) -> tuple[bool, str]:
"""Fast breaking change evaluation."""
breaking_patterns = {
# Method signatures
"removed_parameter": True,
"renamed_parameter": True,
"changed_parameter_type": True,
"removed_method": True,
"renamed_method": True,
# API endpoints
"removed_endpoint": True,
"renamed_endpoint": True,
"changed_response_format": True,
"removed_response_field": True,
# Data models
"removed_field": True,
"renamed_field": True,
"changed_field_type": True,
"made_required": True,
# Return types
"changed_return_type": True,
}
# Safe changes (backward compatible)
safe_patterns = {
"added_parameter_with_default": False,
"added_optional_field": False,
"added_endpoint": False,
"added_response_field": False,
"deprecated_but_kept": False,
}
change_type = change.get("type")
return breaking_patterns.get(change_type, False), change_type
# BEFORE (v1.0)
def process_payment(amount, currency, user_id):
pass
# AFTER (v2.0) - BREAKS EXISTING CODE
def process_payment(amount, user_id): # Removed currency!
pass
# ✅ FIX: Keep parameter with default
def process_payment(amount, user_id, currency="USD"):
"""
Args:
currency: Deprecated in v2.0, always uses USD
"""
pass
Migration Path: Add default value, deprecate, document.
# BEFORE
def getUserProfile(user_id):
pass
# AFTER - BREAKS CALLS
def get_user_profile(user_id): # Renamed!
pass
# ✅ FIX: Keep both, deprecate old
def get_user_profile(user_id):
"""Get user profile (v2.0+ naming)."""
pass
def getUserProfile(user_id):
"""Deprecated: Use get_user_profile() instead."""
warnings.warn("getUserProfile is deprecated, use get_user_profile", DeprecationWarning)
return get_user_profile(user_id)
Migration Path: Alias old name → new name, add deprecation warning.
# BEFORE - Returns dict
@app.route("/api/user/<id>")
def get_user(id):
return {"id": id, "name": "Alice", "email": "alice@example.com"}
# AFTER - Returns list - BREAKS CLIENTS!
@app.route("/api/user/<id>")
def get_user(id):
return [{"id": id, "name": "Alice", "email": "alice@example.com"}]
# ✅ FIX: Keep format, add new endpoint
@app.route("/api/v2/user/<id>") # New version
def get_user_v2(id):
return [{"id": id, "name": "Alice"}]
@app.route("/api/user/<id>") # Keep v1
def get_user(id):
return {"id": id, "name": "Alice", "email": "alice@example.com"}
Migration Path: Version the API (v1, v2), keep old version alive.
# BEFORE
@app.route("/users")
def get_users():
pass
# AFTER - REMOVED! Breaks clients.
# (endpoint deleted)
# ✅ FIX: Redirect to new endpoint
@app.route("/users")
def get_users():
"""Deprecated: Use /api/v2/accounts instead."""
return redirect("/api/v2/accounts", code=301) # Permanent redirect
Migration Path: Keep endpoint, redirect with 301, document deprecation.
# BEFORE - email optional
class User:
def __init__(self, name, email=None):
self.name = name
self.email = email
# AFTER - email required! Breaks existing code.
class User:
def __init__(self, name, email): # No default!
self.name = name
self.email = email
# ✅ FIX: Keep optional, validate separately
class User:
def __init__(self, name, email=None):
self.name = name
self.email = email
def validate(self):
"""Validate required fields."""
if not self.email:
raise ValueError("Email is required (new in v2.0)")
Migration Path: Keep optional in constructor, add validation method.
# BEFORE
{
"id": 123,
"name": "Alice",
"age": 30,
"email": "alice@example.com"
}
# AFTER - Removed age! Breaks clients expecting it.
{
"id": 123,
"name": "Alice",
"email": "alice@example.com"
}
# ✅ FIX: Keep field with null/default
{
"id": 123,
"name": "Alice",
"age": null, # Deprecated, always null in v2.0
"email": "alice@example.com"
}
Migration Path: Keep field with null, document deprecation.
# BEFORE
def process_payment(amount):
pass
# AFTER - Safe! Has default
def process_payment(amount, currency="USD"):
pass
# Old calls still work:
process_payment(100) # ✅ Works
# BEFORE
{"id": 123, "name": "Alice"}
# AFTER - Safe! Added field
{"id": 123, "name": "Alice", "created_at": "2025-10-30"}
# Old clients ignore new field: ✅ Works
# New endpoint added
@app.route("/api/v2/users")
def get_users_v2():
pass
# Old endpoint unchanged: ✅ Safe
## Breaking Change Report
**Status**: [✅ NO BREAKING CHANGES | ⚠️ BREAKING CHANGES DETECTED]
---
### Breaking Changes: 2
1. **[CRITICAL] Removed endpoint: GET /users**
- **Impact**: External API clients will get 404
- **File**: api/routes.py:45
- **Fix**:
```python
# Keep endpoint, redirect to new one
@app.route("/users")
def get_users():
return redirect("/api/v2/accounts", code=301)
```
- **Migration**: Add to CHANGELOG.md, notify users
2. **[HIGH] Renamed parameter: currency → currency_code**
- **Impact**: Existing function calls will fail
- **File**: payments.py:23
- **Fix**:
```python
# Accept both, deprecate old name
def process_payment(amount, currency_code=None, currency=None):
# Support old name temporarily
if currency is not None:
warnings.warn("currency is deprecated, use currency_code")
currency_code = currency
```
---
### Safe Changes: 1
1. **[SAFE] Added optional parameter: timeout (default=30)**
- **File**: api_client.py:12
- **Impact**: None, backward compatible
---
**Recommendation**:
1. Fix 2 breaking changes before merge
2. Document breaking changes in CHANGELOG.md
3. Bump major version (v1.x → v2.0) per semver
4. Notify API consumers 2 weeks before release
# Automatic trigger when modifying APIs
/lazy code "rename /users endpoint to /accounts"
→ breaking-change-detector triggers
→ Detects: Endpoint rename is breaking
→ Suggests: Keep /users, redirect to /accounts
→ Developer applies fix
→ Re-check: ✅ Backward compatible
# Before PR
/lazy review US-3.4
→ breaking-change-detector runs
→ Checks all API changes in PR
→ Reports breaking changes
→ PR blocked if breaking without migration plan
# Semantic versioning
Given version: MAJOR.MINOR.PATCH
# Breaking change detected → Bump MAJOR
1.2.3 → 2.0.0
# New feature (backward compatible) → Bump MINOR
1.2.3 → 1.3.0
# Bug fix (backward compatible) → Bump PATCH
1.2.3 → 1.2.4
❌ Catch internal/private API changes (only public APIs) ❌ Test runtime compatibility (use integration tests) ❌ Manage database migrations (separate tool) ❌ Generate full migration scripts
✅ DOES: Detect public API breaking changes, suggest fixes, enforce versioning.
# Strict mode: flag all changes (even safe ones)
export LAZYDEV_BREAKING_STRICT=1
# Disable breaking change detection
export LAZYDEV_DISABLE_BREAKING_DETECTOR=1
# Check only specific types
export LAZYDEV_BREAKING_CHECK="endpoints,schemas"
Version: 1.0.0 Follows: Semantic Versioning 2.0.0 Speed: <3 seconds for typical PR