COBOL modernization intelligence

We build the map of your codebase before touching a single line.

Most modernization projects fail because tools read code as text, not topology. CodeGraph parses your mainframe estate into a typed knowledge graph and resolves the full transitive dependency closure of a change, across copybooks, REDEFINES, COMP-3, DB2, and JCL, with file:line provenance for every edge and a proof of how much it could resolve. The map is the product. Translation is a downstream use case.

9/9 vs 3/9

Dependencies recovered: graph vs single-file window

On the TRN-LIMIT fixture, against a known ground-truth set

97.1%

References resolved (33 of 34), 1 flagged for review

Deterministic completeness gate, same result every run

47 / 70

Nodes and edges across 7 node types

The shipped synthetic bank fixture

This is a runnable demo. The estate is synthetic and authored for the demo, the graph is in-memory plus SQLite, and the DB2, JCL, and naive single-file views are file fixtures and simulations, not live connectors.

Modernization fails at understanding, not translation

The failure mode is contextual blindness, and a bigger model does not remove it.

70 to 80% of mainframe modernization projects fail to meet their objectives (industry meta-analysis, 2025). Not because the translation is wrong, but because the tools treat code as text instead of topology. A commodity translator reads the one file it can see. The fact that actually matters is invisible in a single-file context window.

The stakes are not academic. Roughly 220 billion lines of COBOL still run in production, carrying about 95% of ATM transactions, 43% of banking systems, and 3 trillion dollars of activity a day (Reuters, 2017), against an estimated 1.52 trillion dollars of accumulated US technical debt (CISQ, 2022). This is the core of the banking and insurance stack, and it is exactly the code no one wants to touch blind.

The concrete parable is a wire-transfer program that computes on a field called TRN-LIMIT. In the one file a translator can see, the arithmetic looks trivial. But TRN-LIMIT is a COMP-3 packed decimal defined three copybooks away, its interpretation is chosen by a flag set in a different program, and that flag is written by a 2 a.m. JCL batch job that runs before the wire job. Handed only the visible facts, a model emits a plain long, the Java compiles, passes unit tests, and then corrupts the database on the first live wire transfer. That referential-integrity failure surfaces in UAT. The failure was contextual blindness.

This does not age out as models improve. A real estate is 1 to 10 million lines or more and does not fit in any context window, present or future. The hard part is retrieving the exact transitive slice a change touches and proving you found all of it. That is a topology, retrieval, and evidence problem, not a reasoning-quality problem. Agents advise, code decides.

How CodeGraph works

Parse the estate into a typed graph, then run deterministic analyses. No LLM sits in the critical path.

The pipeline runs Fixture estate, then parse (COBOL, copybooks, JCL, DB2 DDL), then build a typed knowledge graph, then transitive-closure impact plus provenance, then the deterministic analyses, then an audit and evidence export, then the interactive dashboard. On load the app runs this live over Server-Sent Events, so each stage narrates with its real measured latency in a console, panels fill progressively, and a persistent stage rail lets you open any stage's Input, Processing, and Output trace. A single control replays the whole run.

The CodeGraph interface running its live analysis pipeline over the WIRETXN program, with per-stage latency shown in the console: scan, parse, build graph, impact closure, recover facts, and plan and audit.
The live pipeline: scan, parse, build graph, impact closure, recover facts, and plan and audit, each stage with its real measured latency.

The typed knowledge graph

Built with networkx and held in-memory plus SQLite, the graph has seven node types (program, copybook, variable, table, jcl, dataset, and an unresolved placeholder) and typed edges such as DEFINES, IMPORTS, REDEFINES, CONTROLS_TYPE_OF, WRITES_VAR, REFERENCES, CALLS, READS and WRITES, EXECUTES, USES_DATASET, and PRECEDES. On the shipped fixture the graph has 47 nodes and 70 edges: 14 programs, 5 copybooks, 17 variables, 3 DB2 tables, 3 JCL jobs, 4 datasets, and 1 unresolved node.

Four deterministic analyses

These are plain graph algorithms, not model calls, so the same fixture yields the same result every run.

1. Impact closure with provenance

The transitive dependency slice of a change, with each edge carrying its file:line source, so you can see not just what is affected but where the evidence lives.

