Before an AI Rewrites Legacy Code, Build a Parity Gate An engineer published a source-based guide arguing that teams should build a parity gate—running identical representative inputs through legacy and rewritten implementations and comparing outputs—before letting AI agents replace legacy code behavior. The piece cites Cisco president Jeetu Patel's reported challenge to a 27-year-old engineer to rewrite 98% of Cisco's legacy code in 24 months with unlimited AI tokens, while noting the public coverage describes an ambition and four-week proof of concept, not completed results. The guide recommends starting with bounded, deterministic behaviors and treating process errors as failures rather than skipping them. A team can generate a new implementation faster than it can decide whether the new implementation is still the same product. That is the important tension behind a report that Cisco president Jeetu Patel gave a 27-year-old engineer unlimited AI tokens and a goal to rewrite 98% of Cisco's legacy code within 24 months, with a four-week proof of concept. The account comes from Fortune reporting summarized by Tom's Hardware https://www.tomshardware.com/tech-industry/big-tech/cisco-gives-27-year-old-engineer-unlimited-ai-tokens-to-rewrite-98-percent-of-the-companys-legacy-code-in-24-months-president-plucks-former-startup-founder-telling-him-to-go-nuts . The headline is striking. The engineering problem underneath it is less glamorous: how do you know a rewrite still does what users and dependent systems expect? This article is a source-based engineering guide, not a report from a Cisco project or a hands-on legacy migration. The public coverage describes an ambition and a proof-of-concept window, not completed results. It does not establish that 98% has been rewritten, that the effort will meet the deadline, or that token supply is the limiting factor. The useful takeaway is a method you can apply to a small, reversible change: create a parity gate before asking an agent to replace behavior. A legacy system often has no single complete specification. Its behavior is distributed across code, database constraints, production data, integrations, error handling, and assumptions that nobody wrote down. A rewrite can look cleaner and still change a default, rounding rule, ordering guarantee, or failure mode that another system depends on. The first question is not, “Can an agent reproduce this function?” It is, “What observable behavior must remain stable, and what evidence would show that it changed?” The distinction is practical. A test that merely calls the new code and checks that it returns a plausible value proves little about equivalence. A parity test runs the same representative inputs through the old and new implementations and compares the outcomes. A reviewer can then inspect disagreements instead of trying to infer correctness from a large diff. Microsoft's guidance for migrating AI agents recommends defining acceptance gates before a model change, capturing a baseline from the current system, using the same test data and environment assumptions for both versions, and investigating individual regressions rather than trusting an average score. Those ideas apply just as well to a code rewrite. See Microsoft's migration-validation guidance https://learn.microsoft.com/en-us/microsoft-copilot-studio/guidance/manage-agent-model-migration . For coding-agent work, Visual Studio Code's testing guide https://code.visualstudio.com/docs/agents/guides/test-code-with-ai also says to preserve assertions, report what ran, and treat unrun tests as unverified. Start with a behavior that is bounded, deterministic, and important enough to matter. A pricing rule, date conversion, permission decision, or serialization function may be a better first slice than an entire service. Do not begin with the hardest code in the repository. Begin with a seam where you can call both implementations under controlled conditions. For illustration, imagine an old and new implementation that both accept JSON inputs and return JSON results. The harness below reads one case per line, sends each input to both commands, and records exact output mismatches. It intentionally treats a process error as a failure rather than silently skipping it. bash /usr/bin/env python3 """Compare legacy and candidate commands on newline-delimited JSON cases.""" import json import subprocess import sys from pathlib import Path CASES = Path sys.argv 1 OLD COMMAND = "python3", "legacy impl.py" NEW COMMAND = "python3", "candidate impl.py" def run command, case : completed = subprocess.run command, input=json.dumps case , text=True, capture output=True, check=False, timeout=10, if completed.returncode = 0: raise RuntimeError f"{command 1 } exited {completed.returncode}: " f"{completed.stderr.strip }" return json.loads completed.stdout def main : cases = json.loads line for line in CASES.read text .splitlines if line mismatches = for index, case in enumerate cases, start=1 : old = run OLD COMMAND, case new = run NEW COMMAND, case if old = new: mismatches.append {"case": index, "input": case, "legacy": old, "candidate": new} print json.dumps { "cases": len cases , "mismatches": len mismatches , "details": mismatches, }, indent=2, sort keys=True return 1 if mismatches else 0 if name == " main ": raise SystemExit main Save representative inputs in cases.jsonl , one JSON object per line, then run python3 parity.py cases.jsonl . Replace the two command arrays with real, isolated entry points. The example is intentionally strict: if the output formats differ, the harness reports a mismatch. Normalize only fields that are genuinely nondeterministic, and document each normalization so it cannot hide a meaningful regression. This small script is not a migration framework. It is a starting gate. Production systems may need database snapshots, service stubs, message queues, feature flags, and stronger isolation. The key is that each version sees the same input and that you retain the evidence for every comparison. A collection of ordinary happy-path examples is not a useful characterization set. Include cases that make hidden behavior visible: Do not ask an agent to invent the expected result for every case and then treat its own answer as the oracle. Where possible, derive expected outcomes from existing tests, approved requirements, recorded behavior, or a domain owner. When the old implementation is the reference, it can reveal current behavior, but it cannot tell you whether that behavior is correct. Mark known defects as exceptions with an explicit decision rather than preserving them accidentally. A raw “17 tests failed” message is not enough. Each mismatch should show the input, the old output, the candidate output, and a stable case identifier. Group related mismatches by behavior: rounding, validation, authorization, serialization, and so on. A reviewer can then decide whether a difference is a bug, an intended improvement, or an old defect that should not be carried forward. Keep three outcomes distinct: Never turn a mismatch into a pass by weakening the test just to make the candidate green. Microsoft's guidance explicitly recommends investigating individual regressions rather than relying on an aggregate rate. A 99% pass rate can conceal the one authorization or billing case that matters most. A coding agent can help inventory call sites, propose test cases, explain mismatches, and implement a candidate behind a feature flag. Those are useful tasks. It should not be allowed to change the acceptance criteria and approve its own output in the same unreviewed step. A safer task boundary looks like this: This also makes “unlimited tokens” less important as a planning metric. More generation can increase the amount of code to inspect. The scarce resource may be trustworthy test cases, time from domain owners, or a review path that catches an unintended behavior change. That is an engineering inference, not a reported finding about Cisco's internal project. Before replacing a legacy component, ask: A parity harness is not proof that a rewrite is safe. It is a way to turn a vague claim of equivalence into inspectable evidence. It tells you where to focus human attention, and it makes the decision to proceed, pause, or roll back more concrete. The public Cisco account is a striking example of how AI changes the perceived cost of attempting a large rewrite. But a deadline and token budget are not evidence of preserved behavior. Until results are independently reported, the 98% figure belongs to the stated ambition, not the outcome. For an engineering team considering a similar effort, begin with one narrow behavior and a fixed corpus. Make the old and new outputs comparable. Let the agent help produce the candidate, but keep the contract, mismatch decisions, and promotion gate reviewable by people responsible for the system. Expand only when the gate catches the kinds of mistakes you care about and the rollback path has been exercised. I write about software engineering, developer tools, and practical AI workflows. Subscribe if you want more guides like this. Have you used a parity harness for a rewrite or migration? What behavior did it catch that ordinary unit tests missed?