Skip to main content
puodziukas.dev›CASES/COBOL PAYROLL FORENSICS/

For engineers modernizing COBOL batch payroll

Forensic case study, synthetic probe

COBOL PIC V9 Truncation Passes Reconciliation

I built a public probe on a synthetic fixed-seed payroll corpus, with no real payroll data and no employer behind it.

Hire me - remote W2Clone and run the probe

PIC V9 truncation passed a standard audit and the reconciliation diff, and the cost is a synthetic compounding error you can reproduce to the cent by cloning and running it.

Topographic data-mesh backdrop in navy and royal blue

Limit: the corpus is synthetic and fixed-seed. The loss is a reproducible demonstration, not a measurement of any real payroll.

47,312 synthetic payroll records - Deterministic replay - Reproducible proof
A standard audit shows green. The reconciliation diff shows clean. Underneath runs a PIC V9 truncation neither check is built to name. A public probe reproduces it to the cent: clone and run.

Type a number, watch a PICTURE clause eat it

COBOL stores a value in the shape its PICTURE clause declares. Digits past the declared decimal places are dropped, not rounded, and the loss compounds every time the value is stored again. Try your own amounts and a PIC of your choosing.

Runs in your browser. Nothing is sent anywhere.

The Failure Class

COBOL PICTURE clauses fix how many digits a field keeps. The probe reproduces the failure class: narrow input fields (hours PIC 9(3)V9, rate PIC 9(4)V99) silently drop digits on every store, and the multiplication adds a smaller loss. No ROUNDED or ON SIZE ERROR clause is present, so nothing signals the truncation. The probe prints the split by source field with python3 probe.py --attribute.

The truncation is small per record, so a per-record review can miss it. Compounded across the corpus, the drift is confirmed to the cent via deterministic replay. The failure class is reproduced on a synthetic, fixed-seed corpus: $40,832.41 synthetic compounding error across 47,312 synthetic records. Clone and run: github.com/mpuodziukas-labs/cobol-pic-probe (CI-verified, deterministic).

* payroll.cob, field declarations (verbatim lines from the public repo) 01 WS-RATE-BUGGY PIC 9(4)V99 COMP-3. 01 WS-HOURS-BUGGY PIC 9(3)V9 COMP-3. 01 WS-GROSS-BUGGY PIC 9(7)V99 COMP-3. * The repo notes USAGE COMP-3 does not change the truncation; * the loss comes from the narrow fields, mostly hours and rate.

Why This Kind of Drift Runs Silent

Three conditions combine to make this class of defect invisible to standard audit tooling:

  1. Sub-threshold per-record delta. No single record looks large. The difference is small per record, so a per-record review can miss it.
  2. Silent truncation. Modern monitoring systems observe program exit codes and exception logs. A store into a narrow field raises neither when no ON SIZE ERROR clause is present; the digits are dropped and the run exits cleanly.
  3. No replay coverage. A batch can carry full test coverage by count while zero tests verify arithmetic idempotency under boundary inputs. Coverage confirms the program ran; it does not confirm what the program computed.

The Forensic Method

Public methodology (no client data, fixed-seed synthetic corpus):

$ python3 probe.py COBOL PIC 9(7)V99 Truncation Probe - SYNTHETIC Records processed : 47,312 Compounding error (loss): $40,832.40790 (excerpt: three lines of the probe output, verbatim; other lines omitted)

Replay over 47,312 synthetic records returns identical results run after run (test_repeated_runs_are_identical). Each replay output is verifiable independently, without trusting the forensic environment.

Recovery and Prevention

The prevention pattern the probe demonstrates: narrow input fields get widened and each store gets an explicit ROUNDED or ON SIZE ERROR clause with explicit exception routing that exits with a non-zero status code. Monitoring is wired to watch for non-zero exits as well as crashes. Replay coverage is added as a pre-deploy gate: any batch that cannot reproduce a known-correct output blocks the deploy.

PROOF ARTIFACTS
✓47,312 synthetic records - Each replay returns identical results, independently verifiable
✓Drift quantified to the cent - Computed to the cent by deterministic replay; the public figure reproduces on the synthetic corpus
✓Public, CI-verified - cobol-pic-probe repo: clone and run the exact assertions
✓Exact reference - Every delta recomputed with exact decimal arithmetic on the synthetic corpus

Does Your COBOL Batch Have Replay Coverage?

Three questions determine whether this failure class is running in your system right now:

01Can you replay any past payroll batch and verify the output to the cent, without trusting the original environment?
02Do your COBOL batch programs have arithmetic boundary coverage at PIC field precision limits?
03Does your monitoring alert on non-zero COBOL program exits, or only on HTTP errors and system crashes?
Hire me - remote W2

replay-verified findings - Remote - open to mid-level and senior IC roles

RELATED CASES
COBOL -> Rust Reference Implementation ->

How to verify

Clone cobol-pic-probe and run python3 probe.py.

Roles this proves: QA / Test Automation Engineer.