Skip to content

feat(skills): add batch-migration skill#13693

Open
MorAlekss wants to merge 2 commits into
NousResearch:mainfrom
MorAlekss:feat/batch-migration-380
Open

feat(skills): add batch-migration skill#13693
MorAlekss wants to merge 2 commits into
NousResearch:mainfrom
MorAlekss:feat/batch-migration-380

Conversation

@MorAlekss

@MorAlekss MorAlekss commented Apr 21, 2026

Copy link
Copy Markdown
Contributor

batch-migration skill — Parallel Code Migration via Git Worktree Isolation

Closes #380


1. What this skill does

batch-migration is a skill for orchestrating large-scale, parallelizable code migrations across a codebase. It decomposes a migration into independent work units, spawns one Hermes agent per unit in an isolated git worktree, and each agent independently implements, tests, and creates a PR. The coordinator tracks progress, verifies results, merges PRs in the correct order, and cleans up.

Trigger phrases: "batch migrate X to Y", "migrate all files from X to Y", "bulk refactor across the codebase", "parallel migration"


2. How it's implemented — phases

The skill implements the three-phase workflow described in issue #380, with two additional phases added based on real-world testing.

Phases from issue #380

Phase 1 — Research and Plan

  • Explore the codebase: find all affected files, understand conventions
  • Discover project runtime and entry points (server start command, CLI entry points, test infrastructure) to build accurate E2E test recipes
  • Run baseline tests and record exact passing/failing count as regression baseline
  • Decompose into work units: one unit per source file, no grouping, shared file assignment check
  • Determine E2E test recipe using one of four patterns: existing test suite, dev server + curl (API), browser automation (UI), CLI output verification
  • Present plan via clarify(): mandatory user approval gate before any work starts

Phase 2 — Execute

  • Prepare main branch: update .gitignore, requirements.txt, commit and push
  • Verify gh auth, save ROOT_DIR, create git worktrees with printf "%02d" zero-padding
  • Initialize todo tracking: one todo per unit
  • Write self-contained worker prompts: one prompt file per unit with everything the worker needs
  • Self-verify all prompts before spawning: automated checks for review step, PR report line, scope warning, worktree paths, duplicate files, port uniqueness, orphaned test files, browser verification
  • Spawn all workers simultaneously via terminal(background=True)

Phase 3 — Monitor and Verify

  • Poll workers, update status table, verify code review was run, spot-check PR diffs for scope violations

Additional phases (not in original issue)

Phase 4 — Merge

  • Coordinator analyses PR dependencies and builds merge order: source-only PRs first (no test files, no conflicts), then test-file PRs after all source changes are in main. A mandatory clarify() gate presents the final summary table with PR links and merge order, and waits for explicit user approval before any merge begins.
  • Run full test suite on main after all PRs merged and compare against baseline. If any regressions appear, the coordinator automatically spawns a cleanup worker that diagnoses and fixes the issue, then re-runs the suite to confirm everything is resolved. This acts as a safety net that can catch stale mocks, missing awaits, orphaned test files, or any other post-merge inconsistency without requiring manual intervention.

Phase 5 — Cleanup

  • Remove all worktrees, local branches, and remote branches

3. Phase alignment with issue #380

Issue Phase Status
Phase 1 MVP: three-phase workflow, worktree isolation, self-contained prompts, process(poll) tracking, workers create PRs, clarify() approval gate ✅ Fully implemented
Phase 2 Enhanced: worker failure recovery, conflict detection, progress dashboard, code review integration ✅ ~80% implemented: dynamic scaling based on system resources is not implemented; all other Phase 2 items are present
Phase 3 Advanced: multi-agent DAG, judge model, auto-merge, resumable migrations ❌ Not implemented

4. Additions beyond the issue description

The skill implements everything in Phase 1 MVP and goes further with several additions that emerged from real-world testing:

Full migration cycle — beyond PR creation

The issue describes the workflow ending at PR creation. This skill goes further and implements a complete end-to-end cycle:

Automated merge with approval gate: after all workers finish, the coordinator presents a final summary table with PR links and recommended merge order. A mandatory clarify() tool call stops execution and waits for explicit user approval. Only after the user confirms does the coordinator proceed with merging. This is a hard gate; unlike text-based STOP instructions, clarify() cannot be skipped by the agent.

Post-merge verification: after all PRs are merged, the coordinator pulls main and runs the full test suite, comparing results against the baseline recorded in Phase 1. This catches regressions that only appear after all changes are combined, which individual worktree tests cannot detect.

Self-healing cleanup worker: if post-merge tests fail (e.g. stale mocks, missing await, orphaned test files), the coordinator automatically spawns a cleanup worker with a fully self-contained prompt describing exactly what to fix. The cleanup worker creates a fix branch, opens a PR, and merges it. The coordinator then re-runs the full test suite to confirm all regressions are resolved before declaring the migration complete.

