deployment
Agentic Planning For Cross Package Refactors Production Playbook: practical systems guide
Technical field guide on agentic planning for cross package refactors production playbook for teams building dependable AI coding workflows.
# Agentic Planning For Cross-Package Refactors: Production Playbook
Cross-package refactors fail because humans underestimate dependency graphs and AI agents overfit to local context. You rename a function in `shared-auth`, regenerate twenty import sites, then discover the mobile SDK vendors that module into a native bridge where your types don't serialize. The agent never saw the bridge. You spend two days unwinding.
The solution isn't stronger models or bigger context windows—it's upfront constraint mapping. Before any agent touches code, you need a planning phase that surfaces every boundary your refactor will cross: package exports, API contracts, generated artifacts, deployment topology. This post walks through the systems architecture for agentic planning that actually ships cross-package changes to production.
Why planning is the bottleneck, not editing
AI coding agents are excellent at local transformations. Given a clear instruction and a single file, they'll rename symbols, update tests, adjust imports. The failure mode appears when the instruction requires coordinating changes across compilation units that have different stakeholders, release schedules, or runtime environments.
Traditional refactoring tools solve this with static analysis—build a global call graph, perform a transitive rename, done. But that approach assumes homogeneous codebases: one language, one build system, one deployment artifact. Real engineering orgs have polyglot services, vendored dependencies, mobile apps that bundle web views, infrastructure-as-code repos that template from application schemas.
An agent working file-by-file will miss these boundaries. You need a planning step that explicitly enumerates:
- **Package boundaries**: which `package.json` / `go.mod` / `Cargo.toml` files define compilation scopes
- **API surfaces**: REST routes, GraphQL schemas, protobuf definitions, public library exports
- **Generated code**: ORM models, API clients, type definitions emitted by code-gen pipelines
- **Cross-repo dependencies**: submodules, vendored copies, internal package registries
Only after mapping these can you decide whether a refactor is a safe single-PR change or requires a multi-phase rollout with compatibility shims.
The constraint collection phase
Before prompting any agent to edit code, run a constraint collection pass. This is a separate script or pipeline step that walks your repository structure and outputs a dependency manifest.
For a typical monorepo with multiple packages:
# Enumerate all package roots
find . -name 'package.json' -o -name 'go.mod' -o -name 'Cargo.toml' \
| xargs -I {} dirname {}
# For each package, extract exports and dependencies
# Then build a JSON map of { package -> { exports, imports, consumers } }
The manifest should answer:
- If I change a symbol in package A, which packages import it?
- Does this symbol appear in any serialization boundaries (JSON schemas, API specs)?
- Are there generated artifacts that derive from this package's types?
This sounds like heavy static analysis, but you don't need perfect precision. A conservative overapproximation—flagging any file that references the symbol string—is sufficient. The goal is to prevent the agent from missing an entire subsystem, not to compute exact dataflow.
Decomposing the refactor into constrained subtasks
Once you have the dependency map, decompose the refactor into a sequence of isolated edits, each with explicit constraints.
For example, renaming `AuthService.validateToken()` to `AuthService.verify()` might decompose to:
1. **Update the definition** in `packages/auth/src/service.ts`
Constraint: must preserve function signature, only rename
2. **Update call sites** in same package tests
Constraint: no new imports, only rename invocations
3. **Update API layer** in `packages/api/src/routes/auth.ts`
Constraint: preserve HTTP contract, internal refactor only
4. **Update generated client** in `clients/typescript/`
Constraint: regenerate from OpenAPI spec, do not hand-edit
Each subtask goes to the agent loop (plan → constrain → edit → validate → retry) with these constraints enforced at the validation gate. The agent cannot produce a diff that violates the constraint—if it tries to change the HTTP response shape in step 3, the OpenAPI contract test fails and the agent must retry.
This is where Goatfied's compile-first model helps: every edit is gated by linters, type checkers, and unit tests before it reaches review. An agent that tries to rename a function without updating its test mocks will fail the test suite and get a fresh chance to fix it, never polluting your PR with broken intermediates.
Handling cross-repo boundaries
The hardest case is when your refactor spans repositories. Internal package consumers, mobile apps that vendor your SDK, infrastructure repos that import your service's protobuf definitions.
You have two options:
**Option 1: Compatibility shim**
Keep the old API surface as a thin wrapper during a transition period. Add both `validateToken()` and `verify()`, mark the former deprecated, ship the change, then remove it in a follow-up once consumers migrate.
**Option 2: Coordinated multi-PR release**
Update all repos simultaneously. This requires the agent to produce multiple PRs—one per repo—then orchestrate their merge order.
For option 2, structure the plan as a DAG: nodes are PRs, edges are "must merge before" dependencies. The agent generates each PR independently, but your deployment tooling enforces the merge order. If repo B depends on repo A's new export, B's PR stays in draft until A merges and publishes.
Validation gates that catch integration failures
The core idea: every agent edit must pass automated checks that prove it respects package boundaries.
Minimal gate set:
- **Compile/typecheck**: obviously
- **Unit tests**: including mocks that exercise the renamed symbol
- **Contract tests**: if you touched an API surface, regenerate client fixtures and verify serialization
- **Dependency graph check**: re-run the constraint collection script and diff against the original manifest—if new unexpected edges appeared, fail
In Goatfied's workflow, these gates run after every edit attempt. If the agent produces a diff that breaks tests, the validate step surfaces the error message, and the agent retries with that feedback. Small, reversible diffs mean failures are cheap: the agent isn't trying to fix a 2000-line changeset, it's adjusting a single import statement.
When to bail out to human review
Some refactors are genuinely too complex for full automation. Signals to escalate:
- The dependency graph shows cycles (mutual imports between packages that both need updates)
- Generated code is hand-edited downstream (your API client was templated but then customized)
- No automated tests cover the integration boundary
- The refactor requires semantic changes, not just renames (e.g., splitting one function into two with different error handling)
In these cases, have the agent produce a draft PR with detailed comments explaining what it couldn't safely complete. A human takes over, but with 80% of the mechanical work done and a clear map of the remaining risk areas.
Practical rollout: start with single-package scope
If you're adopting agentic planning today, don't start with cross-repo refactors. Begin with:
1. **Single-package renames**: stay within one `package.json` boundary, let the agent learn your test patterns
2. **Add constraint validation**: wire up the compile/lint/test gates so failures surface immediately
3. **Gradually expand scope**: multi-package within the same monorepo, then coordinated cross-repo
Track how often the agent succeeds on first attempt vs. requires retries. If retry rates stay high, your constraints are either too loose (agent makes invalid edits) or your tests don't cover integration points (agent produces diffs that break things downstream but pass local checks).
Related reading
- [Self-hosted AI coding assistants: a complete Goatfied deployment guide](/blog/self-hosted-ai-coding-assistants-goatfied-deployment-guide)
- [Deployment playbook #2: practical Goatfied tactics for shipping PRs](/blog/goatfied-deployment-playbook-2)
