Batch codemod call sites into reviewable pull requests
Your task
Your company is removing a deprecated internal API used at about 4,000 call sites in a monorepo. A codemod agent (one that rewrites code by a fixed rule) migrates the mechanical sites in small pull requests per team and hands the rest to people.
Write plan_codemod_batches(call_sites, max_sites_per_pr): the rule your agent follows to turn the inventory into a migration plan.
call_sites(list of str): one entry per call site, writtenteam:pattern, for example"payments:simple".max_sites_per_pr(int): the most call sites one pull request may hold. A value of 0 or less means 1.- Return a list of plan entries, each written
owner=<team>;rule=<rule>;sites=<count>.
Rules:
- Split each entry at its first
:into team and pattern, exactly as written, with no trimming. An entry with no:is all team, with an empty pattern. - The rule is the pattern itself if it is
import,simpleorwrapper. Any other pattern, the empty one included, gets the rulemanual. - Group the sites by team and rule, and count each group.
- Order the groups by the text
team + "|" + rule, compared character by character.|sorts after every letter, digit,-and_, so teamabcomes before teama. - A
manualgroup becomes one entry with its full count, whatever the cap: it is a review queue, not a pull request. - Any other group is split into pull requests of
max_sites_per_prsites, full ones first, then the remainder.
Examples
plan_codemod_batches(call_sites: list[str], max_sites_per_pr: int) -> list[str]Example 1
Input
plan_codemod_batches(["payments:simple", "payments:simple", "payments:simple", "search:dynamic"], 2)Output
["owner=payments;rule=simple;sites=2", "owner=payments;rule=simple;sites=1", "owner=search;rule=manual;sites=1"]Example 2
Input
plan_codemod_batches(["core:generated", "core:reflection", "core:simple"], 10)Output
["owner=core;rule=manual;sites=2", "owner=core;rule=simple;sites=1"]Example 3
Input
plan_codemod_batches(["search:simple", "payments:simple", "search:simple", "payments:wrapper", "search:dynamic"], 2)Output
["owner=payments;rule=simple;sites=1", "owner=payments;rule=wrapper;sites=1", "owner=search;rule=manual;sites=1", "owner=search;rule=simple;sites=2"]