The problem. Legacy code is everywhere: internal tools, research code, and business logic written years ago for Python 2 or old library versions. It usually has no tests, and the people who wrote it have moved on. Modernizing it is risky because nobody fully remembers what the code is supposed to do. The most dangerous bugs are not crashes but silent changes: code that still runs after an upgrade but quietly behaves differently. So teams postpone modernization, and technical debt keeps growing. Our solution. LegacyLift is a modernization pipeline built on IBM Bob 2.0 that follows one rule: record the old behavior before changing anything. It has five stages: Analyze: Bob scans the codebase and reports every deprecated construct with line numbers, risk ratings, and out-of-scope modules. Protect: Bob generates characterization tests and runs the original code in its original runtime (Python 2.7 in Docker) to capture "golden" outputs. The tests must pass on the legacy code before any change is allowed. Modernize: Bob upgrades the code to Python 3.12 and current NumPy, following official migration guides, with one subagent per module. Verify: The same tests run against the modernized code in a Python 3.12 container. Report: A web page shows exactly what changed, with before/after numbers. Tested on a real project. We ran LegacyLift on Michael Nielsen's "Neural Networks and Deep Learning" code, a widely used MIT-licensed project written for Python 2.7 that its author has said he will not port to Python 3. Results: Deprecated or Python 2-only usages: 23 → 0 across three modules Characterization tests: 0 → 31, all 31 passing on the original code in Python 2.7 Original code on Python 3.12: 0 passed, 29 failed Modernized code on Python 3.12: 29 passed, 0 failed, plus 2 intentional, documented behavior changes The Theano-based module was flagged as out of scope, with the reason documented Silent bugs caught. LegacyLift found problems a simple find-and-replace would miss: zip() returning a one-time iterator, a bare print that silently does nothing in Python 3, and an integer-division hazard in the learning-rate update (3/2 equals 1 in Python 2 but 1.5 in Python 3). Instead of copying that bug or changing it silently, LegacyLift detected it, documented it, and fixed it as a deliberate decision. What makes it different. Most AI refactoring tools change code first and hope existing tests catch problems, but legacy code rarely has tests. LegacyLift builds the safety net first, captured from the original runtime rather than assumed, and turns every behavior change into an explicit, reviewable decision. Who it's for. Teams maintaining old internal tools, companies migrating off Python 2 or outdated libraries, and research groups keeping old code usable. A developer points LegacyLift at a repository, reviews the analysis, and gets back modernized code, a test suite, and a report they can trust. Next steps: more migration paths (Java 8 → 17, COBOL), CI integration, and dashboards to track technical debt over time.
Category tags: