feat(core-engine): jcl sync_locks counts the exclusive-ENQ dispositions (#2733) - #2742
Merged
Merged
Conversation
…ns (#2733) #2733 was filed as a design question with two acceptable outcomes. Taking option (a): add the narrowed rule and accept the documented overlap with io. DISP=OLD and DISP=MOD request an exclusive system ENQ on a dataset; DISP=SHR requests shared access. That is a lock acquisition declared in the job deck -- the construct sync_locks already measures through each language's own idiom (cobol's EXEC CICS ENQ, abap's ENQUEUE_/DEQUEUE_, solidity's nonReentrant). Declining would have left z/OS's only native serialization construct unmeasured for the whole language. #2610's rejection of a cleanup rule on DISP=(...,DELETE/CATLG) does not carry over: a second-positional disposition rides along on essentially every DISP=, so that rule would have re-counted the whole operand. This shape is 48 of the corpus's 525 DISP= occurrences (~9%), across 15 of 186 files -- SHR (429) is the shared-access default every job asks for and NEW (48, including an omitted first positional) is an allocation, not contention over an existing resource. The residual overlap is real and accepted, which is the engine's existing posture where the meanings genuinely differ: jcl's own COND=((4,LT),EVEN) counts safety AND safety_bypasses, haskell's finally counts cleanup and safety. test_jcl_sync_locks_overlaps_io_by_design pins it so a later change re-makes the decision rather than drifting silently. Golden masters re-blessed: 15 differences per mode, all Thread Synchronization Locks on those same 15 jcl files, summing to 48. No other language moved and no topology ripple. Also corrects docs/language_status/jcl.md, whose §3 was missing dead_code and spec_exposure (added by #2732, never documented) and whose §6 strict-test count was stale at 65. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Contributor
squid-protocol
added a commit
that referenced
this pull request
Sep 5, 2026
Conflict was confined to the two golden-master fixtures, both auto-generated: #2742 (jcl sync_locks) re-blessed them on main while this branch was in flight. Resolved per .agents/skills/ci-push-checklist section 6 -- never hand-merge a generated file: took origin/main's version of both to clear the markers, then re-ran `crucible_check.py --update --yes` so they are recalculated from the merged code rather than stitched together. Verified the resolution rather than trusting the regen: re-attributed the regenerated fixtures against origin/main and got the same 3384-diff profile as before the merge, bucket for bucket (2120 topology X/Y/Z, 300 API Exposure, 257 Documentation Exposure, 255 Public Exports, 255 Structural Magnitude, 197 roll-ups) and the same per-language counts. `jcl` appears nowhere in the per-file diffs, which is the positive check that #2742's blessing survived intact instead of being overwritten. Both modes PASS, full suite 7625 passed serially, audit_check and tree-sitter-accuracy audit clear. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WfeHRWra1d6Z5uSReFajSq
This was referenced Sep 5, 2026
squid-protocol
added a commit
that referenced
this pull request
Sep 5, 2026
…ution narrowed to the command executors (#2748–#2751) (#2755) * feat(core-engine): jcl api, cleanup and globals rules, high_risk_execution narrowed to executors (#2748, #2749, #2750, #2751) Four rosetta gaps in one language, found by the 2026-09-05 pass over every non-green cell of the keyword-rosetta bias report and filed as #2748-#2751. - api: `//name PROC` -- a cataloged or in-stream procedure is the callable surface `EXEC name` / `EXEC PROC=name` invokes (api contract, fallback family). 13 declarations in 13 crucible files; 185 of 376 EXEC steps call one. - cleanup: DELETE as a dataset's normal-termination disposition (`DISP=(MOD,DELETE,DELETE)`, `(OLD,DELETE)`, `(,DELETE)`) -- JCL's teardown idiom. #2610 declined it for the io overlap; #2742 reversed that posture for sync_locks and the same narrow-subset measurement applies (36 of 533 DISP=). The abend-only positional of an allocation is excluded. - globals: JOBLIB (vs STEPLIB), a job-level SET symbol (vs a PROC parameter) and EXPORT SYMLIST -- the scoped-vs-global distinction the ledger said JCL lacked. SET is dual globals+state_mutation, dockerfile's ENV shape. - high_risk_execution: a bare `PGM=` counted every step (188 of 376 crucible EXECs, IEFBR14 and the compilers included). Narrowed to the programs that execute caller-supplied commands: IKJEFT01/1A/1B, BPXBATCH/BPXBATSL/BPXBATA2/ BPXBATA8/AOPBATCH, IRXJCL, SDSF. 61 hits in 48 files after. 20 new strict cases: per-rule partitions, overlap pins (io/sync_locks/state), an end-to-end deck through prism + splice, ReDoS detonations. Docs: jcl status sections 1/3/4/6/10 and the api contract's fallback family + audit table. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> * test(core-engine): re-bless the golden masters for the jcl rule changes (#2748-#2751) Both fixtures regenerated with crucible_check.py --update. Every substantive difference is in jcl files or jcl directory aggregates (zero off-target files); the rest is the corpus-wide topological re-solve. Field breakdown and direction of change are in the PR description. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> * test(core-engine): re-bless the golden masters on top of #2754's orphan-census fix Main re-blessed for #2754 after this branch's first bless, so the fixtures conflicted. Merged main (taking its fixtures) and regenerated both from the merged tree. Scoped against main: 893 differences, 428 topological, 465 substantive -- all jcl files / jcl aggregates plus the two corpus-wide health averages they feed; zero off-target files. Same shape as the first bless. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> --------- Co-authored-by: Joe Esquibel <squid-protocol@users.noreply.github.com> Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #2733.
The call
#2733 was filed as a design question with two acceptable outcomes: add the narrowed rule and accept
a documented overlap with
io, or decline it per #2610'scleanupprecedent. Taking option (a).DISP=OLDandDISP=MODrequest an exclusive system ENQ on a dataset;DISP=SHRrequests sharedaccess. That is a lock acquisition declared in the job deck — the same thing
sync_locksmeasuresthrough each language's own idiom elsewhere (cobol's
EXEC CICS ENQ, abap'sENQUEUE_/DEQUEUE_,solidity's
nonReentrant). Declining would have left z/OS's only native serialization constructunmeasured for the whole language.
Why the #2610 precedent doesn't carry over
#2610 rejected
cleanuponDISP=(...,DELETE/CATLG)because a second-positional disposition ridesalong on essentially every
DISP=, so the rule would have re-counted the whole operand. Themeasured spread on the language-crucible corpus says this shape is a different animal:
DISP=formsync_locksDISP=SHR(incl.DISP=(SHR)DISP=(NEW,…)/ omitted first positional (DISP=(,PASS))DISP=OLD/DISP=(OLD,…)DISP=(MOD,…)48 hits across 15 of the corpus's 186
.jcl/.prc/.bmsfiles.SHRis the shared-access defaultevery job asks for and
NEWis an allocation, not contention over an already-existing resource —neither declares a serialization decision, so neither counts.
The residual overlap is real (every
sync_lockshit is also aniohit) and is accepted rather thanavoided, which is the engine's existing posture where the meanings genuinely differ: jcl's own
COND=((4,LT),EVEN)deliberately countssafetyandsafety_bypasses, and haskell'sfinallycounts
cleanupandsafety.test_jcl_sync_locks_overlaps_io_by_designpins the overlap so alater change makes it a decision again rather than a silent drift.
Verification
test_jcl.py+test_jcl_strict.py: 117 passed (strict suite 74 → 80). New cases cover theOLD/MOD-vs-SHR/NEW partition,
DISPOSITION=OLD/DISP=OLDER/ aPARM='OLDMODE'value asnon-dispositions, the
//continuation-line shape, the io overlap, and ReDoS detonation.code-stream counts (no comment-stream leakage). Same 48 end-to-end through
StructuralExtractor.coding_analysis.crucible_check.py: 15 differences per mode before the bless, all of themThread Synchronization Lockson those same 15 jcl files, summing to 48. No other language movedand no topology ripple — the diff was fully surfaced, well under the 50-diff print cap. Golden
masters re-blessed.
ruff_audit.py --ci/mypy_audit.py --ci: no new findings beyond baseline.tri_comparison_chart.py --all --ci: 3 languages, all OK.tree_sitter_accuracy_audit.py --ci --all: 30 languages, all OK. (Neither covers jcl — it has no tree-sitter grammar or ctagssupport — but both gate this file.)
_calc_concurrencyand the Race Condition Radar are both no-ops for jcl (concurrencyisNone),so the new signal changes the signal counts and the defense surface, not a risk score.
Also in here
docs/language_status/jcl.md§3 was missingdead_codeandspec_exposure(added by #2732, neverdocumented) and §6's strict-test count was stale at 65. Both corrected alongside the
sync_locksentry, with the growth attributed per-issue.
Owed follow-up (corpus side, not this PR)
The keyword-rosetta jcl probe corpus has no
DISP=OLDplant (0 hits there today), and the ledgerentry
jcl-sync-locks-disp-enq-questionis stillupstream-question. Per the no-pins flow theengine merges first, so a follow-up keyword-rosetta PR owes: a paired
DISP=OLDplant per GATING,the manifest re-bless against main, and flipping that entry to record this decision.
🤖 Generated with Claude Code