Extraction stopped being the hard part
A few years ago, the first year of a mainframe modernization went to reading code. Teams paid specialists to trace COBOL (Common Business-Oriented Language) programs, job control language (JCL) and copybooks (shared COBOL files that define record layouts) until someone could say what the system did. Vendors now describe much of that reading as automated.
AWS Transform for mainframe, in Amazon Web Services' (AWS) June 2026 post on its Reimagine workflow, builds dependency graphs across programs, entry points and data stores, runs deterministic static analysis on each program (rule-based analysis of the source that gives the same result on every run, without executing it), and extracts business rules with a natural-language description and traceability back to source. It turns those rules into requirements with testable acceptance criteria.
International Business Machines' (IBM) watsonx Code Assistant for Z, built for IBM Z mainframes, covers similar ground: it maps mainframe applications and their dependencies, refactors COBOL and PL/I (Programming Language One) into modular business services, converts COBOL to Java with generative AI, and generates unit tests "to compare semantic equivalence" between the new Java service and the original COBOL.
General-purpose models are closing in from the other side. On 19 October 2026 OpenAI published new evaluations for coding in low-resource programming languages, COBOL migration among them. We cover what those results do and do not measure in our analysis of OpenAI's COBOL migration benchmark.
You can now get a fairly complete account of what the old system does. You still have to decide which parts of that account the new system is obliged to keep.
What the old system does is not the specification
The tempting shortcut is to treat the extracted behavior as the specification. That shortcut carries the old bugs, the retired workarounds and the accidental structure into the new codebase, now with fresh tests that lock them in.
Take a legacy banking application. Recovery tools and a careful team would surface facts like these:
| Recovered fact | What kind of fact it is | What to do with it |
|---|---|---|
| A COBOL program truncates a decimal value instead of rounding it | Observed behavior | Test that the new code matches, then confirm the financial rule the truncation is meant to implement |
| A legacy service reads the account database directly | Architectural implementation | Decide whether it was deliberate or incidental |
| The target architecture requires access through a storage adapter (one module that owns reads and writes to account data) | Reviewed engineering decision | Check new code against it with an enforceable rule |
| Customer data must stay in an approved jurisdiction | Deployment requirement | Check it with an authorized deployment control |
| A workaround exists for an interface that was retired years ago | Historical implementation | Review whether to remove it |
Each row needs a different owner and a different kind of check. The truncation may be a regulatory requirement, or it may be a defect that customers have absorbed for decades. The direct database read may be a performance decision someone defended in 1998, or a shortcut nobody reviewed. The rows also come from different sources with different authority: rows 1, 2 and 5 come out of the old code, row 3 from the target design, row 4 from regulation and contracts. An extraction tool sees only the first group, and it cannot tell you which of those behaviors are binding.
Observed does not automatically mean authoritative.
Recovering business logic is not recovering decisions
Business-rule extraction answers "what does this code do?" The modernization needs a second answer: "which of these behaviors did someone with authority decide to keep?" The two get confused because extracted rules look like decisions. They have a name, a description and a line of source.
The AWS post shows where the vendor tooling draws its line. Its traceability step maps every extracted rule to one of three dispositions: captured in the new requirements, not applicable (platform mechanics with no cloud equivalent), or delegated to a shared module. The key metric is "not accounted for = 0", which AWS presents as proof that no business logic was lost. That is a useful completeness check: every rule landed somewhere. The post does not describe a disposition for "this rule is a defect, change it", or say who assigns dispositions.
Our review of the research on reverse-engineering architectural decisions found the same split from the academic side. Recovering structure and function is mature. Recovering the reasons behind them is early, and model-generated decisions tend to describe the change and miss the rationale. A modernization program inherits that gap at scale: thousands of extracted rules and no record of which ones were intended.
For mainframes, extraction is a product category with established vendors and dedicated parsers. Buy it. The work this article is about starts once the extracted rules arrive and someone has to decide which of them the new system must honor.
Three labels before anything is rewritten
Before migration work starts, every recovered fact should carry one of three labels:
- Observed: the old system demonstrably does this. Evidence is code, a trace, a test or production data.
- Inferred: a tool, model or engineer proposes that this behavior reflects an intended rule. The evidence is attached, and nobody has signed off.
- Approved: a named owner has decided the new system must do this, or must deliberately do something different.
The research review makes the general case for labels like these, drawing on a September 2026 preliminary study by Karan, Dhar, Soliman and Vaidhyanathan in which a manual review of one model's extracted decisions found they often described the change but missed the rationale. For a modernization the point is narrower: only approved facts may become constraints the migration is checked against. Observed facts become parity tests, which check behavioral parity (the new code produces the same outputs as the old for the same inputs). Label them as such, so that a test failure on a known defect is a decision to make and not an automatic block.
From evidence to governing constraints
The labels describe a sequence. Each stage has a different output and a different owner, and skipping one is how bugs get promoted into the specification.
- System evidence. Source, JCL, schemas, batch schedules, production logs, incident history and whatever documentation survives. Collect it before anyone interprets it.
- Behavioral reconstruction. Extraction tools and engineers describe what the system does: rules, data flows, dependencies, edge cases. Output: observed facts with source traceability. This is the stage AWS Transform and watsonx Code Assistant for Z automate.
- Candidate decisions. For each observed fact that looks intended, someone writes a candidate: "interest calculations truncate to two decimal places", with the evidence and a proposed owner. Output: inferred decisions, none of them binding yet.
- Human adjudication. Owners accept, change or reject each candidate. Accepting the truncation rule means the new system keeps it. Changing it means the new system deliberately diverges and the parity test for that case is rewritten. Rejecting the retired-interface workaround means it is not migrated.
- Governing constraints. Accepted engineering decisions are written down in the decision corpus (the set of engineering decisions the team maintains) and, where a decision can be checked mechanically, given a rule. Business rules go into requirements and tests. Deployment requirements go to deployment controls.
- Migration execution. Engineers and coding agents rewrite the system against those constraints. This is the stage our article on AI-assisted software migrations and architectural drift covers.
- Differential tests and decision-linked evidence. Old and new systems run side by side. Each divergence is explained by an approved change or treated as a defect, and each approved decision has evidence that the new code follows it.
Stage 2 is well tooled, and vendors have started on stage 7: IBM's tool generates unit tests to compare the new Java service with the original COBOL. Stages 3 to 5 are where modernization programs lose information, because they are organizational work that looks like a technical step.
Who authorizes a changed business rule?
Suppose the team finds that the truncation produces a fraction of a cent of difference against the documented rounding policy on some accounts. Matching the old behavior exactly keeps every downstream reconciliation stable. Fixing it brings the system in line with policy and changes balances. An engineer cannot make that call alone, and neither can a model.
Decide before the program starts who owns each class of fact:
- Business rules (calculations, eligibility, limits): a business owner, usually with finance, risk or compliance sign-off for anything that changes customer outcomes.
- Engineering decisions (boundaries, data access paths, dependencies): the architecture or platform owner for the target system.
- Deployment requirements (residency, availability, segregation): whoever owns the deployment controls, often security or infrastructure.
- Historical workarounds: the owner of the interface or process the workaround served. If that owner no longer exists, the default should be removal with a test, not silent preservation.
Write the approval down with the decision: who approved it, when, and what evidence they saw. A rule without a recorded approver will be re-argued at cutover, when the cost of changing it is highest.
When the sources disagree
Recovered facts conflict. The code truncates; the product manual says it rounds; a 2011 change request says rounding was approved and never implemented; the operations team says customers were compensated manually for years. None of these sources settles the question on its own.
Three conventions keep conflicts from stalling the program:
- Record the conflict, not a winner. The candidate decision lists every source and what each says. An extraction tool or model that silently picks one has made an approval decision without authority.
- Ask the current owner, not the oldest document. A document is not binding because it is old or because it is the only one. It is binding if the person who owns that rule today confirms it.
- Time-box adjudication. Unresolved conflicts default to behavioral parity, labelled as unadjudicated, so the migration can proceed without treating the old behavior as approved.
What can be automated
Most of the pipeline can. Adjudication cannot, and should not look as if it can.
| Stage | Automation |
|---|---|
| Evidence collection and behavioral reconstruction | Largely automated by vendor tools and models today |
| Drafting candidate decisions | A model can draft them with evidence attached; expect missing rationale |
| Detecting conflicts between sources | Automatable once sources are linked to the same candidate |
| Adjudication | Human. Tools can route candidates to owners and record the outcome |
| Checking code against approved engineering decisions | Deterministic where the decision has a machine-checkable rule |
| Differential testing | Automated, with each divergence routed back to an owner |
The order of the adjudication row and the checking row matters. A deterministic check is only as good as the decision behind it. If an inferred decision gets a rule before anyone approves it, the migration is blocked by a guess.
After adjudication: governing the migration itself
Once approved decisions exist, the migration itself raises a different set of problems: agents copy the legacy patterns they see most often, transitional adapters outlive their purpose, and the same rule must apply to migrated code but not to code the migration has not reached. Our article on AI-assisted software migrations and architectural drift covers that stage. This piece is about the stage before it: deciding what the migration is obliged to preserve.
Where Mneme fits, and where it does not
Mneme, an open-source decision and control layer for agentic software development, covers a narrow part of this sequence today. It does not compete on extraction: AWS and IBM already do that, with mainframe parsers Mneme does not have. Most of what Mneme could add beyond enforcement is design direction or research.
Shipped in mneme-hq 0.10.0 (Mneme's open-source package, current released version). Teams record engineering decisions, such as "target services reach account data only through the storage adapter", as architecture decision records (ADRs) and import them into the Decision Index, Mneme's persisted record of each decision's versions, lifecycle status and, where known, source.
Decisions that carry an active typed rule (a machine-checkable rule attached to the decision, such as a forbidden import) are enforced deterministically in supported coding agents (Claude Code, Codex CLI and Kiro among them) and in continuous integration. Each check returns a verdict of PASS, WARN or FAIL, and only a violation names the decision. A rule can carry path selectors (file path patterns that limit where it applies), so a team can apply the adapter rule only to the target tree. The Decision Index does not record who approved a decision, so the approval record from the adjudication stage has to live in the ADR or in the team's own process.
Not claimed. Mneme does not parse COBOL or integrate with mainframe tooling. It does not extract business rules or execute financial rules. It does not check data residency; that belongs to deployment controls, though the residency requirement can be written down as a decision record so the reason stays attached to the system.
Planned design direction. Distinguishing observed, inferred and approved decisions with provenance is part of Mneme's design direction for engineering decision governance. The design is accepted and not released.
Conceptual. Recovering candidate decisions from legacy systems, and linking differential test results to the decisions they evidence, are research questions. Mneme has a research-only test setup for running recovery experiments; there are no results to report yet.
Before the first module is rewritten
- Buy extraction, don't build it. Vendor tools already reconstruct behavior with source traceability. Put your effort into what happens to their output.
- Label every recovered fact. Observed, inferred or approved, with evidence attached. Make parity tests say which facts they are protecting.
- Name an owner per class of fact before the first conflict arrives, including who can approve a changed business rule.
- Turn only approved engineering decisions into rules. Send business rules to tests and residency to deployment controls.