Skip to content

Migration Rules Reference

YAML rule schema, 150+ built-in rules, transform types, and custom rule authoring.

10 min read

Ovvoc uses YAML migration rules to define deterministic code transformations for dependency updates. The rule database contains 150+ rules across 29 npm packages, covering all 25 update categories.

Rule file schema

Each YAML file targets a specific package and version range. Here's an annotated example for Express 4→5:

rules/express/express-4-to-5.yaml
# Package identifier (npm package name)
package: "express"

# Version range this rule file covers
from_version: "4.x"
to_version: "5.x"

# Ordered list of migration rules
rules:
  # Rule 1: Rename app.del() to app.delete()
  - type: function_rename
    from: "del"
    to: "delete"
    object: "app"               # Only match calls on Express app
    file_pattern: "**/*.{js,ts}"
    confidence: 1.0             # Fully deterministic
    priority: 1                 # Run first

  # Rule 2: Update wildcard route syntax
  - type: syntax_change
    pattern: "app.get('*'"
    replacement: "app.get('{*path}'"
    file_pattern: "**/*.{js,ts}"
    confidence: 1.0
    priority: 2

  # Rule 3: Handle removed Connect middleware
  - type: ai_assisted
    description: "Remove built-in Connect middleware"
    prompt_category: "removed_feature"
    budget_tokens: 2000
    confidence: 0.85
    priority: 10                # Run after deterministic rules

Rule types

ast_transform

The primary rule type. Uses the OXC AST parser to apply syntax-tree-level transformations. There are 11 subtypes:

SubtypeDescription
function_renameRename a function or method call
import_path_changeChange import/require paths
param_signature_changeModify function call parameters
default_to_named_exportConvert default to named import
named_export_renameRename a named import/export
deprecated_api_replacementReplace deprecated API calls
config_key_renameRename keys in config objects
syntax_changeGrammar/syntax pattern replacement
async_api_changeSync to async API migration
type_system_changeTypeScript type annotation updates
middleware_api_changePlugin/middleware signature changes
ast_transform example
- type: function_rename
  from: "render"
  to: "createRoot"
  module: "react-dom"
  file_pattern: "**/*.{jsx,tsx}"
  confidence: 1.0
  priority: 1

ast_grep_pattern

Regex-based pattern matching with replacement. Used for patterns that are too simple for full AST analysis:

ast_grep_pattern example
- type: ast_grep_pattern
  pattern: "require\('express'\)\.Router\(\)"
  replacement: "require('express').Router()"
  file_pattern: "**/*.js"
  confidence: 0.9
  priority: 5

config_change

Modify JSON, YAML, or TOML configuration files:

config_change example
- type: config_change
  file: "tsconfig.json"
  operations:
    - set: "compilerOptions.moduleResolution"
      value: "bundler"
    - delete: "compilerOptions.typeRoots"
  confidence: 0.95
  priority: 3

file_edit

Line-level insertion, deletion, or replacement for non-code files:

file_edit example
- type: file_edit
  file: ".npmrc"
  operations:
    - insert_after: "registry="
      line: "engine-strict=true"
  confidence: 1.0
  priority: 8

ai_assisted

Budget-controlled AI generation with validation. Used when deterministic rules can't solve the transformation:

ai_assisted example
- type: ai_assisted
  description: "Migrate class component to hooks"
  prompt_category: "paradigm_shift"
  budget_tokens: 4000
  validation:
    - must_compile: true
    - must_preserve_exports: true
  confidence: 0.7
  priority: 20

Confidence scoring

Every rule has a confidence score from 0.0 to 1.0:

  • 1.0: Fully deterministic — the transform is guaranteed correct
  • 0.85–0.99: High confidence — deterministic with edge case caveats
  • 0.7–0.84: Medium confidence — AI-assisted with validation
  • <0.7: Lower confidence — requires additional human review

The overall PR confidence score is the minimum confidence across all applied rules.

Priority ordering

Rules within a file are executed in priority order (lowest first). Order matters — for example, a rename must happen before a parameter change on the same function.

Supported packages

PackageFromTo
express4.x5.x
react17.x19.x
react-dom17.x19.x
@types/react17.x19.x
axios0.x1.x
lodash3.x4.x
jest27.x30.x
eslint8.x9.x
webpack4.x5.x
typescript4.x5.x
sinon6.x19.x
mocha4.x11.x
ava4.x6.x
next13.x15.x
vue2.x3.x

Plus 14 more packages. See the full list in the Breaking Changes feature page.

Group rules

The _groups/ directory contains multi-package coordination rules for packages that must be updated together:

_groups/react-18-to-19.yaml
group: "react-ecosystem"
description: "Coordinated React 18 → 19 upgrade"
packages:
  - name: "react"
    from: "18.x"
    to: "19.x"
  - name: "react-dom"
    from: "18.x"
    to: "19.x"
  - name: "@types/react"
    from: "18.x"
    to: "19.x"
strategy: atomic    # All packages in single PR
order: sequential   # Apply rules in package order

Custom rules (Enterprise)

Enterprise and self-hosted customers can add custom rules for internal packages. Use the same YAML schema and mount at /rules/custom/. See the Self-Hosted Agent docs for details.

Rule file format in depth

