Skip to content

rocq-elpi, coq-elpi: bound dune < 3.24 on the 16 released versions still using the (using coq) extension - #3819

Merged
gares merged 1 commit into
rocq-prover:masterfrom
JasonGross:claude/elpi-dune-324-bounds
Aug 6, 2026
Merged

rocq-elpi, coq-elpi: bound dune < 3.24 on the 16 released versions still using the (using coq) extension#3819
gares merged 1 commit into
rocq-prover:masterfrom
JasonGross:claude/elpi-dune-324-bounds

Conversation

@JasonGross

Copy link
Copy Markdown
Member

Bound dune < 3.24 on the 16 released rocq-elpi / coq-elpi versions whose sources still select the deleted coq dune-language extension.

Why

dune 3.24 removed the coq language extension, so any dune-project containing (using coq X.Y) now fails to parse — Error: Extension coq was deleted in the 3.24 version of the dune language — regardless of its own (lang dune ...). opam solves one dune version per switch, so a single uncapped recipe anywhere in a closure selects dune ≥ 3.24 for everything in it and breaks packages that never touch elpi.

This is the tail of a cap that has been applied three times already and keeps being escaped:

The failure this reproduces today, in the archive's own CI on a dev-prover job:

Error: Extension coq was deleted in the 3.24 version of the dune language

from rocq-elpi.3.4.0, which takes the whole mathcomp stack down with it. Capping only the newest version each time leaves the next one down to be selected; this closes the remaining released versions so there is nothing left to escape to.

What

One line per file, depends: only:

-  "dune" {>= "3.13"}
+  "dune" {>= "3.13" & < "3.24"}
  • released/packages/rocq-elpi/rocq-elpi.{2.5.0,2.5.1,2.5.2,2.6.0,3.0.0,3.1.0,3.2.0,3.3.0,3.3.1,3.4.0}/opam
  • released/packages/coq-elpi/coq-elpi.{2.2.0,2.2.1,2.2.2,2.2.3,2.3.0,2.4.0}/opam

Each file also contains ["dune" "subst"] {dev} and a bare "dune" in the build commands; both are left alone. git diff --numstat is 1 1 for all 16 files and lists nothing else.

rocq-elpi.3.5.0 is deliberately untouched — #3795 already capped it, and its depends: line was used as the byte-for-byte spelling control, so every line added here is character-identical to it.

coq-elpi 2.5.0 and later need no change: they are metapackages whose only dependencies are coq-core and rocq-elpi {= version}, so they inherit the cap.

Evidence each version is actually affected

dune-project was read out of all 16 release tarballs — the url { src: } target in each opam file, i.e. the tree opam actually builds, rather than a guess from a raw file URL. All 16 read:

(lang dune 3.13)
(using coq 0.8)

Nothing becomes unsatisfiable

No recipe anywhere in released/, core-dev/ or extra-dev/ requires dune >= 3.24 or newer — the search returns zero. 83 recipes on master already carry a < "3.24" upper bound, so this follows an established convention rather than introducing one. opam lint passes on all 16 directories under opam 2.1.2 (the version the archive CI pins), with an untouched sibling linted alongside as a baseline.

Scope

This is not an archive-wide sweep. 334 recipes still carry an uncapped dune dependency; most are unaffected because they use (using rocq ...), which dune 3.24 kept, but the ones that are affected are not addressed here.

🤖 Generated with Claude Code

https://claude.ai/code/session_01L9BGQT7XUuubV6C619DW4b

…ing the deleted (using coq) extension

dune 3.24 removed the `coq` dune-language extension, so any dune-project
containing `(using coq X.Y)` now fails to parse regardless of its own
`(lang dune ...)` version. opam solves one dune version per switch, so a
single uncapped recipe in a closure selects dune >= 3.24 for everything
in it and breaks packages that never touch elpi.

This is the tail of a cap that keeps being escaped: rocq-prover#3806 capped
rocq-elpi.dev, after which the solver chose rocq-elpi 3.5.0; rocq-prover#3795 capped
3.5.0, after which it chose 3.4.0. 3.4.0 is uncapped, as is every
released rocq-elpi below it, and it is currently failing in the archive's
own CI with

  Error: Extension coq was deleted in the 3.24 version of the dune language

taking the mathcomp stack down with it. Capping only the newest version
each time leaves the next one down to be selected, so this closes the
remaining released versions.

