The receipt room · live trace
Parity receipt
A reduced AL3 record carrying the same structural classes — REDEFINES overlays and OCCURS DEPENDING ON — at smaller scale.
Verdict
PASS
Records
8
Elementary fields
25
REDEFINES
2
OCCURS
3
Five quality gates
| 01 | PARSER | PASS | Deterministic AST extraction yields a non-empty, field-bearing record set. No LLM involved. | 8 records · 25 elementary fields |
| 02 | SCHEMA_SANITY | PASS | Candidate schema parses as valid Zod — balanced delimiters, no markdown fences, no prose. | valid Zod module |
| 03 | FIELD_PARITY | PASS | len(COBOL elementary fields) === len(emitted schema leaves). Off by one and the build fails. | COBOL 25 ⇄ schema 25 |
| 04 | DARK_CORNER | PASS | Every REDEFINES overlay compiles to a union (discriminated where a record-type byte exists); every OCCURS to a dynamic array. | 2/2 overlays · 3/3 arrays |
| 05 | MOCK_STRUCTURE | PASS | A mock document generated from the schema re-validates against it — the schema is internally consistent. | 28 nodes round-tripped |
Field-for-field mapping · 25 elementary fields
| COBOL field | PIC | Storage | Schema path | Type |
|---|---|---|---|---|
| TRANSACTION-TYPE | X(4) | alphanumeric (4 chars) | acordMiniRecord.transactionType | z.string().max(4) |
| MESSAGE-ID | X(8) | alphanumeric (8 chars) | acordMiniRecord.messageId | z.string().max(8) |
| POLICY-NUMBER | X(20) | alphanumeric (20 chars) | acordMiniRecord.policyNumber | z.string().max(20) |
| NAME-TYPE | X(1) | alphanumeric (1 chars) | insuredNameData.nameType | z.string().max(1) |
| INSURED-LAST-NAME | X(30) | alphanumeric (30 chars) | insuredNameData.insuredLastName | z.string().max(30) |
| INSURED-FIRST-NAME | X(20) | alphanumeric (20 chars) | insuredNameData.insuredFirstName | z.string().max(20) |
| ADDR-INDICATOR | X(1) | alphanumeric (1 chars) | insuredAddressData.addrIndicator | z.string().max(1) |
| ADDRESS-LINE-1 | X(35) | alphanumeric (35 chars) | insuredAddressData.addressLine1 | z.string().max(35) |
| CITY | X(25) | alphanumeric (25 chars) | insuredAddressData.city | z.string().max(25) |
| POLICY-EFF-DATE | X(8) | alphanumeric (8 chars) | policyInfo.policyEffDate | z.string().max(8) |
| POLICY-EXP-DATE | X(8) | alphanumeric (8 chars) | policyInfo.policyExpDate | z.string().max(8) |
| PREMIUM-AMOUNT | S9(9)V99 COMP-3 | packed decimal (COMP-3, signed, scaled) | policyInfo.premiumAmount | z.number() |
| VEHICLE-COUNT | 9(2) | display numeric (2 digits) | vehicleData.vehicleCount | z.string().regex(/^\d{1,2}$/) |
| VIN | X(17) | alphanumeric (17 chars) | vehicleData.vehicleEntry[].vin | z.string().max(17) |
| YEAR | 9(4) | display numeric (4 digits) | vehicleData.vehicleEntry[].year | z.string().regex(/^\d{1,4}$/) |
| MAKE | X(15) | alphanumeric (15 chars) | vehicleData.vehicleEntry[].make | z.string().max(15) |
| COVERAGE-IND | X(1) | alphanumeric (1 chars) | coverageData.coverageInd | z.string().max(1) |
| COVERAGE-LINE-1 | X(40) | alphanumeric (40 chars) | coverageData.coverageLine1 | z.string().max(40) |
| COVERAGE-LINE-2 | X(40) | alphanumeric (40 chars) | coverageData.coverageLine2 | z.string().max(40) |
| DRIVER-COUNT | 9(1) | display numeric (1 digits) | driverInfo.driverCount | z.string().regex(/^\d{1,1}$/) |
| DRIVER-NAME | X(30) | alphanumeric (30 chars) | driverInfo.driverEntry[].driverName | z.string().max(30) |
| LICENSE-NUMBER | X(20) | alphanumeric (20 chars) | driverInfo.driverEntry[].licenseNumber | z.string().max(20) |
| CLAIM-COUNT | 9(3) | display numeric (3 digits) | claimHistory.claimCount | z.string().regex(/^\d{1,3}$/) |
| CLAIM-DATE | X(8) | alphanumeric (8 chars) | claimHistory.claimEntry[].claimDate | z.string().max(8) |
| CLAIM-AMOUNT | S9(7)V99 COMP-3 | packed decimal (COMP-3, signed, scaled) | claimHistory.claimEntry[].claimAmount | z.number() |
Emitted schema · TypeScript + Zod
import { z } from "zod";
export const RecordSchema = z.object({
acordMiniRecord: z.object({
transactionType: z.string().max(4),
messageId: z.string().max(8),
policyNumber: z.string().max(20),
}),
// REDEFINES overlay: INSURED-NAME-DATA / INSURED-ADDRESS-DATA
insuredNameData: z.union([
z.object({
nameType: z.string().max(1),
insuredLastName: z.string().max(30),
insuredFirstName: z.string().max(20),
}),
z.object({
addrIndicator: z.string().max(1),
addressLine1: z.string().max(35),
city: z.string().max(25),
})
]),
policyInfo: z.object({
policyEffDate: z.string().max(8),
policyExpDate: z.string().max(8),
premiumAmount: z.number(),
}),
// REDEFINES overlay: VEHICLE-DATA / COVERAGE-DATA
vehicleData: z.union([
z.object({
vehicleCount: z.string().regex(/^\d{1,2}$/),
vehicleEntry: z.array(z.object({
vin: z.string().max(17),
year: z.string().regex(/^\d{1,4}$/),
make: z.string().max(15),
})).max(5) /* OCCURS 0..5 DEPENDING ON VEHICLE-COUNT */,
}),
z.object({
coverageInd: z.string().max(1),
coverageLine1: z.string().max(40),
coverageLine2: z.string().max(40),
})
]),
driverInfo: z.object({
driverCount: z.string().regex(/^\d{1,1}$/),
driverEntry: z.array(z.object({
driverName: z.string().max(30),
licenseNumber: z.string().max(20),
})).max(3) /* OCCURS 0..3 DEPENDING ON DRIVER-COUNT */,
}),
claimHistory: z.object({
claimCount: z.string().regex(/^\d{1,3}$/),
claimEntry: z.array(z.object({
claimDate: z.string().max(8),
claimAmount: z.number(),
})).max(10) /* OCCURS 0..10 DEPENDING ON CLAIM-COUNT */,
}),
});
export type Record = z.infer<typeof RecordSchema>;
Source copybook
Show ACORD_MINI_NIGHTMARE.CPY
01 ACORD-MINI-RECORD.
02 TRANSACTION-TYPE PIC X(4).
02 MESSAGE-ID PIC X(8).
02 POLICY-NUMBER PIC X(20).
01 INSURED-NAME-DATA.
02 NAME-TYPE PIC X(1).
02 INSURED-LAST-NAME PIC X(30).
02 INSURED-FIRST-NAME PIC X(20).
01 INSURED-ADDRESS-DATA REDEFINES INSURED-NAME-DATA.
02 ADDR-INDICATOR PIC X(1).
02 ADDRESS-LINE-1 PIC X(35).
02 CITY PIC X(25).
01 POLICY-INFO.
02 POLICY-EFF-DATE PIC X(8).
02 POLICY-EXP-DATE PIC X(8).
02 PREMIUM-AMOUNT PIC S9(9)V99 COMP-3.
01 VEHICLE-DATA.
02 VEHICLE-COUNT PIC 9(2).
02 VEHICLE-ENTRY OCCURS 0 TO 5 TIMES DEPENDING ON VEHICLE-COUNT.
03 VIN PIC X(17).
03 YEAR PIC 9(4).
03 MAKE PIC X(15).
01 COVERAGE-DATA REDEFINES VEHICLE-DATA.
02 COVERAGE-IND PIC X(1).
02 COVERAGE-LINE-1 PIC X(40).
02 COVERAGE-LINE-2 PIC X(40).
01 DRIVER-INFO.
02 DRIVER-COUNT PIC 9(1).
02 DRIVER-ENTRY OCCURS 0 TO 3 TIMES DEPENDING ON DRIVER-COUNT.
03 DRIVER-NAME PIC X(30).
03 LICENSE-NUMBER PIC X(20).
01 CLAIM-HISTORY.
02 CLAIM-COUNT PIC 9(3).
02 CLAIM-ENTRY OCCURS 0 TO 10 TIMES DEPENDING ON CLAIM-COUNT.
03 CLAIM-DATE PIC X(8).
03 CLAIM-AMOUNT PIC S9(7)V99 COMP-3.Provenance
copybookACORD_MINI_NIGHTMARE.CPY
input SHA-25651a20e49ae1b300607d6e2bddfe7fbdea6bd9aee4cad3e1eab1cbdf8c87e8be6
output SHA-256d82c6b39aa03825c5369ddbe1255a2fda42d32f5bb0ee196fd959392fd32bd32
determinismsame input → identical output hash, every run
machine-readable/receipt.json?cb=mini