This means the skill delivers a migration that is verified working on main, not just a set of open PRs that may or may not pass when combined.

Merge order logic: source-only PRs must merge before test-file PRs. This prevents stale mock failures after merge because test mocks reference the new httpx pattern which doesn't exist until the source PR lands.

Cross-unit async dependency tracking: for async migrations, the coordinator reads each test file's imports, identifies functions from other units that will change signature (sync→async), and explicitly tells the test-file worker to add await and @pytest.mark.asyncio to affected test functions. Prevents the most common post-merge failure pattern.

Mock ownership manifest: every test-file worker receives an explicit table of every mock it must update, with current value and required new value. With a warning that mocks may pass in the worktree (because patch() creates attributes) but will fail after merge.

Pre-commit scope check with exit 1: each worker prompt contains a bash gate that blocks git commit if any file outside the worker's assigned list appears in the diff. Catches scope violations before they become merge conflicts.

Mock verification grep with exit 1: workers grep for stale old-pattern references before committing. If found, commit is blocked.

Orphaned test file check: The pre-spawn verification checks that every test file containing the old pattern is assigned to exactly one unit before spawning. Prevents the case where test files retain stale mocks because no worker owned them.

Port uniqueness check: for API/UI patterns, The pre-spawn verification checks that no two worker prompts use the same localhost port, preventing server startup conflicts during parallel verification.

E2E verification templates: The E2E recipe section provides four concrete templates (source-only/pytest, dev server + curl, browser tool calls, CLI output grep) so coordinators know exactly what to put in each worker's verification section.

printf "%02d" worktree naming: replaces seq -w which produced inconsistent zero-padding across platforms. Guarantees unit-01...unit-30 naming.