The affected dune-project files were read out of all 16 release tarballs
-- the url { src: } target in each opam file, i.e. the tree opam actually
builds -- rather than guessed from the opam metadata. All 16 read
`(lang dune 3.13)` / `(using coq 0.8)`.

rocq-elpi.3.5.0 is deliberately untouched; rocq-prover#3795 already capped it, and
its depends: line was the byte-for-byte spelling control here. coq-elpi
2.5.0 and later need no change either: they are metapackages depending
only on coq-core and rocq-elpi {= version}, so they inherit the cap.

Nothing becomes unsatisfiable -- no recipe in released/, core-dev/ or
extra-dev/ requires dune >= 3.24 -- and 83 recipes on master already
carry this same upper bound. This is not an archive-wide sweep: other
affected packages remain uncapped and are not addressed here.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01L9BGQT7XUuubV6C619DW4b
@gares
gares merged commit c233921 into rocq-prover:master Aug 6, 2026
0 of 2 checks passed
JasonGross added a commit to JasonGross/opam-coq-archive that referenced this pull request Aug 6, 2026
e64b42b and efc9444 tightened six of this branch's new .dev rows. Four
were left: coq-comp-dec-modal.dev, coq-coqtail.dev, coq-hanoi.dev and
coq-waterproof.dev. All four are rows THIS branch adds -- none exists at
upstream/master (`git cat-file -e upstream/master:<path>` fails for all
four) -- so their prover lines are ours to get right.

  coq-comp-dec-modal.dev  "coq" {>= "8.16"}                 -> {= "dev"}
  coq-coqtail.dev         "coq" {>= "8.17"}                 -> {= "dev"}
  coq-hanoi.dev           "coq" {(>= "9.1")}                -> {= "dev"}
  coq-waterproof.dev      "coq" {>= "9.0" & < "9.1" | = "dev"} -> {= "dev"}

The added line is byte-identical in all four to the eight rows already
tightened (2-space indent, `  "coq" {= "dev"}`); coq-bits.dev:20 was the
spelling control. `git diff --numstat` is `1  1` on exactly these four
files and lists nothing else. opam 2.1.2 -- the version the archive CI
pins -- lints all four package directories at rc=0.

WHAT THIS ACHIEVES, AND IT IS NARROW: it converts false greens into honest
skips. It fixes none of these packages' real breaks.

THE FALSE GREENS, from the 4.09.0 job (7695087)

That job's succeeded-to-install bucket at :5294 lists comp-dec-modal,
coqtail and waterproof. None of the three resolved a dev prover:

  coq-comp-dec-modal   coq 8.16.dev   [required by coq-comp-dec-modal]
  coq-coqtail          coq 8.20.dev   (+ coq-core/coq-stdlib/coqide-server)
  coq-waterproof       rocq-core 9.0.dev, rocq-runtime 9.0.dev,
                       coq-core 9.0.dev, coqide-server 9.0.dev

So a `.dev` row in a `dev` repository reported green having built against a
released prover. That is the defect; the floor is what permits it.

The criterion is NOT "the prover line is loose". A loose floor of `>= 9.1`
still resolves 9.1+rc1, which requires `ocaml >= 4.14.0`, so it excludes
4.09.0 exactly as a pin would. The floor has to reach back to a prover old
enough to build on the job's compiler. That is why 8.16 / 8.17 / 9.0 go
false-green here and `>= 9.1` does not.

coq-hanoi is the row that shows it: its `{(>= "9.1")}` was loose and it
skipped anyway. opam's own conflict report above the Skipping line reads
`coq >= 9.1 -> coq-core = 9.1+rc1 -> rocq-runtime = 9.1+rc1 -> ocaml >=
4.14.0`. hanoi is already in the free bucket at :5296, so this edit changes
nothing about its behaviour on any current job -- it is criterion
consistency, not a fix.

coq-waterproof IS A SEMANTIC CHANGE, NOT A FLOOR BUMP

Its line was `{>= "9.0" & < "9.1" | = "dev"}` -- it already had a dev arm.
Tightening deletes the released arm, and the named witness for why is that
the solver actually took that arm: on 4.09.0 the plan reads `install coq
9.0.dev [required by coq-waterproof]`. That plan is also internally mixed
-- rocq-runtime/rocq-core/coq-core/coqide-server at 9.0.dev alongside
rocq-stdlib 9.1.0 and coq-stdlib 9.1.0 -- so the released arm was not
merely selecting an older prover, it was selecting a combination nobody
tests.

