DEV Community

Mohammad Tejabwala
Mohammad Tejabwala Subscriber

Posted on

Sloth Migrate

Hacktoberfest Open-Source AI Challenge Week 3: Slow and Steady Submission πŸ¦₯

This is a submission for the Hacktoberfest Open-Source AI Challenge Week 3: Slow and Steady

Remember the critical PHP vulnerability discovered just recently that sent shockwaves through thousands of legacy servers worldwide? It exposed a brutal reality that every engineering team knows but rarely admits: nobody runs outdated, vulnerable software because they want toβ€”they do it because major dependency upgrades are terrifying.

When foundational libraries release breaking architectural shifts (such as Pydantic v1 to v2, SQLAlchemy 1.4 to 2.0, or major framework redesigns), breaking changes ripple across hundreds of files. Upgrading a manifest constraint breaks your build; fixing one deprecation cascades into three new runtime exceptions. Teams procrastinate for monthsβ€”or yearsβ€”until an active zero-day turns tech debt into an urgent fire.

That sparked an idea: What if an agent took on the dirty work of dependency migrations, but operated under strict engineering discipline? Instead of rushing to overwrite files, what if it worked slowly, methodically, and durably?

Meet SlothMigrate.


What I Built

SlothMigrate is an autonomous, self-healing dependency migration engine designed to safely upgrade Python projects across major breaking revisions.

Rather than treating code migration as an unconstrained text generation task, SlothMigrate implements a closed-loop verification pipeline:

  1. Manifest Inspection & Resolution: Automatically parses pyproject.toml (PEP 621 & Poetry) and requirements.txt, resolves latest stable releases via PyPI, and safely bumps version constraints.
  2. Deterministic Sandbox Test Harness: Executes local unit tests (pytest) with deprecation escalation flags (-W error::DeprecationWarning), capturing exact failure traces.
  3. Targeted AST Patching: Parses the test traceback to isolate the failing file, line number, and deprecation error, prompting an open-weight model with isolated context to draft a surgical modernization patch.
  4. Pre-Disk AST Compiler Guard: Runs Python's native ast.parse over generated code in-memory. If an LLM hallucinates markdown commentary, drops parentheses, or breaks indentation, the patch is blocked before touching the filesystem.
  5. Stateful Self-Healing: Repeats the test-diagnose-patch cycle until all tests turn green, then renders clean unified diffs for developer review.

Why It's Useful & How It Helps Developers

Manual major migrations are cognitively exhausting and prone to human error:

  • Eliminates Manual Pattern Replacement: Upgrades like Pydantic v1 to v2 require converting @validator to @field_validator, injecting @classmethod, updating signatures, and replacing .dict() with .model_dump(). SlothMigrate automates these repetitive syntax updates.
  • Guarantees Zero Broken Commits: Because changes are gated by both compiler-level AST verification and automated test execution, the engine never leaves a repository in a half-broken state.
  • Reduces Security Lag Time: By turning days of high-friction manual refactoring into a self-executing background routine, open-source maintainers and enterprise teams can eliminate legacy CVE exposure without burning engineering sprints.

Demo

Here is SlothMigrate executing a complete, multi-pass durable migration on a legacy Pydantic project:

Agent session recording

Because this was built using the Gemini application rather than any agents, it's ineligible for the post.


Code

The complete source code is open-source under the MIT license:

SlothMigrate πŸ¦₯⚑

Autonomous, Durable Dependency Migration Agent powered by Google Gemma, Temporal, and Sentry.

Hacktoberfest Model Orchestration Observability License: MIT


πŸ“– Overview

Upgrading breaking major dependencies (such as Pydantic v1 β†’ v2, SQLAlchemy 1.4 β†’ 2.0, or modern typing conventions) is often avoided by development teams. Simple regex replacements fail to capture schema semantics, and large-language-model coding tools frequently hallucinate, strip critical classes, or generate invalid syntax.

SlothMigrate transforms breaking dependency upgrades into a deterministic, fault-tolerant self-healing loop:

  1. Detects & Bumps: Inspects pyproject.toml (PEP 621 / Poetry) and requirements.txt, updates version constraints, and synchronizes the virtual environment.
  2. Executes Test Suite: Runs pytest with -W error::DeprecationWarning to escalate deprecated APIs into actionable errors.
  3. Pinpoints Exact Failures: Parses Python tracebacks to extract the exact target file, line number, and error message across platforms (Windows, Linux, macOS).
  4. Targeted Gemma Refactoring: Leverages Google's gemma-4-26b-a4b-it with an engineering-focused prompt enforcing zero code truncation and strict public API preservation.
  5. AST…

