TRANSMISSION // 2611.05457v1

Bloomberg’s AI-assisted code migrations hit a human review bottleneck

Source published

An industrial experience report describes hybrid pipelines that generated 2,333 migration pull requests at Bloomberg, with 729 merged by the observation cutoff. The authors identify review, testing and deployment effort—not change generation—as the main operational constraint.

AI-generated conceptual illustration for Bloomberg’s AI-assisted code migrations hit a human review bottleneck
AI-generated conceptual illustration; not documentary evidence.

Generating a software migration is not the same as getting it adopted. Bloomberg’s Automated Uplift project combined language models with deterministic tooling to prepare infrastructure changes across thousands of candidate repositories, but most generated pull requests received no developer decision during the study.

Infrastructure migrations can remain unfinished even when their benefits are clear: each repository requires engineering attention, while feature work takes priority. In an industrial experience report submitted to arXiv on November 3, 2026, researchers from Bloomberg and University College London describe an attempt to change that calculation through Automated Uplift.

Their central finding is organizational as much as technical. The system could generate migration pull requests faster than repository owners could review, test and deploy them. Automation reduced the work of preparing changes, but did not remove the work of accepting them.

Two migrations, different verification problems

The report examines two sustained campaigns. One moved Python packages from a proprietary shared environment to an internal dependency-isolated packaging model, called PyPackaging in the paper. It targeted approximately 1,900 candidate repositories with widely varying structures.

The other targeted approximately 6,700 C++ repositories for migration from an internal build system, called CppBuild, to CMake. These projects were more uniform. PyPackaging and CppBuild are pseudonyms for Bloomberg tools.

The evaluation includes campaign pull requests created through April 30, 2026, with outcomes measured on June 30. Every included request therefore had at least two months to receive a decision. Across both campaigns, the pipelines generated 2,333 pull requests, of which 729 were merged. These figures describe generated and merged changes, not completed migrations across the entire candidate population or verified production deployments.

Models transform; deterministic tools check

Both pipelines used a shared structure: classify the repository, collect context, render a prompt, execute a transformation, validate the result and describe the change. Classification, context collection, prompt rendering and validation were deterministic. Language models performed transformations, attempted repairs after failed checks and wrote pull-request descriptions.

The division of work differed by campaign. For Python packaging, the model directly edited packaging configuration, source layout and build files. For C++, it extracted build information into structured JSON. A schema checked that information, and templates generated the CMake files. The pipeline then built the project and ran its unit tests before opening a pull request.

One sufficiently standardized C++ category followed a separate, fully deterministic migration path without an LLM. The authors’ approach was therefore not to use a model everywhere, but to restrict it to work that benefited from flexible interpretation.

Python checks offered less assurance. Packaging validation and comparisons of scripts’ --help behavior could catch some mistakes, but could not establish that an application would work after deployment. A dependency choice could pass those checks and still fail during real execution.

Production behavior supplied missing context

The Python pipeline combined source analysis with production information, including interpreter startup logs, module usage traces and dependency versions deployed on different clusters.

For example, imports found both in source code and observed execution could be matched to versions available in the deployed environment. Source-only imports might instead be conditional, test-related or unused. A shared module-to-package mapping also addressed cases where an import name differs from the package supplying it.

The authors report that runtime information helped identify actual entry points, dynamically loaded modules and environment-specific dependency problems. However, they did not conduct a controlled comparison with and without telemetry. Its importance is an engineering judgment supported by their experience, not a quantified causal result.

Most requests waited for a decision

The C++ campaign produced 2,039 pull requests: 698 were merged, or 34.2%; 165 were rejected; and 1,176 received no developer decision. The Python campaign produced 294: 31 were merged, or 10.5%; 64 were rejected; and 199 received no decision.

“No decision” included requests still open and those closed by automation without a developer decision. It was the largest outcome category in both campaigns.

The authors attribute much of the adoption gap to stronger pre-review verification for C++ and its more uniform repositories. But those explanations cannot be isolated: the campaigns also differed in timing, perceived risk and review support. Neither involved an urgent deadline or security driver.

Direct merges also missed some downstream use. In 34 of the 51 Python repositories where generated requests were rejected, owners later completed migrations themselves. Fourteen of their replacement requests reused most of the generated changes. Developers reported difficulty contributing to the bot’s branch, motivating proposed changes to collaboration and testing.

Lessons with limits

This is evidence from two campaigns inside one organization, not a controlled benchmark of migration automation. Models, prompts and pipeline rules changed during evaluation. The authors built the system they assessed, and proprietary code and data are unavailable publicly.

The practical lesson is nevertheless concrete: generating more changes does not automatically produce more adopted changes. In these campaigns, verification evidence, reusable migration patterns and the receiving team’s workload shaped what happened after generation.