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.
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.

Limit: the corpus is synthetic and fixed-seed. The loss is a reproducible demonstration, not a measurement of any real payroll.
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).
Why This Kind of Drift Runs Silent
Three conditions combine to make this class of defect invisible to standard audit tooling:
- Sub-threshold per-record delta. No single record looks large. The difference is small per record, so a per-record review can miss it.
- 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.
- 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):
- Seeded from a fixed-seed synthetic payload set (reproducible, no client data)
- Executed against instrumented COBOL with PIC clause precision tracking
- Replayed deterministically: repeated runs return identical output for every gross-pay computation
- Compared against the expected, untruncated computation; delta = confirmed drift
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.
Does Your COBOL Batch Have Replay Coverage?
Three questions determine whether this failure class is running in your system right now:
replay-verified findings - Remote - open to mid-level and senior IC roles
How to verify
Clone cobol-pic-probe and run python3 probe.py.
Roles this proves: QA / Test Automation Engineer.
