What is The Legacy Integrator?

The Legacy Integrator is a 3-step prompt flow for the hardest common software engineering scenario: adding a feature to a codebase you didn't write, with unclear documentation, hidden coupling, and real consequences if you break existing behavior. It chains TRACE to map the existing system as a constrained actor before writing a line, Tree of Thoughts to branch and evaluate multiple integration strategies against the legacy constraints, and RISEN to implement the safest approach within hard scope boundaries.

The flow addresses the core failure mode of legacy integration: treating the existing codebase as malleable when it isn't. Understand constraints first, explore integration paths second, narrow implementation scope third.

When to Use The Legacy Integrator

🏚️

Inherited Codebases

Adding features to a system you inherited — where the original developers are gone and documentation is sparse or outdated.

🔧

Monolith Extensions

Extending a monolithic application without triggering cascading changes across the existing module graph.

🧩

Third-Party System Integration

Integrating a new service into an existing system where the integration point is tightly coupled to business logic.

📦

Dependency Upgrades

Upgrading a major dependency that requires changes to multiple call sites in a codebase you don't fully understand.

🔀

Cross-Team Contributions

Contributing to another team's service or library where breaking their API contracts would block their deployments.

🗃️

Database Schema Changes

Adding columns or tables to a legacy database schema where existing queries and migrations must remain intact.

The Flow Algorithm

1

TRACE — Map Legacy Constraints

Before planning any change, use TRACE to reason about the existing system as a constrained actor: Task (what the system currently does), Request (what you need to add), Action (what the system expects at each integration point), Context (the hidden coupling, data contracts, and behavioral guarantees the codebase relies on), Example (a concrete trace of how data flows through the relevant code paths today). Focus the Context section on what must not change, not what exists in general.

Produces:

A constraint map of the legacy system: coupling points, behavioral contracts that must be preserved, risk zones where changes propagate unexpectedly, and the data flow trace your new feature must work within.

2

Tree of Thoughts — Branch Integration Paths

Feed the constraint map from Step 1 into a Tree of Thoughts prompt. Generate at least three distinct integration strategies — for example: (A) add a new module with minimal coupling, (B) extend an existing class with a new method, (C) intercept at the service boundary. For each strategy, evaluate: does it preserve the behavioral contracts from Step 1? What does it require to change? What is the regression risk? Prune approaches that violate legacy constraints before selecting the winner.

Produces:

A ranked evaluation of integration strategies with explicit compatibility analysis against the legacy constraints from Step 1. The output is a justified selection of the safest approach, not the most elegant one.

3

RISEN — Implement Within Hard Boundaries

Implement the chosen integration strategy using RISEN, with the Narrowing parameter doing critical work: list every file, interface, and method signature that must NOT be modified. Include the behavioral contracts from Step 1 as explicit constraints. The Role should be "senior engineer who understands legacy systems and prefers additive changes over modifications." The End Goal must include characterization tests for all code paths touched.

Produces:

A bounded, scope-limited implementation of the new feature that adds functionality without modifying legacy contracts — plus characterization tests that document and protect the existing behavior.

Example Prompt Sequence

Step 1 — TRACE Legacy Analysis

Analyze the following legacy codebase using TRACE:

Task: What does the current user authentication system do? Map every behavior, data contract, and assumption.
Request: I need to add OAuth2 login alongside the existing username/password login — without changing how existing sessions work.
Action: Identify every integration point where the new OAuth flow must interact with the existing auth system.
Context: What MUST NOT change — existing session tokens, the User model schema, the /login endpoint contract, any code that reads req.user?
Example: Trace the exact data flow for a current successful login: from POST /login → through middleware → to session creation → to how req.user is populated in downstream routes.

[PASTE RELEVANT CODE SECTIONS HERE]

Step 2 — Tree of Thoughts Integration Strategies