After this change coq-waterproof.dev is unsatisfiable on any job whose
compiler cannot build a dev prover, instead of resolving to 9.0. That is
the intended outcome for a `.dev` row and it is free in the CI gate: the
harness's *not compatible with the current compiler* bucket does not set
RC=1. In scripts/opam-coq-install-remove the four buckets are printed at
:101-104, and `RC=1` appears on exactly two paths -- :67 with FAILURES and
:83 with HARDFAILURES. The UNTESTED path at :86 sets nothing.

NO ROW BECOMES A HARD FAILURE

Checked per row rather than argued: on both 4.14.2 (7695088) and 5.3.0
(7695089), all four rows resolve `coq dev`, with the `coq` line reading
`[required by <the row>]` in each of the eight plans. Neither job has any
member in the not-compatible or can-never-be-installed buckets (:4727/:4728
and :4920/:4921 are both empty). So the tightening cannot move a row into
*can never be installed*.

THE REAL BREAKS, WHICH THIS COMMIT DOES NOT TOUCH

Measured on 7695088 (4.14.2), where all four are in the failed bucket:

  comp-dec-modal  its dependency rocq-elpi.3.4.0 fails to compile (:2856,
                  inside comp-dec-modal's own install block :2847-:2881):
                  `(using coq 0.8)` / "Extension coq was deleted in the
                  3.24 version of the dune language". Addressed separately
                  by the dune < 3.24 caps in rocq-prover#3819.
  coqtail         its own tree: Complex/Canalysis_def.vo, Error 1 (:3001).
  hanoi           its own tree: extra.v:225, "The LHS of subn_eq0
                  (_ - _ == 0) does not match any subterm of the goal".
  waterproof      its own dune-project line 2, same dune 3.24 message as
                  above -- here in waterproof's source, not a dependency.

All four remain red after this change. The claim of this commit is only
that they are red for their real reasons on every compiler, rather than
green on 4.09.0 against a prover the row was never meant to admit.

CORRECTION TO e64b42b (pushed; corrected here rather than amended)

Two errors in that commit's message. Neither affects any recipe, on this
branch or elsewhere; both were found by review, and the second is mine.

1. "coq-stalmarck and coq-stalmarck-tactic ... are exactly the rows the
   4.09.0 job skips" -- the first clause is right, the "exactly" is wrong.
   The skip bucket has six members, enumerated by the job itself at
   7695087:5296: coq-cds4ltl, coq-hanoi, coq-mathcomp-abel,
   coq-mathcomp-apery, coq-stalmarck-tactic, coq-stalmarck.

2. The heading "THIS IS THE FIX FOR THE 4.09.0 CI JOB" covers four of the
   six rows that commit edits, not six. coq-mathcomp-abel and
   coq-mathcomp-apery were already skipping before it, so for them
   `{= "dev"}` is a 4.09.0 no-op. (The section body underneath was already
   correctly scoped to four.)

The skip bucket splits three ways, not two, with every binding edge below
quoted from opam's conflict report above the corresponding Skipping line in
7695087:

  (a) prover-driven, already tight -- the control, and it holds
      coq-stalmarck, coq-stalmarck-tactic:
      `coq >= dev -> coqide-server >= dev -> rocq-runtime >= dev
       -> ocaml >= 4.14.0`
  (b) prover-driven, loose, and skipping anyway
      coq-cds4ltl: `rocq-core >= 9.1 -> rocq-runtime = 9.1+rc1
                    -> ocaml >= 4.14.0`
      coq-hanoi:   `coq >= 9.1 -> coq-core = 9.1+rc1
                    -> rocq-runtime = 9.1+rc1 -> ocaml >= 4.14.0`
  (c) dependency-driven -- the prover line is irrelevant
      coq-mathcomp-abel:  `coq-mathcomp-ssreflect >= 2.4 -> ...
                           -> coq-elpi >= 2.0 -> ocaml >= 4.10.0`
      coq-mathcomp-apery: `coq-coqeal >= 2.1.0 -> coq-elpi >= 2.4.1
                           -> rocq-elpi < 2.5.1 -> ocaml >= 4.10.0`

Class (b) is why the criterion above is stated as reach-back rather than
looseness: describing it as looseness overstates the affected set by two
rows on this very job.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01L9BGQT7XUuubV6C619DW4b
@JasonGross
JasonGross deleted the claude/elpi-dune-324-bounds branch August 7, 2026 03:36
JasonGross added a commit to JasonGross/opam-coq-archive that referenced this pull request Aug 11, 2026
…v rows using the deleted (using coq) extension

These are two of the five rows failing in this PR's own CI, and the only
two with a recipe-side fix. Both die at line 2 of their dune-project,
before anything is compiled:

  Error: Extension coq was deleted in the 3.24 version of the dune language

CI resolved dune 3.24.2 for them because neither recipe had an upper
bound. Read out of the trees the two url { src: } targets actually name:

  rocq-community/stalmarck#master   (lang dune 2.8) / (using coq 0.3)
  impermeable/coq-waterproof#main   (lang dune 3.8) / (using coq 0.8)

so each existing floor already matches its own (lang dune ...) line and
only the ceiling was missing.

Same shape and same spelling as rocq-prover#3819, which capped the 16 released elpi
rows. Nothing becomes unsatisfiable: rocq-runtime.dev and rocq-core.dev
both ask for "dune" {>= "3.21"}, and rocq master's own dune-project is
(lang dune 3.21), so 3.21-3.23.x satisfies the prover and both rows.

These are the only two of the 13 rows this branch adds that depend on
dune at all; the sibling coq-stalmarck.dev is make-driven and needs
nothing. The other three CI failures are source breaks in the packages
themselves and are not addressed here.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01L9BGQT7XUuubV6C619DW4b
JasonGross added a commit to JasonGross/opam-coq-archive that referenced this pull request Aug 11, 2026
dune 3.24 deleted the `coq` dune-language extension, so a `dune-project`
containing `(using coq X.Y)` no longer parses regardless of its own
`(lang dune ...)`. Both rows are built from `apps/json/` and `apps/xml/`
of the coq-elpi tree, whose `dune-project` carries `(using coq 0.8)`.
opam solves one dune version per switch, so an uncapped recipe in a
closure can select dune >= 3.24 for everything in it.

Same spelling as the caps already merged for the released rows
(rocq-prover#3806, rocq-prover#3819). Satisfiable: `rocq-elpi`, which both rows depend on,
already asks `dune {>= "3.13" & < "3.24"}`, and `rocq-core.dev` /
`rocq-runtime.dev` ask `dune {>= "3.21"}`, so 3.21-3.23.x satisfies the
whole closure. `opam lint` passes on both files.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01L9BGQT7XUuubV6C619DW4b
gares pushed a commit that referenced this pull request Aug 12, 2026
dune 3.24 deleted the `coq` dune-language extension, so a dune-project
containing `(using coq X.Y)` no longer parses whatever its own
`(lang dune ...)` says. opam solves one dune version per switch, so an
uncapped recipe in a closure can select dune >= 3.24 for everything in it.

rocq-elpi-json and rocq-elpi-xml are built out of the same coq-elpi
release tarballs as rocq-elpi -- apps/json/ and apps/xml/ of that tree --
so they are hit by exactly the same defect, and they were missed by every
cap so far because they are missed by name: 34f82e5 capped
rocq-elpi.3.5.0, #3806 capped rocq-elpi.dev, and #3819 capped the
remaining 16 released rocq-elpi/coq-elpi rows, leaving 18 capped rows at
master and these 5 uncapped.

The dune-project files were read out of the three release tarballs these
5 rows name in their own `url { src: }` -- v3.3.1, v3.4.0, v3.5.0 -- not
guessed from opam metadata. All three read `(lang dune 3.13)` on line 1
and `(using coq 0.8)` on line 2.

The cap is satisfiable: rocq-elpi, which every one of these rows depends
on, already asks for `dune {>= "3.13" & < "3.24"}`, and rocq-core.dev /
rocq-runtime.dev ask `dune {>= "3.21"}`, so 3.21-3.23.x satisfies the
whole closure.

Not touched, deliberately: the coq-elpi rows at 2.5.0 and above are
metapackages that depend on rocq-elpi and have no dune dependency and no
build, and the coq-elpi rows below 2.2.0 have no dune dependency either.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01L9BGQT7XUuubV6C619DW4b
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.

2 participants