Key Architecture Components

  • src/sloth_migrate/ast_guard.py: In-memory Python AST validator that blocks malformed LLM outputs.
  • src/sloth_migrate/workflows/migration_workflow.py: Temporal state machine managing durable iterations, retry budgets, and state recovery.
  • src/sloth_migrate/workflows/activities.py: Atomic activities for dependency bumping, test execution, and LLM code refactoring.
  • src/sloth_migrate/telemetry.py: Custom Sentry spans tracking agent transactions, token consumption, and execution waterfalls.
  • src/sloth_migrate/ecosystems/python_ecosystem.py: Traceback analyzer isolating file paths, exact line numbers, and deprecation classes.

How I Built It

SlothMigrate bridges deterministic developer tooling with probabilistic AI generation through a defensive architecture:

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                   CLI / Typer Engine                   β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                            β”‚
                            β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚         Temporal Durable Workflow Orchestration         β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”          β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”‚
β”‚  β”‚ bump_and_install   β”‚ ───────► β”‚    run_tests     β”‚  β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜          β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β”‚
β”‚                                            β”‚           β”‚
β”‚                           [Failing Tests]  β–Ό           β”‚
β”‚                         β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”‚
β”‚                         β”‚ generate_and_apply_patch  β”‚  β”‚
β”‚                         β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                                        β”‚
           β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
           β–Ό                                                        β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                                 β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  Google Gemma Model  β”‚                                 β”‚   AST Syntax Guard   β”‚
β”‚ (gemma-4-26b-a4b-it) β”‚ ───────► Raw Code Patch ──────► β”‚     (ast.parse)      β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                                 β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                                                                    β”‚
                                                            [Valid] β–Ό
                                                         Target Codebase
Enter fullscreen mode Exit fullscreen mode

Deterministic Failure Isolation

Instead of passing an entire codebase or large terminal dumps into an LLM context, PythonEcosystem.parse_traceback parses pytest stdout/stderr using strict regular expressions to isolate:

  1. The exact repository-internal file requiring attention (filtering out external virtual environment frames).
  2. The exact offending line number.
  3. The specific deprecation or exception class (PydanticDeprecatedSince20).

The AST Compiler Guard

Before any model-generated code is permitted to touch the target filesystem, it must pass through Python's native syntax compiler:

def validate_python_code(code: str, filename: str = "<generated>") -> ASTValidationResult:
    try:
        tree = ast.parse(code, filename=filename)
        return ASTValidationResult(is_valid=True, ast_tree=tree)
    except SyntaxError as e:
        return ASTValidationResult(is_valid=False, error_message=f"SyntaxError at line {e.lineno}: {e.msg}")
Enter fullscreen mode Exit fullscreen mode

If the model introduces bad indentation, unclosed delimiters, or partial code blocks, the patch is rejected in-memory, preserving the integrity of the target repository.


Why Does Open Innovation Matter?

Open innovation is essential for developer infrastructure and automated tooling:

  1. Codebase Privacy & Data Sovereignty: Proprietary enterprise code cannot always be transmitted to closed SaaS APIs. Open-weight models like Gemma allow migration engines to execute within local boundaries, on-premises servers, or private VPCs without exposing proprietary IP.
  2. Deterministic Architecture Over Closed Magic: Closed APIs frequently alter models and prompt behaviors without notice. Open architectures provide reproducible results, predictable token performance, and deterministic stability.
  3. Extensibility & Community Collaboration: Open-source projects thrive when specialized tools can be composed together. SlothMigrate unites community standards (pytest, ast, temporalio, sentry-sdk, typer) into an integrated developer tool.

The Lazy Payoff

During testing on legacy projects:

  • The Manual Baseline: Upgrading a real Pydantic v1 service manually requires reading migration documentation, hunting down deprecated class validators across multiple files, altering method signatures, inserting @classmethod annotations, rewriting serialization calls, and iteratively debugging test suites. This typically consumes several hours to multiple days of developer time.
  • With SlothMigrate: The entire cycleβ€”from manifest bump to green pytest runβ€”completed autonomously in under 90 seconds across 2 iterations.

