fix(answer-key): model multi-program sources (sibling / nested programs) (#4206) - #4226
Conversation
…ograms, units per PROCEDURE DIVISION (#4206) The draft reader now splits a source into its programs (program_spans). The first program is the entry; the rest are `siblings`, each with units and dead verdicts from its own PROCEDURE DIVISION. Score pairs and census claims name a sibling's unit PROG:NAME, and engine units are placed by start line. Readers that treat a file as one program check against bare names. Fixes four draft-reader errors found on DBB epscsmrd.cbl: a consuming GO TO match swallowed later GO TOs in the same name run; GO TO ... DEPENDING ON followed by a plain GO TO is terminal; XML PARSE PROCESSING PROCEDURE is a reach; END-XML/END-JSON/END-INVOKE close an ON EXCEPTION phrase. No program in the other six corpora drafts differently. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013sNMtAg6s9dyyjNgnjRHi8
|
Suite gate: 13,932 passed. 3 failed, all pre-existing (they also fail on origin/main c0a7e90, and this PR touches no det code): |
|
Correction: the 3 |
2 PIC X(31) ..., implicit FILLER) is read as a field named PIC
#4246
Root cause
The COBOL answer key held one program per source file and keyed dead verdicts by unit name.
_unitsread from the first PROCEDURE DIVISION to end of file. On a source holding several programs (DBBepscsmrd.cbl: 11 batch-compiled siblings plus XCHRFLTR and XWSPFLTR nested in EPSCSMRC, each opening withMAINLINE SECTION), the draft read later programs'PROGRAM-ID/AUTHOR/INSTALLATION/WORKING-STORAGElines as units, and ran reachability across program boundaries.Fix (tests/tools only, no engine change)
program_spanssplits a source into its programs. The first is the key entry; the rest go in a newsiblingsblock (line,end_line,nested_in,units,dead), read from each program's own PROCEDURE DIVISION, which stops at its END PROGRAM or its first nested program. A CALL of a sibling's PROGRAM-ID resolves to the file that holds it. Single-program sources keep the whole-file reading.PROG:NAME(keyed_units/keyed_dead). Engine units are placed in a program by start line, the innermost program winning (keyed_unit_name). The census brief explainsPROG:NAMEonly when it asks about one. Readers that treat a file as one program (the refraction differential and the call-graph COBOL score) use bare names (bare_units/bare_dead).test_key_integritychecks every sibling the way it checks a program._GOTOconsumed the whole name run, which also spans the next statements, so a later GO TO in that run was never seen. EPSCSMRI'sGO TO X000000CC … DEPENDING ONtargets all read as dead (~160 phantom dead units). The capture is now a lookahead.GO TO a b DEPENDING ON x GO TO y .is terminal. The DEPENDING exclusion now applies only when the final transfer is the DEPENDING one.XML PARSE … PROCESSING PROCEDURE A THRU Bnow counts as a reach of A..B.… END-XML GOBACK.no longer reads as falling through.siblings. The staleexcluded_programsreason in the DBB key is rewritten; that is its only data change.epscsmrd.cbl stays excluded (follow-up)
#4216 merged before this PR, so the exclusion is already on main. This PR makes the key able to hold the file but does not add it:
usage_statusmarks the same six headers. Its only miss is that it records no PROGRAM-ID for the file (PROGRAM-ID. 'EPSCSMRD'., quoted, column 9).draft→ insert the entry →cross_verify.py census→ground_truth_ledger.py update/assign.Tests
New:
test_program_spans_split_siblings_and_nested_programs,test_draft_keys_sibling_programs_with_their_own_units,test_score_places_engine_units_in_their_sibling_program,test_every_go_to_in_a_name_run_is_seen,test_xml_parse_processing_procedure_is_a_range_and_end_xml_closes_its_phrase,test_census_asks_about_sibling_programs_units_by_program. All five draft tests fail against origin/main's tool and pass here.Golden drift
None. No engine code changed, and the golden gate passes without a re-bless. Sibling bug-sweep PRs do re-bless golden masters, so if one merges first, merge main and re-bless (
crucible_check.py --update --yes). Never hand-merge the golden files.Gates
check: clean, no ledger change.pr_gates.py, run in chunks under a shared lock: lint, audits, secrets, xray, gauntlet and golden PASS. Suite: see the comment below.Closes #4206
🤖 Generated with Claude Code
https://claude.ai/code/session_013sNMtAg6s9dyyjNgnjRHi8