Per-file slicing instead of per-directory: the issue describes slicing per-directory or per-module (following Claude Code's pattern for large frontend codebases). The skill uses per-file slicing instead. This is an intentional decision: per-file units are smaller, more independently mergeable, and produce cleaner PRs with minimal conflict surface. For codebases where one file is trivially small, the coordinator can group files into one unit, but the default is per-file for maximum isolation and reviewability.


5. How aspects missing from Hermes infrastructure are solved

delegate_task as fallback spawning method

The issue describes two spawning approaches. The skill implements both. Primary method is terminal(background=True) which bypasses the 3-child limit. The skill also documents delegate_task as an explicit fallback for environments where hermes chat -w is unavailable, with a maximum of 3 workers at once in that mode.

Manual-only invocation (disableModelInvocation equivalent)

The issue specifies disableModelInvocation: true — the skill must never auto-trigger. This is enforced through COORDINATOR RULES at the top of the skill (read before anything else) and explicit trigger phrases that must be present in the user's message. The skill description also states "Manual invocation only — never auto-trigger this skill."

Worker isolation (no native worktree isolation)

Hermes has no native isolation: "worktree" parameter. The skill works around this by having the coordinator manually run git worktree add .hermes/worktrees/unit-NN -b batch/unit-NN main for each unit. Workers cd into their worktree as the first step and verify with pwd. The NEVER edit files outside your worktree rule is enforced at the prompt level.

Parallel spawning beyond 3-child limit

delegate_task is limited to 3 concurrent children. The skill uses terminal(background=True) + process(poll/wait/log) instead, which has no such limit.

Code review (no simplify skill in Hermes)

The issue references Claude Code's simplify skill for worker self-review. Hermes doesn't have simplify. The skill uses /requesting-code-review: Hermes's built-in code review slash command: as a direct equivalent. Every worker prompt requires /requesting-code-review before committing, with a hard STOP gate.

Progress dashboard (no native dashboard)

The coordinator maintains a live status table rendered as markdown and updated after every process(poll) call:

| # | Unit                     | Status  | PR                        |
|---|--------------------------|---------|---------------------------|
| 1 | migrate auth.py          | done    | github.com/.../pull/42    |
| 2 | migrate dashboard.py     | running |:                         |

Combined with the todo tool for tracking completion state.


6. Tests conducted

The skill was tested across multiple projects and migration types. All tests resulted in baseline test count matching post-migration test count (zero regressions). Tests were run with 6 to 12 concurrent workers per run depending on codebase size.

Existing integration test suite pattern (pytest)

Project Result Notes
ecommerce-api requests→httpx async, full ecommerce codebase, multiple runs across skill versions
test-sync-to-async Python sync→async migration
test-sync-to-async-2 Python sync→async migration
test-ospath-to-pathlib os.path→pathlib migration
test-print-to-logging print→logging migration

CLI verification pattern

Project Result Notes
cli-migration-test Weather CLI, requests→httpx, CLI output verified
cli-migration-test-3 Multi-module CLI (weather, news, geo, currency), asyncio.run() pattern

Dev server + curl pattern (API)

Project Result Notes
api-migration-test FastAPI project, requests→httpx, coordinator discovered uvicorn via runtime discovery

Browser automation pattern (UI)

The skill includes dedicated support for UI migrations. The E2E recipe section provides a browser verification template and each worker prompt contains a ## Browser verification section separate from the shell-based E2E recipe. This separation is intentional: browser tool calls (browser_navigate, browser_snapshot, browser_vision) are agent tool calls, not shell commands, and cannot be placed in the same bash block as the server start command. The coordinator fills in the shell part (start dev server, assign unique port per unit) in the E2E recipe, and the browser steps in the dedicated section. The skill also includes a pre-spawn check that verifies UI units have the browser verification section filled and not left as N/A.


7. Answers to Open Questions from issue #380

"What's the right default concurrency limit?"
Testing showed stable operation with up to 12 concurrent workers across multiple test runs. The skill recommends 5-20 units as the default range, with a maximum of 30 for large codebases. No rate limit issues were observed at these levels.

"Should workers share any state or be fully isolated?"
Fully isolated. Each worker gets everything it needs in its self-contained prompt: overall goal, specific task, codebase conventions, mock patterns, cross-unit async dependencies, and E2E test recipe. Workers have zero dependency on coordinator context or each other.

"How should the user approve the plan: via clarify tool or file-based review?"
Via clarify() tool. Tested across all runs: it physically stops the coordinator and waits for explicit user input before any work begins. Text-based STOP instructions are unreliable (agents skip them); clarify() cannot be skipped.

"How to handle partially failed migrations?"
The coordinator tracks all workers via the todo tool and status table. If some workers fail, the coordinator notes them in the final summary and the user decides whether to fix manually or spawn targeted cleanup workers. If post-merge tests fail, the coordinator automatically spawns a cleanup worker.

"Should we increase MAX_CONCURRENT_CHILDREN or rely on subprocess spawning?"
Subprocess spawning via terminal(background=True) is the right approach: it bypasses the 3-child delegate_task limit entirely with no code changes needed. delegate_task is kept as a documented fallback for environments where hermes chat -w is unavailable.

"How to handle migrations where units aren't truly independent?"
The ## Cross-unit async dependencies section in worker prompts handles the most common case: when one unit's source changes affect another unit's test expectations. The coordinator detects these dependencies in Phase 1 and explicitly instructs each test-file worker about functions from other units that will change signature.

"Should there be a --dry-run mode?"
Phase 1 effectively serves as a dry-run. The coordinator does a full research pass, decomposes the codebase into work units, builds the complete plan with file lists and E2E recipes, and presents it via clarify(). The user sees the entire migration plan before a single file is touched. Only after explicit approval does execution begin.


8. How the Cons/Risks from issue #380 are addressed

"Orphaned worktrees or branches after failed runs"
Phase 5 (Cleanup) is explicitly marked as non-skippable in the skill. It removes all worktrees with git worktree remove --force, runs git worktree prune, and deletes both local and remote branches. Cleanup uses printf "%02d" naming which guarantees consistent branch names across all platforms.

"Worker divergence: inconsistent stylistic choices"
Each worker prompt contains the exact migration pattern with before/after code examples, codebase conventions discovered in Phase 1, and explicit instructions for every file it must modify. Workers follow the same pattern because they receive the same template: not general instructions.

"PR sprawl: 30 PRs overwhelming code review"
The merge phase handles this automatically. The coordinator merges all PRs in the correct order (source-only first, test-file PRs last) without requiring manual review of each PR. A spot-check of all PR diffs verifies scope before merge. Individual PR review is optional: the coordinator handles it.

"Git worktree edge cases with submodules or unusual configurations"
The skill uses standard git worktree commands and has been tested on macOS and Linux. Submodule support is not explicitly tested and may require additional handling.


Skill file

skills/software-development/batch-migration/SKILL.md

Version: 3.37.1-E2E
Platforms: linux, macos
Requires: terminal toolset, gh CLI authenticated

@alt-glitch alt-glitch added type/feature New feature or request tool/skills Skills system (list, view, manage) duplicate This issue or pull request already exists labels Apr 21, 2026
@alt-glitch

Copy link
Copy Markdown
Collaborator

Likely duplicate of #8194 — both implement the batch-migration skill for #380.

@MorAlekss MorAlekss changed the title Feat/batch migration 380 feat(skills): add batch-migration skill Apr 21, 2026
@MorAlekss

Copy link
Copy Markdown
Contributor Author

@alt-glitch This is not a duplicate, it's a working and adapted version of the skill for Hermes. I explained why in the comment to #380.

Happy to adjust based on feedback.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

duplicate This issue or pull request already exists tool/skills Skills system (list, view, manage) type/feature New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Feature: Batch Migration Skill — Parallel Code Migration Orchestration with Git Worktree Isolation (inspired by Claude Code /batch)

2 participants