Inspiration

Banks, insurers and governments still run on COBOL. The engineers who wrote it are retiring, and rewrites are risky for one reason: nobody can prove the new code does the same thing as the old code. A single cent rounded differently in a payroll or invoice system becomes a real problem at scale. We wanted AI to do the migration, but with a referee it can't argue with: the original program itself.

What it does

You drop a legacy COBOL codebase into NorthBound. A team of NVIDIA Nemotron agents migrates it to Python, one module at a time, through six phases:

  1. Understand: maps CALL and COPY dependencies and orders modules so callees migrate first.
  2. Spec: Nemotron writes a plain-English spec of each program and flags legacy quirks (truncation, overflow, implied decimals).
  3. Record: we compile and run the real COBOL with GnuCOBOL on generated edge-case inputs and save exactly what it prints. That is the answer key.
  4. Rewrite: Nemotron writes idiomatic Python using Decimal, runs it in a sandbox, and fixes its own mistakes before handing it over.
  5. Verify: every recorded case is replayed against the Python.
  6. Accept: a module is accepted only when every output matches, character for character:

$$\text{accept}(P) \iff \forall x \in G:\ P(x) = \text{COBOL}(x)$$

If a rewrite still fails after three attempts, an explainer agent says in one plain-English sentence whether it's a bug in the new code or a quirk of the old system, for example "the old system cuts off fractions of a cent instead of rounding." A person can then send a hint that guides the next attempt.

Everything plays out in a cinematic "galaxy" frontend: each program is a star travelling through seven stations, and you can click any station to see what that step really produced: the spec, the test inputs, the COBOL answer key, each rewrite attempt, and the verification result.

How we built it

  • Models: NVIDIA Nemotron 3.5 Super for rewriting, test writing and explanations; Nemotron 3.5 Lightning for specs, via langchain-nvidia-ai-endpoints.
  • Orchestration: a LangGraph state machine with a verify → rewrite retry loop, writing live state after every step.
  • Ground truth: GnuCOBOL compiles and runs the original programs; their recorded outputs become pytest equivalence tests.
  • Multi-file codebases: subprograms expose a call() convention, callers import already-verified dependencies instead of re-implementing them, and copybooks are expanded into the prompt.
  • Safety: generated code runs in a separate sandboxed process, and an anti-cheat gate rejects any rewrite that touches files or the OS (so it can't just read the answer key).
  • Frontend: a canvas "galaxy" in plain JavaScript that replays recorded real runs, plus a quick live mode that runs one program through Nemotron in about 25 seconds.
  • Team workflow: four people built in parallel against one frozen contract of function signatures, with stubs so the pipeline ran end to end from the first hour.

Challenges we ran into

  • COBOL is full of traps. Values are silently truncated, not rounded; ON SIZE ERROR overrides overflow; input fields have implied decimal points; edited pictures like Z,ZZ9.99 pad with spaces. Every one of these broke a first attempt, so we encoded them into the prompts and gave the model tested helpers.
  • Our model IDs died mid-hackathon. Live testing showed one Nemotron model had been retired (410 Gone) and another wasn't enabled for our accounts (404). We added automatic fallback across Nemotron models.
  • Reasoning ate the answer. With reasoning on, Nemotron sometimes spent its entire token budget thinking and returned nothing, and we were caching those empty replies. We made reasoning a per-agent choice and retried empty answers without it.
  • Invisible context. A program that does COPY INVREC never shows the model its record layout, and Python's isolated mode blocked our sandbox from importing verified dependencies. Both silently broke multi-file rewrites until we found them.
  • A rewrite that cheats can look perfect. Code that reads the recorded outputs from disk would pass every test, so we built a gate that forbids it.

Accomplishments that we're proud of

  • All 3 programs in each of our recorded real runs were verified byte for byte, and they passed 926/926 and 600/600 held-out inputs they had never seen.
  • A dependency chain (INVOICE calls DISCOUNT) migrates with the caller importing the verified callee, never copying its logic.
  • When we planted a one-cent rounding bug, the system caught it and explained it in plain English.
  • The legacy quirks are preserved, not "fixed", because the real COBOL output is the test.

What we learned

  • Generating code is the easy part. Verifying it is what makes AI migration trustworthy, and the original program is the best possible oracle.
  • Give LLMs exact rules and tested helpers for fiddly semantics instead of hoping they infer them.
  • Test against the live API early: model catalogs change, and reasoning models need room in the token budget.
  • A frozen contract between teammates is what let four people merge without conflicts.

What's next for NorthBound

  • Programs that read and write files and databases, plus CICS screens and batch JCL.
  • Coverage-guided input generation, so the answer key provably hits every branch.
  • Producing a ready-to-review pull request per module, with its spec, tests and proof attached.
  • More source languages (PL/I, RPG) and target languages (Java, Go).

Built With

Share this project:

Updates

Submission history