Skip to main content

Patch Engine

The patch engine safely applies AI-generated changes to .msh files using JSON Patch format.

Purpose

The patch engine provides:

  • Safe application: Validates patches before applying
  • Atomic operations: Changes are applied atomically
  • Dry-run mode: Preview changes before applying
  • Error handling: Clear error messages for failures

Patch Format

Patches use JSON Patch (RFC 6902) format:

{
"patches": [{
"file_path": "assets/revenue.msh",
"diff": "unified diff string",
"operations": [
{
"op": "replace",
"path": "/transform",
"value": "SELECT customerId as customer_id, ..."
},
{
"op": "add",
"path": "/tests",
"value": [
{"assert": "monthly_revenue > 0"}
]
}
]
}]
}

Operations

Add

Add value at path:

{
"op": "add",
"path": "/tests",
"value": [
{"assert": "monthly_revenue > 0"}
]
}

Remove

Remove value at path:

{
"op": "remove",
"path": "/tests/0"
}

Replace

Replace value at path:

{
"op": "replace",
"path": "/transform",
"value": "SELECT customerId as customer_id, ..."
}

Generating Patches

Patches are generated by AI commands:

# Generate patch from fix command
msh ai fix assets/revenue.msh --json > patch.json

# Generate patch from tests command
msh ai tests assets/revenue.msh --json > patch.json

Applying Patches

Preview Changes

Preview changes before applying:

msh ai apply patch.json --dry-run

Output:

Previewing patch: patch.json

Files to modify:
- assets/revenue.msh

Changes:
--- assets/revenue.msh
+++ assets/revenue.msh
@@ -10,7 +10,7 @@
transform: |
SELECT
- customer_id,
+ customerId as customer_id,
DATE_TRUNC('month', order_date) as month,
SUM(amount) as monthly_revenue
FROM {{ source }}
+ WHERE order_date >= CURRENT_DATE - INTERVAL '1 year'
GROUP BY customer_id, DATE_TRUNC('month', order_date)

No files modified (dry-run mode)

Apply Patch

Apply patch to files:

msh ai apply patch.json

Output:

Applying patch: patch.json

✓ assets/revenue.msh - Applied successfully

Patch applied to 1 file(s)

Safety Validation

The patch engine validates patches before applying:

1. Syntax Validation

Validates JSON Patch format:

{
"patches": [{
"file_path": "assets/revenue.msh",
"operations": [
{"op": "replace", "path": "/transform", "value": "..."}
]
}]
}

2. Safety Check

Uses safety layer to block dangerous operations:

{
"operations": [
{"op": "replace", "path": "/transform", "value": "DROP TABLE customers"}
]
}

Result:

✗ assets/revenue.msh - Blocked: Contains dangerous operation 'DROP TABLE'

3. File Validation

Validates file exists and is writable:

✗ assets/revenue.msh - Failed: File not found

Error Handling

File Not Found

✗ assets/revenue.msh - Failed: File not found

Fix: Check file path in patch.

Invalid Patch

✗ Patch validation failed: Invalid JSON Patch format

Fix: Check patch format matches JSON Patch (RFC 6902).

Safety Violation

✗ assets/revenue.msh - Blocked: Contains dangerous operation 'DROP TABLE'

Fix: Review patch and remove dangerous operations.

Syntax Error

✗ assets/revenue.msh - Failed: SQL syntax error

Fix: Review generated SQL and fix syntax errors.

Workflow

1. Generate Patch

# Generate patch
msh ai fix assets/revenue.msh --json > patch.json

2. Preview Changes

# Preview changes
msh ai apply patch.json --dry-run

3. Review Changes

Review the diff and ensure changes are correct.

4. Apply Patch

# Apply patch
msh ai apply patch.json

5. Verify Changes

# Test changes
msh run revenue

Best Practices

Always Preview First

Always use --dry-run before applying:

msh ai apply patch.json --dry-run

Review Generated Patches

Review patch JSON before applying:

cat patch.json | jq '.'

Test After Applying

Test changes after applying:

msh run revenue

Version Control

Commit patches for review:

git add patch.json
git commit -m "AI-generated patch for revenue asset"