2. Naive versus graph recall

The graph's closure scored against the fixture's known ground-truth dependency set, versus a simulated single-file window, which is what a text-based tool actually feeds a model.

3. Extraction sequencing

A coupling and blast-radius score per program (coupling weighted three, COMP-3 traps weighted two, JCL criticality weighted two, unresolved calls weighted five) that ranks a safe strangler-fig migration order.

4. Dead-code reachability and completeness gate

Every PERFORM, CALL, COPY, and DB2 reference must resolve or be flagged as needs review, never silently dropped. Unreachable paragraphs are reported as an illustration, not scored as a headline metric.

One toggle makes the difference tangible. Tick the naive AI context view and the graph dims to the single source file with a few lines of context. Six of the nine wire-transfer facts vanish, a red banner states the consequence, and flipping back restores 9/9 with receipts. That toggle is an illustration of what context the retrieval layer must supply, not the source of value.

When you are done, Export JSON writes a migration-evidence.json file, and Evidence report renders a printable Codebase Topology and Completeness Report: the node and edge summary, per-module closures with file:line provenance, the recall result and method, the ranked extraction sequence, the dead-code list, and a timestamp. We position that as a DORA ICT-asset inventory and a SOC-2 change-control receipt. An optional Pydantic-AI layer can answer questions over the closure, but it is off by default and key-gated, and the deterministic demo records the result without any key.

The TRN-LIMIT wire-transfer closure, worked end to end

One change on one field, resolved against a known ground-truth set. Every image below is a screenshot of the running app.

Nine facts, and six a single file cannot see

The default view lands on the wire-transfer subsystem with TRN-LIMIT selected. The impact panel shows graph retrieval at 9/9 (100%) against a naive single-file context of 3/9 (33%), scored against the fixture's known ground-truth dependency set. Three facts are visible in the one file: WIRETXN uses TRN-LIMIT in a COMPUTE (WIRETXN.cbl:33), copybook CBACCT is imported by name (WIRETXN.cbl:13), and an UPDATE on DB2 table ACCOUNTS occurs (WIRETXN.cbl:37). The six that decide correctness are not: TRN-LIMIT is a PIC S9(9)V99 COMP-3 packed decimal that must become a BigDecimal and not a long (CBACCT.cpy:11), TRN-LIMIT-ALPHA REDEFINES it as text over the same six bytes (CBACCT.cpy:12), LIMIT-TYPE-FLAG decides which interpretation is live (CBACCT.cpy:13), two programs (LIMITSET and BATCHUPD) write that flag, and the JCL job NIGHTLY at 02:00 runs before WIREJOB so the flag is set before the wire runs.

The TRN-LIMIT impact panel: graph retrieval 9/9 versus naive single-file 3/9, with facts F1 to F3 marked in-file and F4 to F9 marked hidden and critical or high, each carrying its file:line provenance.
Graph retrieval 9/9 versus naive single-file 3/9. The three visible facts are in-file; the six that decide the type are hidden from a single-file view, each with file:line provenance.

The money beat: flip to a single-file window and watch six facts vanish

Tick the naive AI context view and the graph dims to what lives inside WIRETXN.cbl. The COMP-3 type, the REDEFINES overlay, the controlling flag, its two cross-module writers, and the 02:00 JCL predecessor all grey out, and a red banner states the consequence: handed only the three visible facts, a model emits a plain long TRN_LIMIT and writes corrupted bytes into ACCOUNTS.TRN_LIMIT, which is the UAT failure. This is the exact contextual-blindness gap a text-window tool structurally cannot close, made visible in one click.

The naive single-file context view: a red banner explains that only 3 of 9 facts live inside WIRETXN.cbl, and facts F4 to F9 are greyed out, including the COMP-3 type, the REDEFINES overlay, the controlling flag, and the 02:00 JCL predecessor.
The naive single-file view: six facts dim out and a red banner states the resulting production failure. Flip back and 9/9 returns with receipts.

A safe order of extraction, ranked by blast radius

