From 5040dea3580fe95492622924ac810ae6cee5049d Mon Sep 17 00:00:00 2001 From: Joe Esquibel Date: Mon, 31 Aug 2026 12:18:21 -0400 Subject: [PATCH] fix(cobol): func_start no longer mistakes LE service calls for paragraphs Closes #2538. `CEE3DMP.`/`CEEMOUT.`/`CEEDUMP.` (Language Environment runtime diagnostic calls) sitting alone on a line indented into Area B were counted as paragraph headers -- func_start's reserved-word shield had no entry for them, and the post-sequence-area whitespace slot tolerates any horizontal indent to support genuinely free-format source, so it can't distinguish Area A from Area B on its own. Traced #2489 (the previous func_start sequence-area hardening) to confirm this wasn't a deliberate decision -- that PR only fixed vertical-whitespace handling, unrelated to column position. Fix: add CEE3DMP/CEEMOUT/CEEDUMP to the reserved-word shield, the same low-risk pattern already used repeatedly in this file (CONTINUE, LOCAL-STORAGE, SOURCE-COMPUTER/OBJECT-COMPUTER). These three are already a recognized class elsewhere in cobol.py (the `telemetry` rule). A general Area-A column anchor was considered and deferred -- the existing sequence-area consumer can't reliably tell a genuine fixed-format sequence number from free-format leading spaces without file-level fixed/free-format detection, a bigger change than this bug warrants. Verification: reproduced the exact FP (5 matches for 3 real paragraphs, now 3), added cases to test_cobol.py/test_cobol_strict.py, full cobol + cross-language strict suites pass, audit_check.py clean, crucible_check.py both modes PASS against the full corpus with zero diffs (these tokens aren't present in the existing corpus). Co-Authored-By: Claude Sonnet 5 --- .../language_standards/languages/cobol.py | 22 ++++++++++++++++++- tests/extraction/languages/test_cobol.py | 3 +++ .../extraction/languages/test_cobol_strict.py | 8 +++++++ 3 files changed, 32 insertions(+), 1 deletion(-) diff --git a/gitgalaxy/standards/language_standards/languages/cobol.py b/gitgalaxy/standards/language_standards/languages/cobol.py index 0bdb91e1e..1059a15b0 100644 --- a/gitgalaxy/standards/language_standards/languages/cobol.py +++ b/gitgalaxy/standards/language_standards/languages/cobol.py @@ -142,7 +142,27 @@ # `CONTINUE.` is `.`, not a paragraph header. Confirmed FP against # language-crucible v1.2.0 (che-che4z_nist_ccvs85/IF4014.2.cbl:30 etc., # cobol-sample_SAMPLE1.cbl). Same class as LOCAL-STORAGE (#1890). - r"DELETE|OPEN|CLOSE|CONTINUE|PROGRAM-ID|CLASS-ID|SECTION|DIVISION|END-[A-Za-z0-9_-]+)(?=[ \t\n.]))" + r"DELETE|OPEN|CLOSE|CONTINUE|" + # #2538: CEE3DMP/CEEMOUT/CEEDUMP are Language Environment (LE) + # runtime diagnostic service names -- already recognized elsewhere + # in this file as the `telemetry` class (see that rule below) -- not + # paragraph names. A bare `CEE3DMP.` statement call sitting on its + # own line, indented into Area B, was being swept up as a paragraph + # header: this shield had no entry for them, and the post-sequence- + # area slot (`[ \t]*`, item 1 above) tolerates any horizontal + # indent to support genuinely free-format source, so it doesn't + # distinguish Area A (paragraph names, columns 8-11) from Area B on + # its own. Confirmed FP: `data/cobol/b.cpy` (che-che4z #1096 control + # corpus) planted `CEE3DMP.`/`CEEMOUT.` in Area B and both were + # captured as extra paragraphs (func_start=5 for 3 real paragraphs). + # Scoped narrowly to these three known LE tokens, same fix class as + # CONTINUE/LOCAL-STORAGE above, rather than a general Area-A column + # anchor: the sequence-area consumer in item 1 can't reliably tell + # a genuine fixed-format sequence number from 6 free-format leading + # spaces, so a real structural fix needs file-level fixed/free- + # format detection -- out of scope for this narrow token exclusion. + r"CEE3DMP|CEEMOUT|CEEDUMP|" + r"PROGRAM-ID|CLASS-ID|SECTION|DIVISION|END-[A-Za-z0-9_-]+)(?=[ \t\n.]))" # 4. THE DIVISION/SECTION HEADER SHIELD # Bans any word followed immediately by DIVISION (e.g., "PROCEDURE DIVISION"). # Upgraded to `[ \t\n]+` to prevent vertical ghosting. diff --git a/tests/extraction/languages/test_cobol.py b/tests/extraction/languages/test_cobol.py index bde3126a0..57510667d 100644 --- a/tests/extraction/languages/test_cobol.py +++ b/tests/extraction/languages/test_cobol.py @@ -66,6 +66,9 @@ " * TargetFunc.", # column-7 comment marker "123456* TargetFunc.", # column-7 comment with real sequence numbers " *> TargetFunc.", # free-format inline comment marker + "000600 CEE3DMP.", # #2538: LE diagnostic call, Area B, not a paragraph + "000700 CEEMOUT.", # #2538: LE diagnostic call, Area B, not a paragraph + " CEEDUMP.", # #2538: same LE-service class, free-format indent ], "pathological": [ ("TargetFunc \n SECTION.", "TargetFunc"), # carried-forward: margin-hugging + vertical split diff --git a/tests/extraction/languages/test_cobol_strict.py b/tests/extraction/languages/test_cobol_strict.py index a835bcc14..86c346d36 100644 --- a/tests/extraction/languages/test_cobol_strict.py +++ b/tests/extraction/languages/test_cobol_strict.py @@ -365,6 +365,11 @@ def test_cobol_func_start_excludes_reserved_verbs_and_headers(): WRITE, EXIT, GOBACK, STOP, DISPLAY, DIVISION, SECTION headers) -- these are false alarms from the sweep picking up func_start's own exclusion list text, not a real double-match risk. + + #2538 extends this same list: CEE3DMP/CEEMOUT/CEEDUMP (the `telemetry` + rule's LE runtime diagnostic service names) share the same "bare + token + period" shape as a paragraph header when indented into Area B, + with nothing in the old shield to exclude them. """ func_start = COBOL_RULES["func_start"] for reserved in ( @@ -375,6 +380,9 @@ def test_cobol_func_start_excludes_reserved_verbs_and_headers(): " PROCEDURE DIVISION.", " STOP RUN.", " GOBACK.", + " CEE3DMP.", + " CEEMOUT.", + " CEEDUMP.", ): assert not func_start.search(reserved), f"func_start incorrectly matched reserved line {reserved!r}"