Evaluate three distinct strategies for adding OAuth2 login to this legacy auth system. For each strategy:
1. Describe the approach
2. List every file and method that would need to change
3. Assess: does it preserve the behavioral contracts mapped in Step 1? (session format, User schema, req.user shape)
4. Rate the regression risk: High / Medium / Low, with reasoning
5. Identify the first thing that would break if this approach has an edge case

Constraint map from Step 1:
[PASTE STEP 1 OUTPUT HERE]

After evaluating all three, recommend the safest approach — not the most elegant — and explain why.

Step 3 — RISEN Scoped Implementation

Role: Senior engineer who specializes in adding features to legacy systems with minimal risk. You prefer additive changes over modifications, and you treat behavioral contracts as hard constraints.
Instructions: Implement the OAuth2 integration strategy selected in Step 2.
Steps: 1) New OAuth route handler (additive, new file), 2) OAuth callback that creates a session in the existing format, 3) Characterization tests for all existing auth paths, 4) Integration test for the new OAuth flow.
End Goal: OAuth2 login works alongside existing login. All existing auth tests pass unchanged. New characterization tests document legacy behavior.
Narrowing: Do NOT modify: User model schema, session middleware, /login endpoint, req.user shape, or any existing test files. All new code goes in /auth/oauth.js and /tests/oauth.test.js only.

Selected strategy from Step 2:
[PASTE STEP 2 RECOMMENDATION HERE]

Pros and Cons

Strengths

  • TRACE constraint mapping prevents unknown behavioral contract violations
  • Tree of Thoughts ensures you don't commit to the first approach
  • RISEN narrowing creates hard scope boundaries that prevent drift
  • Produces characterization tests as a by-product
  • Works in any language or framework

Trade-offs

  • More prompts and time than a direct "add this feature" approach
  • Requires pasting significant legacy code context into each step
  • Tree of Thoughts evaluation can be verbose — requires careful reading
  • Overkill for well-documented, well-tested, actively maintained codebases

Frequently Asked Questions

What is The Legacy Integrator prompt flow?

The Legacy Integrator is a 3-step prompt flow that chains TRACE, Tree of Thoughts, and RISEN to help you add features to codebases you didn't write without breaking existing behavior. It maps legacy constraints before planning, explores all integration paths against those constraints, then implements the safest approach within hard scope boundaries.

Why use TRACE to analyze legacy code instead of just asking for an analysis?

TRACE forces a structured response covering Task, Request, Action, Context, and Example — which means the model must reason about the existing system as a constrained actor with specific goals, not just summarize the code. This produces coupling maps, behavior contracts, and risk zones rather than a generic code description, which is what you need before touching legacy code.

Why explore multiple integration paths before implementing?

In legacy codebases, the first integration approach that comes to mind is often not the safest one — it's the one that ignores the hidden coupling your analysis revealed. Tree of Thoughts forces the model to generate and evaluate at least three distinct integration strategies, each assessed against the constraints from Step 1. You commit to the approach that best preserves existing behavior, not the one that's most obvious.

What does RISEN add for legacy integration that other frameworks don't?

RISEN's Narrowing parameter is critical for legacy work. It lets you explicitly constrain the implementation: no changes to files outside these boundaries, no modifications to these interfaces, preserve these exact method signatures. This prevents the common failure where the model generates a clean solution that also refactors 15 surrounding functions you weren't supposed to touch.

How do I handle cases where the legacy code has no tests?

In Step 1 (TRACE), include a specific request to identify all code paths and data contracts that your change must preserve, even without tests. In Step 3 (RISEN), add to the Narrowing: 'Generate characterization tests for all touched code paths before implementing the feature.' This makes the absence of tests a constraint to fill, not a gap to ignore.

Is this flow suitable for modernization or migration work?

For incremental modernization (adding new features while gradually improving the codebase), yes — the RISEN narrowing keeps you from accidentally doing a full refactor. For large-scale migrations, consider The Code Architect instead, which is designed for greenfield architectural work. The Legacy Integrator is specifically optimized for the 'add a feature and get out' scenario.