The extraction view ranks all 14 programs by a coupling and blast-radius score. AUDITLOG is the safe first extraction at rank 1 with a risk score of 0 and zero coupling. WIRETXN sits at rank 11 (risk 4, one COMP-3 trap plus JCL criticality). DISPATCH ranks 12 (risk 5) for its unresolved dynamic CALL, and the god-program ACCTMGR extracts last at rank 14 (coupling 5, risk 15). That is a strangler-fig order you can defend, lowest risk first, highest coupling last.

The extraction sequence table ranking 14 programs by coupling, COMP-3 traps, JCL criticality, and risk score, with AUDITLOG first at risk 0 and the god-program ACCTMGR last at risk 15, next to a legacy-to-modernized diff view.
The strangler-fig order: AUDITLOG first at risk 0, ACCTMGR last at risk 15, with the reason for each rank shown in the coupling, traps, and JCL columns.

A completeness gate that flags what it cannot resolve

The audit tab reports 97.1% of references resolved, which is 33 of 34, with exactly one flagged for review and not silently dropped. That one is DISPATCH's dynamic CALL WS-PROGNAME, whose target is computed at runtime (DISPATCH.cbl:15) and so cannot be resolved statically. The tab also lists dead code by reachability: AUDITLOG's LEGACY-FORMAT paragraph and WIRETXN's OLD-LIMIT-CHECK paragraph are unreachable. Refusing to fake a resolution is the honest behavior, and it is the behavior a regulator wants to see.

The audit tab showing 97.1% references resolved and 1 flagged for review, with the DISPATCH dynamic CALL WS-PROGNAME called out as flagged not silently dropped, and a dead-code list naming AUDITLOG LEGACY-FORMAT and WIRETXN OLD-LIMIT-CHECK.
97.1% resolved, 1 flagged. The unresolvable dynamic CALL is marked for review, not dropped, and the dead-code list is reported alongside.

An exportable audit artifact

Everything above exports to a printable Codebase Topology and Completeness Report: the 47-node, 70-edge summary, the 97.1% coverage, the nine TRN-LIMIT dependency facts with their single-file visibility and file:line provenance, the ranked extraction sequence, and a generation timestamp. Because the estate is synthetic and authored, the true dependency set is known by construction, which is what makes the recall figure a reproducible labeled measurement rather than a claim. We attribute 9/9, 3/9, and 97.1% to this shipped fixture, never as an open-world guarantee over arbitrary COBOL estates.

The printable Codebase Topology and Completeness Report showing 47 nodes, 70 edges, 97.1% references resolved, the TRN-LIMIT dependency facts F1 to F9 with single-file visibility and provenance, and the strangler-fig extraction sequence.
The exportable Codebase Topology and Completeness Report: node and edge summary, the nine dependency facts with provenance, and the ranked extraction sequence, positioned as a DORA ICT-asset inventory.

A single-file context window versus the graph

The same toggle the demo compares against, side by side, on the wire-transfer fixture.

Dimension Single-file context window CodeGraph knowledge graph
TRN-LIMIT dependencies recovered 3 of 9 9 of 9, against a known ground-truth set
COMP-3 type across copybooks Invisible Resolved with file:line provenance
REDEFINES overlay and controlling flag Invisible Resolved, including cross-module writers
JCL-only ordering edge (NIGHTLY before WIREJOB) Invisible Modeled as a PRECEDES edge
Completeness proof None 97.1% resolved, unresolved flagged for review
Safe extraction order None Ranked by coupling and blast radius
Audit artifact None Exportable topology and completeness report

What this demo does not do

  • ✓ It does not translate COBOL to Java. CodeGraph is the understanding layer, the map. Translation is a downstream use case it deliberately does not perform.
  • ✓ It does not use live connectors. The graph is in-memory plus SQLite, DB2, JCL, and scheduler inputs are file fixtures, and the naive single-file view is a simulated context window. Neo4j or Memgraph is the named production path, not shipped here.
  • ✓ It does not present the bank, its programs, or any numbers as a real customer's codebase. The estate is synthetic and authored for this demo. There is no case study and no deployment result.
  • ✓ It does not claim full IBM Enterprise COBOL dialect coverage. The parser covers a realistic synthetic subset, not every dialect, ALTER, or OCCURS DEPENDING ON, and it does not claim to beat any vendor's parser.
  • ✓ It does not present 9/9, 3/9, or 97.1% as open-world guarantees. They are measurements on the shipped synthetic wire-transfer fixture, whose ground-truth set is known by construction.
  • ✓ It does not carry customers, case studies, testimonials, or ROI figures. None exist yet. This is a demo that proves the mechanism.

