GEN2E/i is not a business application in the ordinary sense — it is a
rehost-fidelity reference corpus. It is a clean-room, generator-style OPM RPG/400
customer-master maintenance function set (CUSPOST / CUSRPT, a generated
/COPY standard header Y2CPY, and machine-uniform @/#/$
names) authored to prove that CA 2E (Synon)- and Plex-generated RPG runs AS-IS on the SteelFrame X engine.
It exercises the constructs a 2E/Plex generator characteristically emits and, in doing so, it
found two real platform gaps (both since fixed). This manual documents it as what it is: a proof
vehicle, honest about its batch/oracle-driven nature. It is grounded entirely in the committed source
(gen2e-app/src/sources.mjs, src/programs.mjs, src/seed.mjs, the
test/gen2e_build.mjs build+run+oracle driver, and gen2e-app/FINDINGS.md).
CA 2E (formerly Synon/2E) and CA Plex are model-driven 4GL development tools for IBM i.
A developer designs against a model (entities, access paths, functions) and the tool
generates native RPG (and COBOL/DDS) source which is then compiled with the normal IBM i
compilers (CRTRPGPGM for OPM RPG/400, CRTBNDRPG for RPG IV). The generated
source has a recognisable machine signature:
#, @, $ and numeric suffixes — e.g.
#CUSMR, Y2U0001, S1R@01, W0EDT2, and dense
numbered indicators *IN71..*IN79./COPY standard header. Essentially every generated function
/COPYs a Y2* (2E) or #* copybook of standard work fields.
This is the characteristic 2E artifact.KLIST/KFLD for keyed
CHAIN/READE, CASxx dispatch groups, dense conditioning
indicators, an EXCPT exception-report pattern, and a *PSSR program-status
error subroutine.The SteelFrame X product's REHOST value proposition (see ZOSWEBI-LANGUAGE-COVERAGE.md,
§"Tier: 4GLs that GENERATE native code") asserts that the generated RPG/COBOL/C runs as-is
on the engine — the model tool is not re-hosted, its output is. GEN2E/i tests exactly that
claim.
Before GEN2E/i, the "generated RPG runs as-is" claim was asserted but unverified against actual generator-shaped source. GEN2E/i is a deliberate, first-principles proof vehicle:
rpg3-app corpus, so any failure is the engine's, not an authoring artifact.CRTPF/CRTLF/CRTRPGPGM pipeline (the OPM RPG/400 target 2E
classically emits to). Every construct that fails to compile or run as-is is logged as a fidelity
gap; every construct that works is logged as as-is evidence.GEN2E-01, GEN2E-02) sit exactly where
machine-generated OPM code differs from hand-written code. Both are now fixed (see section F). The
full driver reports 15/15 checks passed.CUSPOST posts synthetic credit adjustments and CUSRPT totals balances only
so that a full generated-style RPG program has something concrete to compute against a hand-derived
oracle. Treat the "application" as a fixture; the deliverable is the fidelity evidence. MODEL (DDS) GENERATED RPG/400 BUILD + ORACLE (test/gen2e_build.mjs)
---------- ----------------- ------------------------------------
CUSMR (master PF) -> CUSPOST (post txns) CRTLIB GEN2E
CUSMRL1 (access LF) KLIST/KFLD CHAIN seedGen2e() -> QDDSSRC + QRPGSRC members
CUSTXN (txn PF) CASxx @CHG/@PAY CRTPF/CRTLF -> CUSMR, CUSMRL1, CUSTXN
COMP -> *IN73 over-limit CRTRPGPGM -> CUSPOST, CUSRPT (AS-IS)
Y2CPY (/COPY hdr) -> /COPY QRPGSRC,Y2CPY -> CUSPOSTB, CUSRPTB (*B variants)
| *PSSR error subr writeRecords -> seed 3 masters + 4 txns
+--copybook of----> CUSRPT (report) callPgm -> run CUSPOSTB / CUSRPTB
W0CUS/W0NAM/ SETLL/READ walk decode CUSMR + read QPRINT spool
W0BAL/W0STS EXCPT LINE/TOTAL assert vs hand-derived oracle -> 15/15
A single run flows: the driver creates library GEN2E and seeds the generated-style
members → builds the model DDS objects → compiles the RPG AS-IS through
CRTRPGPGM → seeds three master rows and four transactions → calls the compiled
program → reads back the master file and the QPRINT spool and checks every value against
a hand-derived oracle. There is no interactive step and no persistent state between runs (a fresh,
gitignored data root is built each time).
| Object | Type | Role |
|---|---|---|
| GEN2E | *LIB | The corpus library (text "CA 2E (Synon)-style generated app"). |
| QDDSSRC | PF-SRC | DDS source members (the model). |
| QRPGSRC | PF-SRC | RPG source members (programs + the /COPY header). |
| CUSMR | PF (DDS) | Model-generated customer master, keyed on CUSNO. |
| CUSMRL1 | LF (DDS) | Access-path object over CUSMR, keyed CUSTYP then CUSNO. |
| CUSTXN | PF (DDS) | Transaction file (credit adjustments to post). |
| Y2CPY | /COPY member | Generated standard work-field header copybook. |
| CUSPOST | RPG/400 | Generated-style posting function (AS-IS, keeps /COPY + @-subrs). |
| CUSRPT | RPG/400 | Generated-style report function (AS-IS, keeps /COPY). |
| CUSPOSTB | RPG/400 | Runnable variant of CUSPOST (inlined header, @-subrs renamed). |
| CUSRPTB | RPG/400 | Runnable variant of CUSRPT (inlined header). |
| QPRINT | Printer/spool | Program-described exception/report output file. |
The corpus is 3 DDS members + 1 /COPY header + 4 RPG members (2 AS-IS faithful, 2 runnable
variants), all built and driven by one test file. Sections D and F expand each. The AS-IS members
(CUSPOST/CUSRPT) keep the faithful /COPY Y2CPY and @-named
subroutines that demonstrate the two findings; the *B variants exist only to exercise the
rest of the generated constructs past those gaps (see F.3–F.4).
GEN2E/i has no 5250 display file, no subfile, and no interactive program. Unlike a servicing or
maintenance application, it is not something an operator signs on to and drives from a green screen. It is
a batch fidelity corpus: two generated-style RPG/400 programs (CUSPOST,
CUSRPT) that read files, compute, and write a printer/spool report — driven entirely by
its own build+run+oracle harness (test/gen2e_build.mjs), never by a human at a terminal.
The manual states this plainly because the honest thing a 2E-shop reader needs to know is:
what will my generated OPM RPG do when I compile and run it as-is on this engine? That question is
answered by compiling the members through CRTRPGPGM and calling them — the same way a
scheduled/JOBQ batch step would — not by an interactive session.
| To do this | How it happens here |
|---|---|
| Build the model files | CRTPF/CRTLF over the seeded DDS members (driver step). |
| Compile a generated program AS-IS | CRTRPGPGM PGM(GEN2E/CUSPOST) SRCFILE(GEN2E/QRPGSRC) SRCMBR(CUSPOST) |
| Run a posting/report | compile.callPgm(job, 'GEN2E', 'CUSPOSTB', []) (a bare, parameterless CALL). |
| Inspect results | Decode CUSMR rows + read the QPRINT spool, compare to oracle. |
Were these functions dropped into a real 2E-generated application, they would be the batch legs of a customer-master maintenance module:
CUSTXN in key order, CHAIN each transaction to the customer master
CUSMR, apply a charge or payment, re-check the credit limit and flag over-limit
accounts, and print an exception report (over-limit alerts and no-such-customer lines).Both take no parameters — exactly the SBMJOB idiom (a scheduled submission is a bare
CALL). The generated-style programs DSPLY nothing; their entire result is in the updated
master file and the QPRINT spool, which is what the oracle checks. See section F for the full
program walk-throughs, and section C for the seeded inputs and expected outputs.
The whole corpus is exercised by one driver, gen2e-app/test/gen2e_build.mjs. It boots the
engine in-process against a fresh gitignored data root, seeds the generated-style 2E corpus, creates the
DDS objects, compiles + runs the generated RPG/400 AS-IS through CRTRPGPGM, and asserts every
result against a hand-derived oracle. Run it with:
$ node gen2e-app/test/gen2e_build.mjs ... 15/15 gen2e checks passed
The driver's sequence (all in library GEN2E, job GEN2EBLD run as
QSECOFR with LIBL = QSYS QGPL GEN2E QTEMP, CURLIB = GEN2E):
CRTLIB LIB(GEN2E), then seedGen2e() writes the DDS + RPG + Y2CPY
members into QDDSSRC/QRPGSRC.CRTPF for CUSMR, CRTLF for the
access-path LF CUSMRL1, CRTPF for CUSTXN.CUSPOST and CUSRPT via
CRTRPGPGM — these keep the faithful /COPY Y2CPY header (the
load-bearing 2E trait). Since the GEN2E-01 fix (commit 32f4f6c89) these
compile AS-IS because expandCopies now runs on the OPM path.CUSPOSTB / CUSRPTB (inlined header,
@-subrs renamed) to exercise the rest of the constructs.writeRecords into CUSMR) and 4 transactions into
CUSTXN.compile.callPgm runs CUSPOSTB then CUSRPTB; the driver decodes
CUSMR and reads the QPRINT spool and asserts against the oracle.| CUSMR (master, before) | CUSTXN (transactions, key order) |
|---|---|
| #100 ACME METALS — type A, bal 100.00, lim 500.00, sts ' ' | 100 code 1 (charge) 50.00 |
| #200 BOREAL SUPPLY — type B, bal 300.00, lim 300.00, sts ' ' | 200 code 1 (charge) 250.00 |
| #300 CRESCENT LTD — type C, bal 0.00, lim 100.00, sts ' ' | 300 code 2 (payment) 25.00 |
| 400 code 1 (charge) 10.00 — no such customer |
| # | Op | Result |
|---|---|---|
| 100 | charge 50.00 | bal 100+50 = 150.00 (≤ limit 500, ok). |
| 200 | charge 250.00 | bal 300+250 = 550.00 > limit 300 → STS set 'H' (COMP/*IN73) + ALERT line. |
| 300 | payment 25.00 | bal 0−25 = −25.00. |
| 400 | charge 10.00 | CHAIN miss → NO CUST exception line. |
The driver runs fifteen assertions; a green run is 15/15 gen2e checks passed. They fall in
five groups:
| Group | Checks |
|---|---|
| Model DDS objects (3) | CUSMR PF, CUSMRL1 LF (access path), CUSTXN PF each created from generated DDS. |
| AS-IS /COPY compile (2) | [GEN2E-01 fixed] CUSPOST & CUSRPT compile AS-IS via CRTRPGPGM with the /COPY Y2CPY header intact. |
| Variant compile (2) | CUSPOSTB & CUSRPTB (inlined header) compile AS-IS. |
| CUSPOST run + oracle (6) | ran clean; #100=150; #200=550 & STS 'H'; #300=−25; NO CUST line for #400; ALERT line for #200. |
| CUSRPT run + oracle (2) | ran clean; the TOTAL CUST line printed (READ walk + EXCPT). |
CUSMR/CUSMRL1/CUSTXN
to exist first so the compile can resolve the record formats.CUSPOST/CUSRPT keep the faithful /COPY Y2CPY and
@-named subroutines to demonstrate GEN2E-01/GEN2E-02. The
runnable CUSPOSTB/CUSRPTB variants (a) inline the Y2CPY body and
(b) rename @CHG/@PAY→XCHG/XPAY (same 4-char
width, so every fixed-form column is preserved exactly). These are documented workarounds for
logged findings, not edits to dodge a gap — the driver only executes the variants because a
program has to run to check the oracle.ibmidata-gen2e-build, rmSync then recreated), so the driver is
fully self-contained and idempotent by construction.All objects are in library GEN2E, grounded in gen2e-app/src/sources.mjs. The
DDS is emitted through proven-column helpers (field name at col 19, length ending col 34, type col 35,
decimals col 37) that mirror the verified rpg3-app layout — so the files are byte-for-byte
what a generator-style member would look like. There are three model files plus one /COPY
header member.
The "model"-generated master. 2E names the record format like the file + R
(CUSMRR); the fields carry the model's generated field names.
| Field | Type (DDS) | Meaning |
|---|---|---|
| CUSNO | 6S 0 (packed/zoned, 0 dec) | Customer number (key field K CUSNO). |
| CUSNAM | 25A | Customer name. |
| CUSTYP | 1A | Type A / B / C. |
| CUSBAL | 9S 2 | Balance. |
| CUSLIM | 9S 2 | Credit limit. |
| CUSSTS | 1A | Status flag (set to 'H' on over-limit). |
A logical file — the 2E "access path" object — PFILE(CUSMR) keyed
CUSTYP then CUSNO. It reuses the same record format name
(CUSMRR) so externally-described I-specs resolve identically whether a program opens the PF or
the LF. This is exactly how a 2E generator emits an alternate access path for the same model entity.
Credit adjustments to be posted against the master.
| Field | Type (DDS) | Meaning |
|---|---|---|
| TXCUS | 6S 0 | Customer number (key K TXCUS). |
| TXCOD | 1A | 1 = charge, 2 = payment, 3 = limit change. |
| TXAMT | 9S 2 | Amount. |
Y2CPY is the characteristic 2E artifact: a generated "standard header" copybook of
work fields that essentially every generated function /COPYs. It is stored in
QRPGSRC as member Y2CPY and coded as a fixed-form I-spec data structure of work
fields with machine names.
| Subfield (DS Y2WRK) | Positions | Meaning |
|---|---|---|
| W0CUS | 1–6 | Work customer-number image. |
| W0NAM | 7–31 | Work name. |
| W0BAL | 32–40 | Work balance. |
| W0STS | 41–41 | Work status. |
The DS subfields are laid out through the proven IDS3/ISF3 helpers (DS name at
col 7; subfield from/to at cols 44–51, decimals col 52, name from col 53) — the same layout the
verified rpg3-app corpus uses, so the copybook is a faithful generator-shaped member.
CUSPOST and CUSRPT both include it with I/COPY QRPGSRC,Y2CPY. Note
that CUSRPT also references work counters W0CNT and W0TOT for its
count/total line (defined inline through arithmetic result fields, not in Y2CPY).
CUSMRL1 is an alternate access path over CUSMR (PFILE(CUSMR), shared record format CUSMRR).CUSTXN.TXCUS is matched to CUSMR.CUSNO at posting time via the generated C@KEY KLIST + CHAIN (no declared DB FK; the join is procedural, as generated OPM RPG does it).Y2CPY is included by both programs; its W0* fields are shared work storage, not persisted data."Operating" GEN2E/i means running its build+run+oracle driver and reading the result. There are no scheduled cycles, no control row to advance, and no interactive session. The runbook is therefore short and concrete: run it, confirm the compile+run verification, and read the two findings if a regression appears.
AS400 repo root, run the driver:
node gen2e-app/test/gen2e_build.mjs.15/15 gen2e checks passed and the process exits 0. Any
**FAIL line names the exact assertion that regressed.Pre-checks: none required — the driver builds its own fresh, gitignored data root
(ibmidata-gen2e-build) each run, so there is no residual state, library, or control table to
set up. It is self-contained and safe to re-run at will.
A green run establishes four things in order; if it turns red, the failing group tells you where:
| Verification | What a failure means |
|---|---|
Model DDS objects create (CRTPF/CRTLF). | A DDS/externally-described-file regression; the generated model files no longer build. |
[GEN2E-01 fixed] AS-IS /COPY Y2CPY compiles via CRTRPGPGM. | The GEN2E-01 fix regressed — /COPY is again rejected on the OPM path (see F.3). |
The *B variants compile. | A regression in the shared generated constructs (KLIST/CASxx/CHAIN/READE/*PSSR/EXCPT) or in the @-subr emission (see F.4). |
| Run + oracle (#100=150, #200=550+STS'H', #300=−25, NO CUST, ALERT, TOTAL CUST). | A runtime/semantics regression — the generated control flow ran but computed the wrong result. |
test/ibmi_gen2e_battle.mjs (cited in FINDINGS.md) is what a CI sweep runs to keep
both fixes from regressing. If you are hunting a regression in the OPM RPG/400 pipeline or in the
RPG→COBOL subroutine-name emission, this corpus is the fast, minimal reproduction.This is the fullest section: the two generated-style programs in detail, the specific 2E/Plex traits
each one exercises, and the two platform gaps this corpus found (both since fixed). All source is in
gen2e-app/src/programs.mjs and src/sources.mjs; the findings are in
gen2e-app/FINDINGS.md.
The load-bearing member. It reads CUSTXN, CHAINs the master by a generated
KLIST, dispatches on the transaction code via a CASxx group, updates the master, re-checks the
limit, and prints an exception report through QPRINT. It uses *IN71..*IN79 machine
indicators throughout and /COPYs the Y2CPY standard header.
CUSMR update-keyed externally-described (UF E ... K DISK),
CUSTXN input-keyed, QPRINT program-described printer (132).I/COPY QRPGSRC,Y2CPY — the generated standard header (the load-bearing 2E trait).C@KEY KLIST with one KFLD TXCUS — the generated keyed-access list.READ loop over CUSTXNR (*IN79 = EOF),
a per-record SETOF reset of *IN73 (dense-indicator discipline), then
C@KEY CHAIN CUSMR with *IN72 = not-found (HI).N72), a CASEQ group on TXCOD branches
to @CHG (code '1') or @PAY (code '2'), closed by END (ENDCS).CUSBAL COMP CUSLIM sets *IN73 when over; a conditioned
MOVE 'H' sets CUSSTS; UPDAT CUSMRR writes the row back.72 (miss) emits EXCPT NOCUST; 73 (over-limit)
emits EXCPT ALERT.@CHG (CUSBAL ADD TXAMT), @PAY
(CUSBAL SUB TXAMT), and a generated *PSSR program-status error subroutine.NOCUST ("NO CUST" + TXCUS edited Z) and
ALERT ("ALERT" + CUSNO + CUSBAL edit code 1).A simpler report leg. It walks the master by key from the top and prints a per-record line plus a total
line via EXCPT.
CUSMR input-keyed externally-described; QPRINT printer.I/COPY QRPGSRC,Y2CPY.*LOVAL SETLL CUSMRR, then a TAG/READ/GOTO
loop (*IN79 = EOF) — a keyed SETLL+READ walk kept OPM (the
source note explains it uses a program-described walk rather than RPG-cycle level indicators).W0CNT ADD 1 (count) and W0TOT ADD CUSBAL (total), each an
explicit arithmetic result field with fully-specified length and decimals.LINE (CUSNO Z, CUSNAM, CUSBAL edit 1) per record; TOTAL
("TOTAL CUST" + W0CNT + W0TOT) at end-of-file.CUSPOST/CUSRPT keep the faithful /COPY and
@-named subroutines because they demonstrate GEN2E-01/-02. The runnable
CUSPOSTB/CUSRPTB are produced by a variantise() transform that (a)
replaces the /COPY line with the inlined Y2CPY body and drops the copy-comment,
and (b) runs deAt() to rename @CHG/@PAY→XCHG/XPAY.The corpus's purpose is to run generator-characteristic constructs AS-IS. These are the traits it puts
through the real CRTRPGPGM pipeline, each logged as as-is evidence when it compiled + ran with
correct output vs the oracle (per FINDINGS.md "Positive evidence"):
| 2E/Plex trait | Where it appears | Status |
|---|---|---|
Generated /COPY standard header (Y2CPY) | CUSPOST, CUSRPT header line | Ran clean AS-IS after GEN2E-01 fix. |
| Externally-described PF and LF (access path) from model DDS | CUSMR / CUSMRL1 / CUSTXN, ext I/O + O-spec fields | Clean. |
Generated KLIST/KFLD + keyed CHAIN | C@KEY CHAIN CUSMR (hit + not-found) | Clean (correct HI not-found handling). |
CASxx dispatch group (multi-branch CASEQ→subrs) | TXCOD dispatch to @CHG/@PAY | Clean. |
Dense conditioning indicators (N72, 73, N79, ...) | Calc + output specs throughout CUSPOST | Clean. |
COMP setting a resulting indicator; UPDAT | CUSBAL COMP CUSLIM → *IN73; UPDAT CUSMRR | Clean. |
EXCPT exception records with edit codes (Z, 1) | NOCUST / ALERT / LINE / TOTAL | Clean. |
Explicit READ loop with EOF indicator | CUSPOST mainline; CUSRPT SETLL walk | Clean. |
| I-spec data-structure work header | Y2CPY body (inlined in *B) | Clean. |
@/#/$ in field and KLIST names | C@KEY KLIST; probe fields #DBF1, $AMT | Clean (mapped correctly; probe P3 compiles). |
*PSSR error subroutine | CUSPOST | Present and compiled. |
@/#/$ in subroutine/label names | @CHG/@PAY BEGSR; CASxx targets | Gap GEN2E-02 (since fixed) — see F.4. |
Confirmed platform gap. Newly found. Now fixed. (Cited: gen2e-app/FINDINGS.md,
GEN2E-01.)
Severity: High for 2E shops — the Y2*/#* standard-header
/COPY is the characteristic 2E artifact (essentially every generated OPM function
/COPYs it). As found, every such member failed to compile AS-IS via CRTRPGPGM.
Minimal repro: any RPG/400 source with a /COPY line compiled via
CRTRPGPGM:
H
FCUSMR UF E K DISK
I/COPY QRPGSRC,Y2CPY
Expected (real IBM i): RPG/400 (OPM CRTRPGPGM) fully supports /COPY; the
member is included and compiled. Actual (as found):
SNS9309 ... SNF0734 /COPY is not supported by CRTRPGPGM in this system — the member
would be included unconverted.
Locus. ibmi/rpg3.js (the RPG III→IV converter) emitted SNF0734 on
any /COPY//INCLUDE. expandCopies() in ibmi/compile.js
(which handles /COPY correctly) ran only on the RPGLE (CRTBNDRPG) path; the
RPG/400 conversion ran on the raw, un-expanded source, so the converter rejected the
/COPY before any expansion. Cross-check: the same /COPY compiled + ran
fine via CRTBNDRPG (test/copy_probe.mjs), isolating the locus to the OPM path.
Resolution (Fable fix, commit 32f4f6c89). expandCopies() now accepts
options (dftFile, sentinels) and crtBndPgm runs it on the
OPM/CRTRPGPGM path before the RPG III→IV conversion (default source file
QRPGSRC, fixed-form only, no ZFMT sentinels), so /COPY members are inlined and
compiled — matching real RPG/400. The Y2*-header /COPY now compiles + runs
via CRTRPGPGM; ZOSWEBI-LANGUAGE-COVERAGE.md was corrected to move /COPY
out of the honest-boundary list into supported. Guard: test/ibmi_gen2e_battle.mjs. This is why
the driver's AS-IS CUSPOST/CUSRPT assertions are tagged [GEN2E-01 fixed].
Confirmed platform gap. Newly found. Now fixed. (Cited: gen2e-app/FINDINGS.md,
GEN2E-02.)
Severity: High for 2E/Plex — generators routinely name subroutines and internal labels with
@/#/$ + numeric suffixes (@CHG, S1R@01,
#DBF1). Field names with these characters were handled; subroutine/label names were not.
Minimal repro (test/atname_probe.mjs):
EXSR @CHG + @CHG BEGSR ... ENDSR via CRTRPGPGM →
SNF9998 ... invalid symbol '@' - skipping word.#COD CASEQ '1' @CHG (CASxx branch to an @/#-named target) →
SNF9998 ... invalid symbol '#'.@-named KLIST (C@KEY) + #/$-named
fields (#DBF1, $AMT) → compiles. The defect is specific to
subroutine/label emission.Expected (real IBM i): @ # $ are valid RPG symbolic-name characters; a subroutine
@CHG compiles and EXSR @CHG performs it. Actual (as found): the generated
COBOL emitted the section name unsanitized — PERFORM SR-@CHG / SR-@CHG SECTION.
— and GnuCOBOL rejects @ in a section name, so the compile failed.
Locus. ibmi/rpg.js built subroutine section names as
SR-${name.toUpperCase()...} at the PERFORM SR-<name> and
SR-<name> SECTION./-P. emission points, interpolating the RPG label
without routing through cobName() (the mapper that turns $→-D,
#→-P, @→-A for field names). Fields used cobName;
subroutine labels bypassed it.
Resolution (Fable fix). A single srName() helper now routes every SR- emission point
(EXSR PERFORM, CASxx PERFORM, fixed-form EXSR, SECTION header, -P paragraph) through
cobName() consistently, so @/#/$-named subroutines emit
valid COBOL section names. Verified: EXSR @CHG + a CASxx-to-@-target compile + run
via both CRTRPGPGM and CRTBNDRPG. Guard: test/ibmi_gen2e_battle.mjs
(including a combined /COPY + @-subroutine member → oracle 20.00). Because the
section-name emission is shared, this gap would otherwise hit either compile path.
Rigor note, from FINDINGS.md: several symptoms first looked like platform gaps but
ultra-think traced them to the synthetic source using the wrong RPG column/operand — they are
not findings, and are logged only to show the false-positives were disqualified:
| Symptom | Real cause (authoring bug, corrected) |
|---|---|
| File program-described unexpectedly | F-spec external attribute at col 22 instead of col 19. |
| EXCPT record not emitted | Record name in the result field instead of factor 2. |
Empty COBOL IF | SETOF/SETON numbered indicator in factor 1 instead of the resulting-indicator cols 54–59. |
| Infinite loop | READ EOF indicator in lo instead of the EQ position (58–59). |
| Missed not-found branch | CHAIN not-found indicator in lo instead of HI (54–55). |
| "not numeric" on arithmetic | Blank decimal-positions column typed the result X(len); coding an explicit 0 (which a generator emits) types it numeric. |
The distinction matters: only GEN2E-01 and GEN2E-02 are real platform gaps
(reproduced minimally, locus identified, cross-checked against the working path). Everything else was the
corpus's own mistake, fixed in the source. Caveat (from FINDINGS.md): the corpus is
generator-style, clean-room synthesized — not actual Synon/Plex output — so real
generated source would exercise far more /COPY headers and @/# labels,
and both gaps would recur heavily; exact breadth on true generator output is inferred, not measured.
CUSMRL1 keys CUSMR by CUSTYP then CUSNO, sharing the
CUSMRR record format.CUSPOST uses a CASEQ group on TXCOD to branch to charge
or payment.CUSPOST CHAINs the master by the generated
C@KEY KLIST; the HI indicator (*IN72) signals not-found.Y2CPY standard header is included via I/COPY QRPGSRC,Y2CPY — the
characteristic 2E artifact (see GEN2E-01).CRTRPGPGM is the OPM RPG/400 path (the classic 2E OPM target);
CRTBNDRPG is the ILE RPG IV path. GEN2E/i compiles AS-IS through CRTRPGPGM.*IN71..*IN79) used tightly to condition calc and output specs
— a generator hallmark. N72 means "indicator 72 off", 73 "73 on".CUSPOST EXCPTs NOCUST/ALERT; CUSRPT EXCPTs
LINE/TOTAL.E in the F-spec), so the RPG
program does not re-declare fields — the standard 2E model-file pattern.C@KEY is a one-field KLIST over TXCUS.#, @, $ and numeric
suffixes (#CUSMR, @CHG, W0EDT2). Valid RPG symbols; the source of
both GEN2E findings.CRTRPGPGM and is the classic
target 2E generates to.CUSPOST.CUSRPT does
*LOVAL SETLL to walk the master from the top.Y2WRK with fields
W0CUS/W0NAM/W0BAL/W0STS) that every generated function /COPYs.