Developers can kick off a migration, step away from their desk, and return to an AST-verified codebase with green tests and clear diffs.


Prize Categories

Featured Categories

πŸ† Best Use of Gemma

  • How Gemma Was Used: We integrated Google's open-weight Gemma model (gemma-4-26b-a4b-it) via Google AI Studio as the core reasoning engine for syntax and architectural modernization.
  • Implementation Details: Instead of generic code generation, Gemma was deployed as a surgical refactoring agent. We constructed targeted prompts containing the isolated pytest traceback, the exact line number, the runtime deprecation warning, and the source file. Gemma ingested legacy Pydantic v1 syntax and reliably produced v2 implementations, correctly replacing @validator with @field_validator, injecting required @classmethod decorators, and updating .dict() to .model_dump().
  • Impact: Gemma demonstrated high adherence to strict system instructions, consistently emitting clean Python without conversational filler, allowing our AST parser to validate and write the patches directly.

Partner Categories

πŸ›‘οΈ Best Use of Temporal

  • Making the Migration Agent Durable: AI agents operating on developer repositories are inherently multi-step and prone to external failuresβ€”LLM rate limits, network timeouts during PyPI package downloads, or interrupted terminal sessions. We wrapped SlothMigrate's entire self-healing loop in a durable Temporal Workflow (DependencyMigrationWorkflow).
  • Workflow Architecture:
    • Activity 1 (bump_and_install_activity): Modifies manifests and installs updated packages into the sandbox, configured with exponential retry policies.
    • Activity 2 (run_tests_activity): Executes pytest in an isolated process and extracts failure points.
    • Activity 3 (generate_and_apply_patch_activity): Invokes Gemma, validates syntax against the AST guard, calculates unified diffs, and writes patches to disk.
  • Fault Tolerance in Practice: If an activity experiences an API blip or network dropout, Temporal's retry policy automatically intervenes without restarting the entire migration from scratch. If the machine terminates mid-run, the workflow preserves state and resumes from the exact activity boundary.
  • Observability: Maintainers can open the Temporal Web UI (http://localhost:8233) to inspect live state transitions, execution timelines, retry counts, and payloads.

πŸ” Best Use of Sentry Agent Tracing

  • Instrumenting Agent Telemetry: To understand agent latency, token costs, and internal debugging loops, we instrumented SlothMigrate with the Sentry SDK (sentry-sdk[tracing]) using custom spans across every lifecycle phase.
  • Custom Spans Monitored:
    • manifest.bump: Tracking manifest file reads and regex rewrite duration.
    • pip.install: Measuring sandbox package installation latency.
    • pytest.run: Capturing test execution runtime and return codes.
    • gemma.generate_fix: Recording LLM round-trip latency, prompt size, response size, and token usage.
    • ast.validate: Tracking in-memory compilation overhead and recording syntax errors as tagged Sentry events.
  • Debugging with Tracing Waterfalls: During development, Sentry traces exposed where the agent spent the majority of its time (compilation vs. LLM inference) and allowed us to immediately catch rejected AST patterns before they touched disk.

Clone and enter SlothMigrate

git clone https://github.com/Mohammadtej/Sloth-Migrate
cd SlothMigrate

Set up environment

python -m venv .venv
source .venv/bin/activate # or .venv\Scripts\activate on Windows
pip install -e .

Set your API keys

export GEMMA_API_KEY="your-google-ai-studio-key"
export SENTRY_DSN="your-sentry-dsn"

Run against the included demo repository

sloth-migrate run --path demo_pydantic_repo --package pydantic --version 2.14.1

Screenshots

Thank you for reading this far!

Top comments (2)

Collapse
 
mohammad515253 profile image
Mohammad Tejabwala •

PS: This was initially intended for other ecosystems as well. The idea itself originated from the recent PHP vulnerability that was discovered and people had to take the latest version.... But alast Gemma did not perform well with the PHP code, and the concept had to be delayed for another release

Collapse
 
mohammad515253 profile image
Mohammad Tejabwala •

This is my 3rd hackathon and again submitted at the last minute: 🫣dev.to/mohammad515253/sloth-migrat...

Maybe I am lazy...