Questions buyers actually ask

Is this a COBOL to Java translator?

No. CodeGraph is the understanding layer, not a translator, and it deliberately does not paste COBOL and emit Java. It builds a typed dependency graph of your estate and resolves the exact transitive slice a change touches, with file:line provenance and a completeness proof. Translation is a downstream use case, and every translation tool still needs this map to know what a change actually touches.

Won't a bigger context window or a better model just solve this?

No, and that is the durable point. A real estate is 1 to 10 million lines or more and does not fit in any context window, present or future. The hard part is retrieving the exact transitive slice and proving you found all of it, which is a topology, retrieval, and evidence problem, not a reasoning-quality problem. A perfect model still cannot prove to a regulator which dependencies were retrieved, still needs a safe extraction order, and still owes an ICT-asset inventory.

How do you prove you found every dependency for an auditor?

The completeness gate requires every PERFORM, CALL, COPY, and DB2 reference to either resolve or be flagged for review, never silently dropped. On the shipped fixture that is 33 of 34 references resolved, which is 97.1% coverage, with the one unresolvable reference flagged. You can export a printable Codebase Topology and Completeness Report with the node and edge summary, per-module closures with file:line provenance, the recall result and method, the ranked extraction sequence, and the dead-code list, positioned as a DORA ICT-asset inventory and a SOC-2 change-control receipt.

What happens with a dependency you cannot resolve, like a dynamic CALL?

It is flagged for review, not silently dropped, and that honesty behavior is the point. On the fixture the one unresolvable reference is DISPATCH's dynamic CALL WS-PROGNAME, whose target is computed at runtime (DISPATCH.cbl:15), so it cannot be resolved statically. CodeGraph records it as needs review and ranks DISPATCH near the end of the safe extraction order for exactly that reason.

Does this connect to our mainframe, DB2, or z/OS scheduler?

Not in this demo. The graph is in-memory plus SQLite, and the DB2, JCL, and scheduler inputs are file fixtures, while the naive single-file view is a simulated context window. A production deployment would name a graph platform such as Neo4j or Memgraph and read your real estate, but nothing here implies a live z/OS pipeline. The demo proves the mechanism on a synthetic estate, not a deployment.

How is this different from IBM watsonx Code Assistant or a big SI's toolchain?

We do not claim to beat IBM's or a system integrator's parser, and the demo parser covers a realistic synthetic subset of COBOL, not every dialect, ALTER, or OCCURS DEPENDING ON. The distinction is the deliverable: a repository-aware knowledge graph plus a completeness proof and a safe extraction order, rather than a per-file translation. It is the understanding layer that any translation effort needs first, and it is the layer that a better base model does not remove.

Is this a live product or a demo?

It is a runnable demo that proves the mechanism, not a deployed pipeline. The bank estate is synthetic and authored for this demo, so the true dependency set is known by construction, which is what makes the recall metric a reproducible labeled measurement rather than a claim. The parse, the graph, and all four analyses are deterministic plain Python (FastAPI plus networkx, Cytoscape.js UI) that run with no API key and no database. An optional LLM layer for question answering exists but is off by default, and the value does not depend on it.

Technical Research

The research behind this demo — the architecture, the verification design, and the enterprise blueprint.

Planning a mainframe modernization?

The understanding layer is the hard part. We build the map first.

If your team is weighing how to modernize a COBOL estate without a UAT surprise from a dependency no one could see, we would genuinely like to hear how you are thinking about it. The problem is industry-wide and the answers will be too.

Topology assessment

  • ✓ Map where a change can reach across copybooks, DB2, and JCL
  • ✓ Resolve the transitive closure with file:line provenance
  • ✓ Score dependency-retrieval recall against a ground-truth set
  • ✓ Produce the completeness proof your auditors need

Build the map

  • ✓ A typed knowledge graph over your real estate
  • ✓ A completeness gate that flags what it cannot resolve
  • ✓ A ranked, defensible strangler-fig extraction order
  • ✓ An exportable DORA ICT-asset and SOC-2 change-control report