Every rule file follows a consistent YAML schema with a top-level package identifier, version range, and an ordered array of rule objects. Here is the complete schema:

  • package (string, required) — the npm package name exactly as it appears in package.json, including scoped packages (e.g., @types/react).
  • from_version (semver range, required) — the source version range this rule file applies to. Uses standard semver syntax:4.x, >=4.0.0 <5.0.0, or specific versions like 4.21.0.
  • to_version (semver range, required) — the target version range. The rule file is selected when a detected update moves from a version matching from_version to a version matching to_version.
  • rules (array, required) — an ordered list of rule objects. Each rule object must have a type field matching one of the supported rule types. Additional fields vary by type (see below).

Group files (stored in the _groups/ directory) follow a different schema. Instead of a single package field, they have a group name, a description, a packages array referencing individual rule files, and coordination directives like strategy: atomic and order: sequential. Group files do not contain rules directly — they reference the rules defined in individual package files.

Rule types explained

Each rule type is designed for a specific class of code transformation. The type determines how Ovvoc processes the rule and directly affects the confidence score:

  • ast_transform — the safest and most reliable rule type. Uses the OXC AST parser to make structural changes to JavaScript and TypeScript source files. Because the transform operates on the parsed syntax tree (not raw text), it correctly handles whitespace, comments, formatting, and complex expressions. There are 11 subtypes (function rename, import path change, param signature change, etc.), each with specialized logic. Confidence is typically 0.95–1.0.
  • ast_grep_pattern — regex-based pattern matching with replacement. Used for patterns that are structurally simple enough that full AST parsing is unnecessary (e.g., replacing a string literal in a require call). Faster than AST transforms but less precise — regex can match unintended occurrences. Confidence is typically 0.85–0.95.
  • file_edit — line-level insertion, deletion, or replacement for non-code files such as .npmrc, .nvmrc, or .gitignore. Operates on raw text with line matching. Confidence is typically 0.9–1.0 for well-defined edits.
  • config_change — structured modification of JSON, YAML, or TOML configuration files. Supports operations like set (add or update a key), delete (remove a key), and rename (change a key name while preserving its value). Safer than file_edit for config files because it understands the file structure. Confidence is typically 0.9–1.0.
  • ai_assisted — delegates the transformation to AI when deterministic rules cannot handle the complexity (paradigm shifts, architectural changes, hidden behavioral differences). Each AI rule has a budget_tokens limit and a prompt_category that selects the appropriate AI prompt template. The AI output is validated against compilation and export-preservation constraints before being accepted. Confidence is typically 0.6–0.85.

Writing custom rules

Enterprise and self-hosted customers can create custom rules for internal packages or for public packages not yet covered by the built-in database. Follow these steps:

  1. Create a YAML file in the /rules/custom/ directory (or mount your rules directory at that path for self-hosted agents). Name it descriptively, e.g., my-package-1-to-2.yaml.
  2. Define the package and version range. Set the package, from_version, and to_version fields to match the update you want to handle.
  3. Add rules to the rules array. Each rule needs a type, the type-specific fields (pattern, replacement, file_pattern, etc.), a confidence score, and a priority number.
  4. Test against a sample project. Use a test repository that imports the target package and run the Ovvoc pipeline against it. Verify that the transforms produce the expected output and that build and tests pass.
  5. Iterate and refine. Adjust patterns, add edge cases, and test against more repositories. Once your rules are stable, they will be applied automatically for every update of that package.

Community contributions are welcome. If you write rules for a public npm package, consider submitting them as a PR to the Ovvoc rules repository. Accepted contributions benefit all Ovvoc users.

Testing rules locally

Before deploying custom rules to production, you should validate them thoroughly. Here is the recommended testing workflow:

  • Verify rule file syntax. Ensure your YAML is valid and the type field matches one of the supported rule types exactly: ast_transform, ast_grep_pattern, file_edit, config_change, or ai_assisted.
  • Check file pattern matching. Verify that the file_pattern glob matches the files you intend to transform. Common patterns include **/*.js, **/*.{ js,ts}, and src/**/*.tsx.
  • Validate transform output. For AST transforms and regex patterns, confirm that the before → after mapping produces the correct result. Pay special attention to edge cases like multiline expressions, template literals, and dynamic property access.
  • Run build and test. After applying your rules, run npm run build and npm test against the transformed project to verify nothing is broken. This is the same verification Ovvoc performs in the pipeline.

A dedicated CLI tool for local rule testing is planned for a future release. In the meantime, the self-hosted agent provides the most convenient testing path — mount your custom rules and run a test job against a development repository.

Built-in rules inventory

The Ovvoc rule database ships with 31 YAML rule files covering 29 npm packages and containing over 150 individual transformation rules. Here is a summary of the major packages covered:

  • Web frameworks: express (4→5), next (13→15), vue (2→3)
  • React ecosystem: react (17→19), react-dom (17→19), @types/react (17→19), react-router (5→7)
  • HTTP clients: axios (0.x→1.x)
  • Utilities: lodash (3→4)
  • Build tools: webpack (4→5), babel (6→7), typescript (4→5)
  • Linting: eslint (8→9)
  • Testing: jest (27→30), mocha (4→11), sinon (6→19), ava (4→6)

Additionally, 2 group rule files coordinate multi-package updates:

  • react-ecosystem group: Coordinates updates across react, react-dom, and @types/react to ensure all three packages are updated in a single atomic PR.
  • babel-ecosystem group: Coordinates @babel/core, @babel/preset-env, and related Babel packages that must be updated together to avoid version conflicts.

The rule database is continuously expanded as new package versions are released. Rule updates are delivered automatically to cloud customers and via agent updates for self-hosted deployments.

Need help?

Start with one repo and see verified PRs in minutes.