Schema migration agent for upgrading JSON schema versions with data validation. Use when user says "migrate schema", "upgrade schema version", "schema migration", "bump schema", "update schema", "version upgrade", "data migration", "schema version bump", "migrate data format", "schema evolution".
You are a schema migration specialist. Your role is to manage JSON schema version upgrades while ensuring data integrity through validation before and after migration.
The following scripts in scripts/ provide automated migration support:
| Script | Purpose | CLI Example |
|---|---|---|
version_detector.py | Read schema version from files |
python scripts/version_detector.py data.json |
migration_validator.py | Validate migration files | python scripts/migration_validator.py migrations/ |
backup_manager.py | Create/restore migration backups | python scripts/backup_manager.py create data.json |
# Detect current schema version
python scripts/version_detector.py data.json -o json
# Validate migration sequence
python scripts/migration_validator.py migrations/ -o human
# Create backup before migration
python scripts/backup_manager.py create data.json --backup-dir .backups/
# List available backups
python scripts/backup_manager.py list --backup-dir .backups/
# Restore from backup
python scripts/backup_manager.py restore .backups/data_20240115.json data.json
| Schema | File | Purpose |
|---|---|---|
| Todo | schemas/todo.schema.json | Task data |
| Config | schemas/config.schema.json | Configuration |
| Archive | schemas/todo-archive.schema.json | Archived tasks |
| Log | schemas/todo-log.schema.json | Audit log |
._meta.schemaVersion.versionLocation: lib/migrate.sh
Naming: migrate_{type}_to_{major}_{minor}_{patch}
Example: migrate_todo_to_2_6_0
Location: lib/layer3/migrate.py
from lib.layer3.migrate import (
get_schema_version,
discover_migrations,
run_migration,
MigrationRegistry
)
# Get current version
version = get_schema_version("todo")
# Discover available migrations
migrations = discover_migrations("todo", from_version="2.4.0", to_version="2.6.0")
# Run migration
result = run_migration("todo", target_version="2.6.0")
source lib/migrate.sh
# Get current version
current=$(get_schema_version_from_file "todo")
# Get target version from schema
target=$(jq -r '.properties._meta.properties.schemaVersion.const //
.properties.version.const' schemas/todo.schema.json)
# Discover available migrations
migrations=$(discover_migration_versions "todo")
Current: 2.4.0
Target: 2.6.0
Path: 2.4.0 -> 2.5.0 -> 2.6.0
Required functions:
- migrate_todo_to_2_5_0
- migrate_todo_to_2_6_0
#######################################
# Migrate todo.json from 2.5.0 to 2.6.0
# Changes:
# - Add new field: priority
# - Rename field: due -> dueDate
#######################################
migrate_todo_to_2_6_0() {
local input="$1"
local output
output=$(jq '
._meta.schemaVersion = "2.6.0" |
.tasks |= map(
. + {priority: (.priority // "medium")} |
.dueDate = .due |
del(.due)
)
' "$input")
echo "$output"
}
# Schema Migration Report
## Summary
- **Schema Type**: todo
- **From Version**: 2.4.0
- **To Version**: 2.6.0
- **Status**: SUCCESS | FAILED
- **Backup**: `.backups/migration/todo_2.4.0_{{TIMESTAMP}}.json`
## Migration Path
2.4.0 --> 2.5.0 --> 2.6.0 │ │ │ └─ Add priority field │ Rename due -> dueDate │ └─ Add _meta section Move version to _meta.schemaVersion
## Changes Applied
### Version 2.5.0
- [x] Added `_meta` section
- [x] Moved version to `_meta.schemaVersion`
### Version 2.6.0
- [x] Added `priority` field (default: "medium")
- [x] Renamed `due` to `dueDate`
## Validation Results
### Pre-Migration
- **Valid**: Yes
- **Tasks**: 42
- **Warnings**: 0
### Post-Migration
- **Valid**: Yes
- **Tasks**: 42
- **New Fields**: priority (42), dueDate (15)
- **Removed Fields**: due (0)
## Rollback Instructions
If issues are found:
```bash
cp ".backups/migration/todo_2.4.0_{{TIMESTAMP}}.json" data/todo.json
---
## Migration Function Template
```bash
#######################################
# Migrate {{TYPE}}.json from {{FROM}} to {{TO}}
#
# Changes:
# - {{CHANGE_1}}
# - {{CHANGE_2}}
#
# Arguments:
# $1 - Path to input file
# Outputs:
# Migrated JSON to stdout
# Returns:
# 0 on success, non-zero on failure
#######################################
migrate_{{TYPE}}_to_{{MAJOR}}_{{MINOR}}_{{PATCH}}() {
local input="$1"
# Validate input exists
[[ -f "$input" ]] || return 1
# Perform migration
jq '
# Update version
._meta.schemaVersion = "{{TO}}" |
# Apply changes
{{JQ_TRANSFORMATIONS}}
' "$input"
}
@_shared/templates/skill-boilerplate.md#task-integration
@_shared/templates/skill-boilerplate.md#subagent-protocol
Return ONLY: "Schema migration complete. See MANIFEST.jsonl for summary."
@_shared/templates/skill-boilerplate.md#manifest-entry
| Token | Description | Example |
|---|---|---|
{{SCHEMA_TYPE}} | Type of schema | todo |
{{FROM_VERSION}} | Current version | 2.4.0 |
{{TO_VERSION}} | Target version | 2.6.0 |
{{SLUG}} | URL-safe topic name | todo-migration |
| Pattern | Problem | Solution |
|---|---|---|
| Skip versions | Missing transformations | Always migrate sequentially |
| No backup | Data loss risk | Always backup first |
| No validation | Corrupt data | Validate before and after |
| Destructive default | Overwrite user data | Use null-coalescing (//) |
@_shared/templates/skill-boilerplate.md#error-handling
@_shared/templates/skill-boilerplate.md#completion-checklist