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:
# 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 rulesRule types
ast_transform
The primary rule type. Uses the OXC AST parser to apply syntax-tree-level transformations. There are 11 subtypes:
| Subtype | Description |
|---|---|
function_rename | Rename a function or method call |
import_path_change | Change import/require paths |
param_signature_change | Modify function call parameters |
default_to_named_export | Convert default to named import |
named_export_rename | Rename a named import/export |
deprecated_api_replacement | Replace deprecated API calls |
config_key_rename | Rename keys in config objects |
syntax_change | Grammar/syntax pattern replacement |
async_api_change | Sync to async API migration |
type_system_change | TypeScript type annotation updates |
middleware_api_change | Plugin/middleware signature changes |
- type: function_rename
from: "render"
to: "createRoot"
module: "react-dom"
file_pattern: "**/*.{jsx,tsx}"
confidence: 1.0
priority: 1ast_grep_pattern
Regex-based pattern matching with replacement. Used for patterns that are too simple for full AST analysis:
- type: ast_grep_pattern
pattern: "require\('express'\)\.Router\(\)"
replacement: "require('express').Router()"
file_pattern: "**/*.js"
confidence: 0.9
priority: 5config_change
Modify JSON, YAML, or TOML configuration files:
- type: config_change
file: "tsconfig.json"
operations:
- set: "compilerOptions.moduleResolution"
value: "bundler"
- delete: "compilerOptions.typeRoots"
confidence: 0.95
priority: 3file_edit
Line-level insertion, deletion, or replacement for non-code files:
- type: file_edit
file: ".npmrc"
operations:
- insert_after: "registry="
line: "engine-strict=true"
confidence: 1.0
priority: 8ai_assisted
Budget-controlled AI generation with validation. Used when deterministic rules can't solve the transformation:
- 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: 20Confidence 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
| Package | From | To |
|---|---|---|
| express | 4.x | 5.x |
| react | 17.x | 19.x |
| react-dom | 17.x | 19.x |
| @types/react | 17.x | 19.x |
| axios | 0.x | 1.x |
| lodash | 3.x | 4.x |
| jest | 27.x | 30.x |
| eslint | 8.x | 9.x |
| webpack | 4.x | 5.x |
| typescript | 4.x | 5.x |
| sinon | 6.x | 19.x |
| mocha | 4.x | 11.x |
| ava | 4.x | 6.x |
| next | 13.x | 15.x |
| vue | 2.x | 3.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:
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 orderCustom 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 inpackage.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 like4.21.0.to_version(semver range, required) — the target version range. The rule file is selected when a detected update moves from a version matchingfrom_versionto a version matchingto_version.rules(array, required) — an ordered list of rule objects. Each rule object must have atypefield 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 likeset(add or update a key),delete(remove a key), andrename(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 abudget_tokenslimit and aprompt_categorythat 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:
- 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. - Define the package and version range. Set the
package,from_version, andto_versionfields to match the update you want to handle. - Add rules to the
rulesarray. Each rule needs atype, the type-specific fields (pattern, replacement, file_pattern, etc.), aconfidencescore, and aprioritynumber. - 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.
- 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
typefield matches one of the supported rule types exactly:ast_transform,ast_grep_pattern,file_edit,config_change, orai_assisted. - Check file pattern matching. Verify that the
file_patternglob matches the files you intend to transform. Common patterns include**/*.js,**/*.{ js,ts}, andsrc/**/*.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 buildandnpm testagainst 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/reactto 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.