Devin Best Practices: Delegating Multi-File Refactoring with Spec Docs, Branch Isolation & Code Review Checkpoints
Devin Best Practices for Multi-File Refactoring Delegation
Devin, Cognition's autonomous AI software engineer, excels at large-scale refactoring tasks—but only when given clear specifications, proper branch isolation, and well-defined human-in-the-loop review checkpoints. This guide covers a battle-tested workflow for delegating complex multi-file refactoring to Devin while maintaining full control over code quality and project stability.
Prerequisites
- Active Devin workspace with GitHub or GitLab integration
- Repository access configured (SSH or OAuth)
- Team agreement on branch naming conventions and review policies
- A specification document template (covered below)
Step 1: Write a Clear Specification Document
Devin performs best when given explicit, structured instructions. Ambiguity leads to drift. Create a spec document in your repository before delegating.
# specs/refactor-auth-module.md
Objective
Migrate the authentication module from callback-based patterns to async/await
across all files in src/auth/ and src/middleware/.
Scope
- Files: src/auth/.ts, src/middleware/auth.ts, tests/auth/**/*.test.ts
- Do NOT modify: src/auth/legacy-adapter.ts (deprecated, scheduled for removal)
Constraints
- Maintain 100% backward compatibility on all public API signatures
- Keep existing error codes and HTTP status responses unchanged
- All existing tests must pass without modification to test assertions
Acceptance Criteria
- Zero callback-pattern usage in scoped files
- All async functions properly handle errors with try/catch
- No new dependencies added
- CI pipeline passes (lint, type-check, unit tests, integration tests)
Review Checkpoints
- Checkpoint 1: After modifying src/auth/service.ts and src/auth/provider.ts
- Checkpoint 2: After updating all middleware files
Checkpoint 3: After test updates and full CI green
Step 2: Set Up Branch Isolation
Never let Devin work directly on main or develop. Create an isolated feature branch with a consistent naming convention.
# Create the branch before assigning to Devin
git checkout -b refactor/auth-async-await origin/main
git push -u origin refactor/auth-async-awaitWhen starting a Devin session, specify the branch explicitly in your prompt:
Work on the branch refactor/auth-async-await.
Read the specification at specs/refactor-auth-module.md.
Do not push to main. Commit incrementally after each logical unit of work.
Stop and notify me at each review checkpoint defined in the spec.Branch Protection Rules
Configure your repository to prevent accidental merges:
# GitHub CLI example
gh api repos/{owner}/{repo}/branches/main/protection -X PUT
-f required_pull_request_reviews.required_approving_review_count=1
-f enforce_admins=trueStep 3: Define Human-in-the-Loop Checkpoints
Checkpoints are the most critical part of the workflow. They prevent Devin from compounding errors across files.
| Checkpoint | Trigger | What to Review | Action |
|---|---|---|---|
| CP-1 | Core module refactored | Pattern correctness, error handling | Approve or request changes |
| CP-2 | Dependent files updated | Integration consistency, type safety | Approve or redirect approach |
| CP-3 | Tests updated, CI green | Coverage, edge cases, pipeline status | Approve for PR or iterate |
Include this instruction in every Devin session:
After completing each checkpoint, create a commit with the message format:
“checkpoint(N): description of changes”
Then stop and wait for my review before proceeding.
Do not continue to the next checkpoint without explicit approval.Step 4: Review and Iterate
At each checkpoint, review the diff carefully:
# Review checkpoint commits git log —oneline refactor/auth-async-await ^mainInspect specific checkpoint diff
git diff HEAD
3..HEAD2 — src/auth/Run tests locally before approving
npm run test — —coverage src/auth/
If changes need correction, provide specific feedback in the Devin session:
Checkpoint 1 review: Two issues found.
- In src/auth/service.ts line 47, the catch block swallows the error silently. Rethrow after logging: logger.error(err); throw err;
In src/auth/provider.ts line 112, the Promise.all should use Promise.allSettled to handle partial failures gracefully. Fix these before moving to Checkpoint 2.
Step 5: Final Merge via Pull Request
After all checkpoints pass, create a PR with full context:
# Create PR with spec reference
gh pr create
—base main
—head refactor/auth-async-await
—title “refactor: migrate auth module to async/await”
—body “Spec: specs/refactor-auth-module.md
All 3 review checkpoints approved.
CI status: green.
Devin session: [link-to-session]“Pro Tips for Power Users
- Use file-scoped instructions: If certain files need special treatment, add inline comments like
// DEVIN: preserve this function signature exactlyto guide behavior. - Batch related refactors: Group files by dependency order in your spec. Refactor leaf nodes first, then work inward to reduce cascading breakage.
- Leverage Devin’s shell access: Include commands in your spec like
Run npm run typecheck after every file changeto catch errors incrementally. - Pin the commit range: Tell Devin the exact base commit:
Base your work on commit abc1234. Do not rebase or merge during the session. - Template your specs: Store a
specs/TEMPLATE.mdin your repo so every delegation follows the same structure. - Use squash merges: After approval, squash checkpoint commits into a single clean commit for main branch history.
Troubleshooting Common Issues
| Problem | Cause | Solution |
|---|---|---|
| Devin modifies files outside scope | Spec scope was ambiguous or missing exclusions | Add explicit Do NOT modify section with file globs |
| Devin skips checkpoints and continues | Checkpoint instruction was buried in long prompt | Put checkpoint rules at the top of your prompt, bolded |
| Tests fail after refactoring | Devin changed both implementation and test assertions | Add constraint: Do not modify test assertions, only test setup if needed |
| Merge conflicts on feature branch | Long-running branch diverged from main | Keep sessions short; rebase before each new checkpoint |
| Devin introduces new dependencies | No constraint specified | Add No new dependencies to spec constraints |
Recommended Specification Template
# specs/TEMPLATE.md
Objective
[One-paragraph description of the refactoring goal]
Scope
- Include: [file globs]
- Exclude: [file globs]
Constraints
- [List non-negotiable rules]
Acceptance Criteria
- [Measurable outcomes]
Review Checkpoints
- CP-1: [trigger and scope]
- CP-2: [trigger and scope]
- CP-N: [trigger and scope]
Commands to Run
- After each file: [command]
After each checkpoint: [command]
FAQ
How many review checkpoints should I define for a multi-file refactoring task?
A good rule of thumb is one checkpoint per logical boundary in your codebase. For a typical refactoring spanning 10-20 files, three to five checkpoints work well: one after core modules, one after dependent modules, and one after tests and CI validation. Too few checkpoints risk compounding errors; too many slow down the workflow unnecessarily.
Can Devin handle refactoring across multiple programming languages in one session?
Yes, but it is best practice to create separate specification documents and branches for each language boundary. For example, if your refactoring touches both TypeScript backend code and Python data processing scripts, delegate these as two separate Devin sessions with their own specs and checkpoints. This keeps reviews focused and reduces cross-language error propagation.
What should I do if Devin’s refactoring breaks the CI pipeline at a checkpoint?
Do not approve the checkpoint. Instead, share the CI error output directly in the Devin session with specific instructions to fix the failures. Include the exact error messages and file locations. Ask Devin to fix the issues and re-run the CI commands before re-submitting the checkpoint. If failures persist after two correction attempts, consider taking over manually for that specific file and letting Devin continue with the remaining scope.