Skip to content

feat(core-engine): jcl sync_locks counts the exclusive-ENQ dispositions (#2733) - #2742

Merged
squid-protocol merged 1 commit into
mainfrom
fix/2733-jcl-sync-locks-disp-enq
Sep 5, 2026
Merged

feat(core-engine): jcl sync_locks counts the exclusive-ENQ dispositions (#2733)#2742
squid-protocol merged 1 commit into
mainfrom
fix/2733-jcl-sync-locks-disp-enq

Conversation

@squid-protocol

Copy link
Copy Markdown
Owner

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's cleanup precedent. Taking option (a).

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 same thing sync_locks measures
through each language's own idiom elsewhere (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.

"sync_locks": re.compile(r"\bDISP=\(?(?:OLD|MOD)\b", re.I),

Why the #2610 precedent doesn't carry over

#2610 rejected cleanup on DISP=(...,DELETE/CATLG) because a second-positional disposition rides
along on essentially every DISP=, so the rule would have re-counted the whole operand. The
measured spread on the language-crucible corpus says this shape is a different animal:

DISP= form occurrences counted as sync_locks
DISP=SHR (incl. DISP=(SHR) 429 no
DISP=(NEW,…) / omitted first positional (DISP=(,PASS)) 48 no
DISP=OLD / DISP=(OLD,…) 17 yes
DISP=(MOD,…) 31 yes
total 525 48 (~9%)

48 hits across 15 of the corpus's 186 .jcl/.prc/.bms files. SHR is the shared-access default
every job asks for and NEW is an allocation, not contention over an already-existing resource —
neither declares a serialization decision, so neither counts.

The residual overlap is real (every sync_locks hit is also an io hit) and is accepted rather than
avoided, which is the engine's existing posture where the meanings genuinely differ: jcl's own
COND=((4,LT),EVEN) deliberately counts safety and safety_bypasses, and haskell's finally
counts cleanup and safety. test_jcl_sync_locks_overlaps_io_by_design pins the overlap so a
later 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 the
    OLD/MOD-vs-SHR/NEW partition, DISPOSITION=OLD / DISP=OLDER / a PARM='OLDMODE' value as
    non-dispositions, the // continuation-line shape, the io overlap, and ReDoS detonation.
  • Isolated rule probe over real Prism code streams: 48 hits / 15 files, identical raw-file and
    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 them
    Thread Synchronization Locks on those same 15 jcl files, summing to 48. No other language moved
    and no topology ripple — the diff was fully surfaced, well under the 50-diff print cap. Golden
    masters re-blessed.
  • Full suite: 7605 passed, 3 skipped, 9 xfailed.
  • 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 ctags
    support — but both gate this file.)

_calc_concurrency and the Race Condition Radar are both no-ops for jcl (concurrency is None),
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 missing dead_code and spec_exposure (added by #2732, never
documented) and §6's strict-test count was stale at 65. Both corrected alongside the sync_locks
entry, with the growth attributed per-issue.

Owed follow-up (corpus side, not this PR)

The keyword-rosetta jcl probe corpus has no DISP=OLD plant (0 hits there today), and the ledger
entry jcl-sync-locks-disp-enq-question is still upstream-question. Per the no-pins flow the
engine merges first, so a follow-up keyword-rosetta PR owes: a paired DISP=OLD plant per GATING,
the manifest re-bless against main, and flipping that entry to record this decision.

🤖 Generated with Claude Code

…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>
@github-actions

github-actions Bot commented Sep 5, 2026

Copy link
Copy Markdown
Contributor

🐦‍⬛ Muninn Security Scan

✅ No security issues found.

🐦‍⬛ Powered by Muninn · Skald Lab

@squid-protocol
squid-protocol merged commit 1e53533 into main Sep 5, 2026
31 checks passed
@squid-protocol
squid-protocol deleted the fix/2733-jcl-sync-locks-disp-enq branch September 5, 2026 13:01
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
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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

jcl: sync_locks — DISP=OLD/MOD is JCL's exclusive-ENQ serialization idiom, but DISP= already feeds io (design question)

1 participant