Skip to content

extra-dev: add 46 dev recipes and update 5 more, for packages that do not yet install (on top of #3809) - #3812

Draft
JasonGross wants to merge 54 commits into
rocq-prover:masterfrom
JasonGross:dev-packages-needing-ports
Draft

extra-dev: add 46 dev recipes and update 5 more, for packages that do not yet install (on top of #3809)#3812
JasonGross wants to merge 54 commits into
rocq-prover:masterfrom
JasonGross:dev-packages-needing-ports

Conversation

@JasonGross

@JasonGross JasonGross commented Aug 6, 2026

Copy link
Copy Markdown
Member

Stacked on #3809 — merge that one first.

#3809 keeps the 45 recipes whose packages install; this PR carries the 43 that do not. Its diff also includes #3809 because several recipes here depend on recipes there, including coq-mathcomp-cad on the mathcomp-analysis family, rocq-sims on coq-ctree, and rocq-marble on rocq-listz.

These red .dev recipes are useful because most affected packages have a live release capped below Rocq master. Without a recipe tracking the default branch, breakage is not found until someone attempts a release against 9.3. The recipes identify the first failure for each package on every archive run.

The results are a lower bound: a compiler stops at the first error, and only 14 of these 43 packages have had their own sources compiled. The other 29 stopped in a dependency or sibling first. A source census for one known 9.3 break found 183 sites in 10 repositories behind these recipes, but only one repository reports that break as its first error. Seven of the other nine are behind elpi, interval, finmap, or deriving blockers; one is behind an earlier error in its own package; and one is in a green package behind a depopts: gate that CI never enables.

Failure ledger

The driver records what changed, rather than merely where the error surfaced. For Rocq-driven rows, Rocq version is the first tag containing the responsible commit (git tag --contains <sha> | sort -V | head -1). visible-now means the reported error is in the package's own sources; latent means its sources have not been measured because a dependency or sibling failed first. A blocked row therefore remains unknown (blocked) rather than inheriting its blocker's driver.

package driver Rocq version visibility
coq-vst-lib unknown (blocked) latent — stops at rocq-elpi
rocq-categories unknown (blocked) latent — stops at rocq-elpi; 1 of site unreached
rocq-elpi-json unknown (blocked) latent — stops at rocq-elpi
rocq-elpi-xml unknown (blocked) latent — stops at rocq-elpi
rocq-navi unknown (blocked) latent — stops at rocq-elpi; 4 of sites, all in examples/ behind {with-test}
rocq-partial-orders unknown (blocked) latent — stops at rocq-elpi; 147 of sites unreached
coq-infotheo unknown (blocked) latent — stops at coq-interval; 20 of sites unreached
rocq-infotheo unknown (blocked) latent — stops at coq-interval; the same 20 sites
rocq-laproof unknown (blocked) latent — stops at coq-interval
rocq-num-analysis unknown (blocked) latent — stops at rocq-mathcomp-finite-group, and capped at < 9.2~
rocq-num-analysis-algebra unknown (blocked) latent — same
rocq-num-analysis-fem unknown (blocked) latent — same
rocq-num-analysis-lax-milgram unknown (blocked) latent — same
rocq-num-analysis-lebesgue unknown (blocked) latent — same
rocq-num-analysis-subset unknown (blocked) latent — same
coq-mathcomp-cad unknown (blocked) latent — stops at rocq-mathcomp-finmap; 2 of sites unreached
rocq-rouche-capelli § unknown (blocked) latent — stops at rocq-mathcomp-finmap; latent content since measured: 1 of site and a goal-order break behind it
coq-ssprove unknown (blocked) latent — stops at coq-deriving; 2 of sites unreached
rocq-ssprove unknown (blocked) latent — stops at coq-deriving; the same 2 sites
rocq-hollight-logic unknown (blocked) latent — stops at coq-mathcomp-classical
rocq-hollight-logic-unif unknown (blocked) latent — stops at coq-mathcomp-classical
coq-coinduction inherited — shim see rocq-coinduction n/a — no sources of its own
coq-color inherited — shim see rocq-color n/a — no sources of its own
coq-trocq-hott-examples unknown (blocked) latent — stops at coq-trocq-hott
coq-trocq-std-examples unknown (blocked) latent — stops at coq-trocq-std
rocq-concert-examples unknown (blocked) latent — stops at rocq-concert
rocq-sims unknown (blocked) latent — stops at coq-ctree, and after the rename at rocq-ctree
rocq-typed-extraction none found was unsatisfiable, so latent in CI; built clean locally against 9.4+alpha, 13/13 .v
rocq-typed-extraction-plugin Rocq V9.3+rc1#21955, ba476414d4 was unsatisfiable; fix verified locally by building past it
coq-pprint toolchain — (dune 3.24) visible-now
coq-sflib toolchain — (dune 3.24) visible-now
rocq-ceres-bytestring toolchain — (dune 3.24) visible-now
coq-ctreerocq-ctree packaging visible-now — renamed in this PR; three further drivers sit behind the rename, none reached
coq-hol-light dependency visible-now
rocq-concert dependency — (plan resolved rocq-core 9.1.dev) visible-now
rocq-mathcomp-hollight-real-with-N Rocq V9.3+rc1#21611, e6a2fb9b2f visible-now — the only of break the archive has actually seen
rocq-robot-rocq dependency — (mathcomp 2.6) visible-now — 1 of site still latent behind angle.v:126
coq-trocq-hott Rocq (presumed) — no PR identified undetermined visible-now
coq-trocq-std Rocq V9.3+rc1#21947, 1fc7ef04ed visible-now
rocq-marble Rocq + dependency V9.3+rc1#21987, eebacb3bb1Rocq half only visible-now
rocq-coinduction recipe n/a (recipe) visible-now (4.09.0 only) — fixed in this PR
rocq-color recipe n/a (recipe) visible-now (4.09.0 only) — fixed in this PR
coq-vcfloat recipe n/a (recipe) visible-now (4.09.0 only) — not fixed; see below

rocq-marble has two independent drivers. The version covers only its Rocq driver.

§ rocq-rouche-capelli was built past its blocker locally. It has two independent breaks: the of site and a rewrite goal-order break that appears only after fixing of. Other latent rows remain unmeasured.

‡ Five of the six rocq-num-analysis* recipes cap rocq-core at < "9.2~"; the sixth inherits that through {= version}. Clearing their blocker still would not put them on master.

Blocked and unsatisfiable packages

Twenty-one packages never reached their own build. Their blockers were:

blocker fails at blocker's driver blocker's version packages it hides
rocq-elpi.3.4.0dune-project says (using coq 0.8), deleted in dune 3.24 dune build -p rocq-elpi toolchain dune 3.24 coq-vst-lib, rocq-categories, rocq-elpi-json, rocq-elpi-xml, rocq-navi, rocq-partial-orders
coq-interval.dev † — ocamlfind: Package 'coq-core.engine' not found ./configure Rocq, twice V9.3+rc1#21955 ba476414d4; 9b1424650d (also V9.3+rc1) is the second driver behind it coq-infotheo, rocq-infotheo, rocq-laproof
rocq-mathcomp-finite-group.devmorphism.v:3, Required library ssreflect matches several files in path make -C finite_group packaging mathcomp 2.5.0 (#1415) the six rocq-num-analysis* packages
rocq-mathcomp-finmap.devfinperm.v:160, The reference index_inj was not found make -j2 dependency mathcomp 2.5.0 (#1430) coq-mathcomp-cad, rocq-rouche-capelli
coq-deriving.0.2.3theories/base.v:3, same matches several files make packaging mathcomp 2.5.0 (#1415) coq-ssprove, rocq-ssprove
coq-mathcomp-classical.1.15.0 make -C classical undetermined undetermined rocq-hollight-logic, rocq-hollight-logic-unif

rocq-elpi.3.4.0, coq-deriving.0.2.3, and coq-mathcomp-classical.1.15.0 are released packages from the main archive, so this PR cannot fix them.

The mathcomp 2.5.0 split of mathcomp-ssreflect into mathcomp-boot and mathcomp-order (math-comp#1415) permits old and new layouts to be co-installed. For example:

rocq-num-analysis-algebra.dev:  rocq-mathcomp-boot dev  +  rocq-mathcomp-ssreflect 2.4.0
coq-ssprove.dev:                rocq-mathcomp-boot dev  +  coq-mathcomp-ssreflect  2.3.0

This makes Require ssreflect ambiguous. rocq-mathcomp-finite-group.dev itself is not broken: math-comp d5507be, finite_group/ built against a dev stack, 10/10 .v.vo, with no source changes. A conflicts: on rocq-mathcomp-boot against {coq,rocq}-mathcomp-ssreflect {< "2.5~"} would turn these into solver errors, but the six rocq-num-analysis* packages behind it would remain capped below master and unmeasured.

rocq-mathcomp-finmap.dev also permits ("coq-mathcomp-ssreflect" {>= "2.2" & < "2.4~"} | "rocq-mathcomp-ssreflect" {>= "2.4"}); under coq-mathcomp-cad.dev, the solver chose coq-mathcomp-ssreflect 2.2.0. Its source uses index_inj, absent at 2.4.0 and present at 2.5.0 (boot/seq.v:1453) and dev (boot/seq.v:1484). Raising the floor to 2.5.0 clears this error, but the result was not built and may reveal another.

coq-mathcomp-classical.1.15.0 could not be attributed because the trace omits the failing line. Its plan includes rocq-core dev, while coq-mathcomp-classical.dev and rocq-mathcomp-classical.dev both pass on the same job, so the two blocked packages need a version-bound change rather than a source port. The later Hollight commits move the relevant constraint to coq-mathcomp-ssreflect.

Six more packages are blocked by recipes in this PR: coq-coinduction, coq-color, coq-trocq-hott-examples, coq-trocq-std-examples, rocq-concert-examples, and rocq-sims.

rocq-typed-extraction.dev and rocq-typed-extraction-plugin.dev were unsatisfiable because they require rocq-elm-extraction {= version} and rocq-rust-extraction {= version}, but neither dependency had a .dev recipe:

[ERROR] Package conflict!
  * Missing dependency:
    - rocq-elm-extraction >= dev
    no matching version

The final commit adds both missing recipes. This turns an unsatisfiable dependency into an ordinary build result; it does not make the whole stack green.

Packages that reached their own build

package first error
coq-pprint dune-project:3 (using coq 0.8) — dune 3.24 deleted the Coq Build Language
coq-sflib dune-project:4 (using coq 0.8) — same
rocq-ceres-bytestring dune-project:2 (using coq 0.2) — same
coq-ctree I don't know about package coq-ctree (passed through --only-packages) / Hint: did you mean rocq-ctree?
coq-hol-light mappings.vUnable to unify "forall x : ?A, ?f x = ?g x" with ...
rocq-concert execution/test/TestUtils.v:175No derive declared for Show, against rocq-core 9.1.dev
rocq-mathcomp-hollight-real-with-N type.v:24Usage: HB.builders Context A (f : F1 A).
rocq-robot-rocq angle.v:126The LHS of ltcR (_%:C%C < _%:C%C) does not match any subterm of the goal
coq-trocq-hott hott/Param_lemmas.vThe LHS of equiv_invK (_ (_^-1%equiv _)) does not match any subterm of the goal
coq-trocq-std generic/Param_vector.v:38The constructor cons (in type t) is expected to be applied to 2 arguments while it is actually applied to 3 arguments
rocq-marble fails at dune build -p rocq-marble; CI output is truncated
rocq-coinduction 4.09.0 onlytheories/lattice.v:40, Syntax error: illegal begin of vernac
rocq-color 4.09.0 onlyUtil/Logic/EpsilonUtil.v:16, same error
coq-vcfloat 4.09.0 onlyIEEE754_extra.v:434, The reference eq_IZR_contrapositive was not found in the current environment

The first three failures occur before any .v is read: dune 3.24 removed (using coq X.Y) and requires (using rocq 0.11) with (lang dune 3.21) or later.

The remaining driver evidence is package-specific:

  • coq-ctree is a package rename, not a source port. Its new recipe preserves upstream's dune {>= "3.8" & < "3.24"}, which avoids the deleted (using coq 0.7) extension without migrating it. The expected next result is therefore a different red rather than a green.

  • rocq-mathcomp-hollight-real-with-N uses HB.builders Context T of HOL_isPointed T.. HB's a12d7cc57 adaptation to #21611 changes no grammar, confirming that the syntax came from Rocq's parser rather than HB.

  • rocq-robot-rocq's pinned source has angle.v:126 as rewrite normrM gtr0_norm; last by rewrite ltcR.; at 4e8bedb43 this becomes a single by rewrite normrM gtr0_norm ?ltcR// …. Its new floors are HB 1.10.0, mathcomp 2.6.0, analysis 1.17.0, and real-closed 2.0.6.

  • rocq-coinduction uses Abbreviation 34 times and rocq-color 675 times. The 9.0 parser failure is not fixed by changing those sources; pinning rocq-core {= "dev"} causes the 4.09 job to skip them, while both already pass on 4.14.2 and 5.3.0.

vellvm/ctrees 29a153df8 renamed (name coq-ctree) to (name rocq-ctree). This PR adds rocq-ctree.dev from upstream's in-tree opam and reduces coq-ctree.dev to depends: [ "rocq-ctree" {= version} ]. This clears the package-name failure but leaves three unreached issues: (using coq 0.7), intuition auto with * (#21129), and _ °_ ^° from relation-algebra 1.9.0. rocq-sims therefore remains blocked.

rocq-concert is dependency-driven. QuickChick removed bare Derive after v2.1.1 in favor of QCDerive; v2.2.0 is the first release without it, and CI selected coq-quickchick.dev = v2.2.0-1-g3d4d6c0. ConCert also needs the now-nullary MetaRocq universes_entry constructor. With those two source fixes and a fully-dev dependency stack, dune build @all passes for 188/189 .v, and the two opam packages install with 72 and 116 .vo. examples/AllTests.v is not built because it has no examples/dune, matching upstream. examples/dexter2/extract/ExtractCPMMLIGO.v:19 requires ulimit -s unlimited; with the default ulimit -s 8192 it fails with Error: Stack overflow.

rocq-mathcomp-hollight-real-with-N is broken by #21611, which reserves of; type.v:24 contains HB.builders Context T of HOL_isPointed T.. The responsible commit is first tagged V9.3+rc1.

rocq-robot-rocq was tested outside upstream's declared support: its pinned cf7add1cb declares "coq" { (>= "9.0" & < "9.2~") } and coq-mathcomp-ssreflect {>= "2.5.0"}, while this run used mathcomp 2.6. Upstream later adapted in d08cd27fc and 4e8bedb43; the archive also lacks a .dev recipe satisfying its new rocq-mathcomp-analysis 1.17.0 floor.

coq-trocq-hott is attributed to Rocq based on upstream's ## Trocq is broken on Rocq-master configuration and its 9.0/9.1-only CI, but no responsible PR or version was identified. Two minimal probes produced byte-identical goals under 9.1, 9.2, and dev, so the ledger leaves its version undetermined.

coq-trocq-std was reproduced locally at a36529e66 against Rocq dev:

File "./generic/Param_vector.v", line 38, characters 6-16:
Error: The constructor cons (in type t) is expected to be applied to
2 arguments while it is actually applied to 3 arguments.

#21947 changed asymmetric patterns so they no longer suppress implicit arguments. Five @-patterns fix the shared generic/ code. coq-trocq-hott and coq-trocq-std also install 36 identically named .vo files under Trocq without declaring a conflict. This PR does not add conflicts: because the isolated archive jobs cannot expose the overlap.

rocq-marble has independent dependency and Rocq failures. theories/traverse.v:217, The variable list_elem_of_init was not found, reflects a mismatch between marble HEAD and listz 597ad1e6; no 9.2 build was run, so that attribution is structural rather than measured. theories/pqueue.v:765, wp_move_up depends on the section variable H2 but H2 in the current context does not refer to the section variable of the same name, is caused by #21987, first tagged V9.3+rc1.

The dependency mismatch is also visible in marble's history: f378d8a (Remove listz_buffer. (Now depending on an up-to-date listz.)) precedes 7563cc8 (New file listz_buffer.v.), leaving marble HEAD dependent on a listz change newer than listz HEAD. The Rocq half comes from the proof engine tracking section-variable status after d52593d7e8; listz's tactic reverts and reintroduces variables, yielding a convertible variable that no longer carries the original marker.

coq-hol-light is dependency-driven by Deducteam/coq-hol-light-real-with-N 95e5c1050 (2025-08-01), 18 commits after tag 2.0.0 at fce5a880… (2025-07-11). Its change to align_ε leaves P a as a premise, and the failure appears downstream in coq-hol-light's mappings.v.

All identified Rocq changes driving rows are first tagged V9.3+rc1. There is no V9.3.0; the latest final release is V9.2.0. These are therefore committed 9.3 release-stream breaks rather than speculative master churn. coq-trocq-hott is excluded from that claim because its responsible change remains unidentified.

Packages not tested against master

Resolved versions from each per-package section show that 14 of the 43 never had Rocq master in their install plan on any compiler:

resolved rocq-core packages where the cap is written
9.1.dev on all three jobs the six rocq-num-analysis* their own depends:
9.1.dev on all three jobs rocq-concert, rocq-concert-examples, rocq-rouche-capelli a sibling's
9.0.dev on all three coq-ssprove, rocq-ssprove a sibling's
8.20.dev on all three coq-ctree, rocq-sims a sibling's
8.18.dev / 8.20.dev coq-mathcomp-cad a sibling's

Five rocq-num-analysis* recipes directly use:

(("coq-core" {>= "8.20" & < "8.21~"} & "coq-stdlib") |
  ("rocq-core" {>= "9.0" & < "9.2~"} & "rocq-stdlib"))

The sixth inherits the cap through {= version} dependencies. Their state is not evidence about master and cannot become evidence until the cap changes.

rocq-concert instead has rocq-core {>= "9.1"} but was dragged to 9.1 by four sibling constraints, all removed by the last commit:

"rocq-metarocq-erasure" {>= "1.5.1" & < "1.6~"}
"rocq-rust-extraction"  {= "0.2.1"}
"rocq-elm-extraction"   {= "0.2.1"}
"rocq-stdpp"            {= "1.13.0"}

The typed-extraction chain was built from eaf194e5 against rocq --version 9.4+alpha: common, elm, and rust pass unchanged, 13/13 .v.vo. git diff v0.2.1..eaf194e5 -- '*/theories' '*/src' '*.opam' is empty, so the released 0.2.1 sources are covered. The plugin then fails at ocamlfind: Package 'coq-core.plugins.extraction' not found; changing it to rocq-runtime.plugins.extraction builds through .cmxs and Loader.v.

rocq-rouche-capelli.dev has the same sideways-cap pattern: it declares rocq-core {>= "9.0.0"} without a ceiling, but five rocq-mathcomp-* {= "2.4.0"} pins and coq-mathcomp-classical {= "1.13.0"} pull the plan to 9.1. Its released 0.2.0 recipe does have rocq-core {>= "9.0.0" & < "9.1~"}, but that is not the .dev constraint responsible for this run.

Relaxing rocq-{rust,elm}-extraction {= "0.2.1"} to {>= "0.2.1"} is a forward allowance: the build used sources byte-identical to v0.2.1, so it shows that 0.2.1 need not be the ceiling, not that every future version works. The relaxation and the new .dev recipes are both required; either alone still resolves the old chain.

The coq-core findlib rename

Commit ba476414d4 (#21955) removed the compatibility coq-core.* findlib packages except coq-core.kernel. Counting ^package in lib/coq-core/META gives 24 subpackages on 9.1 and 9.2, but only kernel on dev. The commit is first tagged V9.3+rc1.

The replacement is rocq-runtime.*, available since V9.0+rc1. It affects two rows here:

  • rocq-typed-extraction-plugin.dev: plugin/RocqMakefile.plugin.local:2 names coq-core.plugins.extraction. Renaming it to rocq-runtime.plugins.extraction is the whole fix, verified through .cmxs and Loader.v.

  • coq-interval.dev: configure.in:44 sets COQROOT=coq-core, and configure.in:160/170 query $COQROOT.engine; src/Plot/META.coq-interval:4 also requires coq-core.plugins.ltac. Renaming those clears configuration but reveals a separate V9.3+rc1 break at src/Plot/plot.c:236, caused by 9b1424650d changing Constrexpr.CGenarg and Ltac_plugin.Tacarg.wit_ltac_in_term.

A census of 77 repositories behind 109 recipes in #3809#3812 found four literal coq-core. lines. Besides the two real cases above, coq-belgames has an unused FINDLIBPKGS entry but no .ml, .mlg, or .mli, while rocq-elpi-json / rocq-elpi-xml contain a comment next to a script that already creates the compatibility shim from rocq-runtime.kernel. Five repositories' seven code-bearing submodules were also screened and had no hits. Dynamically assembled names and pre-fix dependency revisions remain outside that grep's coverage.

The new name itself comes from 3d60180c53 (rename package coq-core -> rocq-runtime). HB's corresponding adaptation for the reserved-of change is a12d7cc57 (also cited upstream as a12d7cc), released in v1.10.3; it changes comments, documentation, error strings, and examples rather than owning the removed grammar.

Hidden of breakage

The source census for #21611 (e6a2fb9b2f, first tag V9.3+rc1) covered 29 pristine repositories at their pinned refs and 3060 .v files. After stripping comments and strings, it counted of only at delimiter depth 0 before the first top-level : or :=, excluding constructors, HB.structure Definition bodies, and quoted term notations. Those exclusions account for 189 + 67 + 17 = 273 legal sites. Mathcomp is the negative control: 0 broken / 530 legal across 139 files at both 2.6.0 and dev.

The result is 183 sites in 10 repositories: 83 HB.builders Context, 53 HB.factory Record, 41 HB.mixin Record, and 6 plain Definition/Lemma binders.

repository (recipes) sites status
rocq-partial-orders 147 latent behind rocq-elpi
coq-infotheo, rocq-infotheo 20 latent behind coq-interval
rocq-navi 4 latent behind rocq-elpi; sites are in examples/ and HB is {with-test}
coq-ssprove, rocq-ssprove 2 latent behind coq-deriving
coq-mathcomp-cad 2 latent behind rocq-mathcomp-finmap
rocq-rouche-capelli 1 latent behind rocq-mathcomp-finmap; built past locally
rocq-categories 1 latent behind rocq-elpi
rocq-robot-rocq 1 behind its own earlier error, angle.v:126
rocq-mathcomp-hollight-real-with-N 1 visible now
rocq-relation-algebra 4 green, but all sites are in fhrel.v behind --enable-ssr and a depopts: gate

The backward-compatible fix is token substitution: replace of with &, preserving any existing &. This passed on Rocq 9.2 with HB 1.10.2 and Rocq dev with HB dev. Fifteen sites have multiple binders; dropping an existing & can preserve parsing while changing arity.

Of those 15 multi-binder sites, 13 have two binders and 2 have three. Twelve remain live, all in unported packages: rocq-partial-orders has 8, including the three-binder heads at theories/lattice.v:179 and :215; coq-infotheo / rocq-infotheo have 3; and rocq-rouche-capelli has 1. The census tracks sentences and delimiter depth rather than line starts, because an anchored regex misses multiline heads such as the rocq-rouche-capelli example.

rocq-rouche-capelli demonstrates both the fix and the lower-bound claim:

HB.mixin Record isFinVector
  (R : nzRingType) (V : Type) of Vector R V & Finite V := {}.

The correct replacement is (V : Type) & Vector R V & Finite V. After that change, the build reaches rouche_capelli.v:57, Cannot apply lemma v2r_inj. math-comp 2.6 removed Global Set SsrOldRewriteGoalsOrder, reversing side-goal order; Set SsrOldRewriteGoalsOrder. fixes the second failure. Thus the census finds the first source error, not every error behind it.

OCaml 4.09 and recipe bounds

rocq-runtime.9.0.dev permits ocaml >= 4.09.0; 9.1 and later require >= 4.14.0. Consequently, the 4.09.0 job cannot use rocq-core.dev and falls back to older provers. In #3809's 45-recipe job, 28 skipped, 17 built, and 0 of those 17 used dev. The resolved versions included coq 8.16+rc1, coq 8.16.dev, coq 8.20.dev, coq-core 8.20.dev, coq 9.0.dev, and rocq-core 9.0.dev.

rocq-color.dev and rocq-coinduction.dev used a numeric floor on rocq-prover, but rocq-prover.meta.1 sorts above every numeric version and has only unconstrained dependencies on rocq-core and rocq-stdlib. Thus {>= "9.2"} admits meta.1 and does not transfer the floor to rocq-core. The 4.09.0 job selected rocq-core 9.0.dev, whose parser predates Abbreviation (#20855, 436dca3b11, first tag V9.2+rc1), producing Syntax error: illegal begin of vernac.

Commit d65d1fddc replaces all eight numeric rocq-prover dependencies under extra-dev and core-dev with "rocq-core" {= "dev"}. git grep -l '"rocq-prover"' d65d1fddc^ -- extra-dev core-dev finds 8 files and the same grep at HEAD finds 0. The affected recipes are rocq-color, rocq-coinduction, coq-hol-light, coq-hol-light-real-with-N, coq-hol-light-real-with-nat, rocq-hollight-logic, rocq-hollight-logic-unif, and rocq-mathcomp-hollight-real-with-N.

rocq-color also allowed old rocq-bignums; rocq-coinduction allowed unconstrained rocq-stdlib. This PR pins all necessary paths:

- "rocq-prover"  {>= "9.0"}/{>= "9.2"}  + "rocq-core"    {= "dev"}   # all eight
- "rocq-bignums" {>= "9.0"}             + "rocq-bignums" {= "dev"}   # rocq-color only
- "rocq-stdlib"                         + "rocq-stdlib"  {= "dev"}   # rocq-coinduction only

coq-vcfloat is different. Its constraint is:

"coq" {(>= "8.16" & < "8.19~") | = "dev"}

On OCaml 4.09, the dev branch is unavailable and the solver validly falls back to Coq 8.16. The recipe therefore remains red; changing it would require a policy decision about whether extra-dev recipes may retain non-dev fallbacks.

The resolved versions were read from job 7695047: rocq-coinduction.dev and rocq-color.dev received rocq-core 9.0.dev, while coq-vcfloat.dev received coq 8.16.dev. For the vacuous rocq-prover floor, raising the number would not help—not 9.9, 99, or 9999999—because meta.1 sorts above any numeric version. This ordering was checked against opam show -f all-versions for 12 packages and 779 versions with zero disagreements.

Job 7709751 contains 10 install rocq-prover meta.1 plan lines. Six are in plans that were executed, covering four recipes: rocq-coinduction, rocq-color, coq-hol-light-real-with-N, and coq-hol-light-real-with-nat. The other four occur only in --update-invariant re-plans. Thus eight recipes contain the defect, while this job directly executes four of them.

Four failures on the 4.09.0 job are also Failed to get sources of coq.8.16+rc1: Bad checksum. They come from the coq/coqrocq-prover/rocq rename changing the top-level directory in generated GitHub archive tarballs. The recorded digest is 87ad8e99…; current bytes hash to b0cf2831…. The archive-wide census found 32 recipes across 16 distinct tarballs with mismatches, versus 9 matches and 0 mismatches for 9 distinct URLs from repositories that were not renamed. Released versions using uploaded release assets are unaffected. This PR's changed-file list does not intersect those 32 recipes.

V8.17+rc1 is affected in the same way (7dc99523… recorded, 55b8066f… current). Pipelines 1455710 (2026-08-01) and 1457864 (2026-08-06) date the exposure, likely through source-cache eviction, rather than the defect; four recipes had already been repaired upstream on 2026-02-21. The census fetched and checked all 19 distinct coq/coq archive URLs rather than relying on a sha512-shaped grep, so it also covers md5 recipes and both /archive/refs/tags/<TAG> and /archive/<TAG> spellings.

The source checksum failure is deterministic but does not identify the full affected set from one job: job 7709746 fetched four of the 32 broken recipes, leaving at least 28 unreached in that run. Three URLs and four recipes were already clean after the February repair; V8.8+beta1 is split, with one of its two recipes repaired and the other still stale. The release-asset control was also fetched and matched, supporting the distinction between mutable generated archives and immutable uploaded assets.

Interpreting the pipeline

The archive helper runs feasibility checks and actual installs differently:

echo Check if $PKG is installable
if opam install "$PKG" -y --with-test --show-action $EXTRA_OPAM_OPTION; then
  echo Installing $PKG
  opam install "$PKG" -y -v -v --with-test $EXTRA_OPAM_OPTION >> $LOG
else
  echo Skipping $PKG since not installable with the current compiler
  echo Check if $PKG is installable with another compiler
  opam install "$PKG" -y --show-action --update-invariant
fi

Both branches print a --show-action plan, while only the first performs the install. In job 7709751, 90 packages were attempted: 28 plans were executed and 62 packages skipped. Four skipped packages timed out before printing a plan, leaving 86 visible plans: 28 acted-on and 58 --update-invariant re-plans. The reliable discriminator is an Installing <pkg> line after the plan's ===== N to install ===== trailer and before the next plan. Every one of the 58 re-plan trailers includes to upgrade; none of the 28 executed-plan trailers does.

The counts can be reproduced with:

grep -cE 'Skipping .* since not installable with the current compiler'  # 62
grep -c  'Skipping'                                                     # 63  <- WRONG
grep -oE '=====[^=]*=====' | sed -E 's/[0-9]+/N/g' | sort | uniq -c
#   58  ===== N to install | N to upgrade =====   <- re-plan
#   28  ===== N to install =====                  <- acted on
#   30  ==========                                <- section rule, not a plan

The bare Skipping count includes GitLab's Skipping Git submodules setup. Plan lines must be paired with the following trailer, not the preceding one. The complete log is 1,101,192 bytes; a prior 1,046,155-byte fetch was a byte-identical prefix and produced plausible but incomplete totals. Counts require the job-end marker (Cleaning up project directory, followed by Job succeeded or ERROR: Job failed).

Job 7709746 is the complete 4.09 audit for #3809's 45 recipes: 28 skipped and 17 built, with zero builds on literal dev. The corresponding 4.14.2 and 5.3.0 jobs resolved dev for every reached package but were still running when read, so those are open rather than final counts.

Pipeline 1457865's 4.09.0 job provides the direct rocq-prover.meta.1 example: - install rocq-prover meta.1 [required by rocq-color] is followed by Installing coq-color.dev and a compile failure. This pipeline predates d65d1fddc, so it demonstrates the original defect rather than the current branch state.

Hollight dependency floors

Commits 6fc3d127e, 8e582aa97, and 64198bdf6 add coq-mathcomp-ssreflect {>= "2.5.0"} to the Hollight .dev recipes because a coq-mathcomp-classical floor does not imply a post-boot mathcomp. Their upstream states differ:

row upstream #main paths in sources expected result
rocq-hollight-logic-unif.dev 6005c99 mathcomp.boot.* green — already migrated upstream
rocq-hollight-logic.dev 881963b mathcomp.ssreflect.* red until the migration lands

Only rocq-hollight-logic is expected to become red. Its required migration matches rocq-hollight-logic-unif PR #9 (Mathcomp2.5.0, merged 2025-12-15). This PR does not depend on that upstream change.

The related rocq-mathcomp-real-closed.dev correction is commit 81cfd315f: its mathcomp 2.4 floor predates the boot module paths its source requires. The other corrected rows in that batch are rocq-infotheo, coq-coqeal, and coq-trocq-std-examples; only rocq-mathcomp-real-closed.dev belongs to #3809.

The two Hollight rows were not measured by Deducteam's dev leg: that job fails earlier in coq-mathcomp-classical.1.13.0 at mathcomp_extra.v:154, Cannot apply lemma floor_ge_int. The expected outcomes above instead come from the checked source paths and the dev-switch layout: mathcomp/ssreflect/ contains only all_ssreflect.*, while choice and ssrbool live under mathcomp/boot/.

Changes inherited from the stacked branch

dev-packages-green is an ancestor of this branch, so this PR's diff against master includes 45 package files from #3809 and 93 package files total, with all 45 overlapping. CI tests the union. A red row seen here may therefore belong to #3809 rather than this PR.

Three commits on this branch also tighten recipes introduced by #3809. rocq-mathcomp-classical.dev and coq-mathcomp-word.dev replace {(>= "2.4" & < "2.7~") | (= "dev")} dependency menus with {= "dev"}. They already resolve to dev because opam prefers dev, but the pin prevents a released mathcomp 2.6.0 stack from becoming selectable if dev later becomes unattractive. rocq-mathcomp-real-closed.dev raises its mathcomp floor because its source requires post-boot module paths.

The branch has also been rebased over the relevant bound changes. In particular, rocq-typed-extraction-common.dev now contains rocq-core {= "dev"}, matching the description and rendered diff.

Verification and scope

Every recipe passes opam lint --warn=-21 --check-upstream, matching scripts/opam-coq-lint. Verdicts and resolved versions come from the three opam-build jobs on #3809's pipeline (4.09.0 / 4.14.2 / 5.3.0), using the package whose build command actually failed rather than the package nominally under test.

Local builds cover the cases where CI output was truncated or dependencies made rows unreachable: rocq-marble, coq-trocq-std, rocq-mathcomp-finite-group, typed extraction, ConCert, and rocq-rouche-capelli. Where no commit, bound, comparison, or local build established a cause, the ledger says undetermined or unknown (blocked).

The ConCert dev-stack build included rocq-stdpp dev.2026-07-31.0.45d12a56. QuickChick's syntax boundary was checked at source level: QCDerive exists at v2.0.3, bare Derive remains through v2.1.1, ec6bd8db narrows it to Derive Instance, and 5a6c291 removes the block before v2.2.0.

A package absent from a job's failure list is not counted as passing: the compiler jobs reached different depths. Each row is sourced from a job that visited that package's own section. Likewise, a feasible --show-action plan is not counted as an executed install unless followed by Installing <pkg>; the real install output is redirected by scripts/opam-coq-install-remove.

This branch has been rebased onto the bound updates it quotes. It remains stacked on dev-packages-green: that branch is an ancestor, so the diff against master contains #3809's 45 recipes plus this PR's additions. Failures in the combined pipeline must therefore be partitioned by owning PR.

🤖 Generated with Claude Code

Wordsmithed by Codex.

@coqbot-app coqbot-app Bot added the needs: rebase PR should be synchronized with the master branch by rebasing. label Aug 6, 2026
@JasonGross JasonGross changed the title extra-dev: add 43 dev recipes for packages that do not yet build against Rocq master extra-dev: add 43 dev recipes for packages that do not yet install Aug 6, 2026
@JasonGross
JasonGross force-pushed the dev-packages-needing-ports branch from 239889b to 8642b4e Compare August 6, 2026 05:19
@coqbot-app coqbot-app Bot removed the needs: rebase PR should be synchronized with the master branch by rebasing. label Aug 6, 2026
@JasonGross
JasonGross force-pushed the dev-packages-needing-ports branch from be29020 to 2036ae0 Compare August 6, 2026 11:16
@JasonGross JasonGross changed the title extra-dev: add 43 dev recipes for packages that do not yet install extra-dev: add 46 dev recipes and update 5 more, for packages that do not yet install (on top of #3809) Aug 7, 2026
@JasonGross
JasonGross force-pushed the dev-packages-needing-ports branch from f55c8a1 to 6c9f219 Compare August 10, 2026 17:49
@coqbot-app coqbot-app Bot added the needs: rebase PR should be synchronized with the master branch by rebasing. label Aug 11, 2026
JasonGross and others added 20 commits August 18, 2026 15:09
These eleven packages have been renamed coq-* -> rocq-* in `released`, but
`extra-dev` still only carries the old coq-* name, so nothing in this archive
tracks their master branches under the name the release uses.

Each recipe is upstream's own in-tree `rocq-<name>.opam` from the default
branch, with the `version: "dev"` line dropped (the directory name supplies
it) and a `url` block appended.  No constraint is relaxed or added.

Seven of them carry an upstream-authored version-scoped conflict on the coq-*
name already.  The other four -- aac-tactics, libhyps, mathcomp-real-closed
and relation-algebra -- get a blanket `conflicts: ["coq-<name>"]`, because the
coq-* dev recipe already in this archive builds the same sources and installs
to the same logpath, so the two cannot be installed together.  A later commit
on this branch turns those coq-<name>.dev recipes into pure compatibility
shims (`depends: ["rocq-<name>" {= version}]`) and narrows the four blanket
conflicts to `{!= version}` accordingly.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01L9BGQT7XUuubV6C619DW4b
Seven packages from DmxLarchey, released at 2.2 with `coq >= 9.2.0 < 9.3~`.
coq-kruskal-trees has seven released reverse-dependencies, so it is the
largest hub in the archive with no dev version at all.

Recipes are upstream's in-tree opam files at the default branch, with
`version:` dropped and a git `url` added. Three of them carried a stale
`coq < "8.21~"` upper bound; since opam orders the version string `dev`
above any numeric version, an upper bound of that shape makes a .dev
recipe unselectable on a dev switch, so it is dropped. Lower bounds are
untouched. The mis-cased `name:` fields (`name: "Coq-Kruskal-Trees"`) are
dropped rather than corrected -- the directory already names the package.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01L9BGQT7XUuubV6C619DW4b
coq-hol-light-real-with-N and coq-hol-light-real-with-nat export HOL Light's
real-number development to Rocq.  Both are recent (`rocq-prover >= 9.0`, no
upper bound), so the dev recipes carry upstream's constraints verbatim.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01L9BGQT7XUuubV6C619DW4b
Two packages from the Peregrine extraction stack.  Both sit on top of
MetaRocq, which already has a dev in extra-dev, and both are capped at
`< 9.2~` in their latest release, so nothing in this stack currently tracks
Rocq master.

The `< 9.2~` upper bounds on rocq-core/rocq-stdlib are dropped for the reason
described in the Kruskal commit; the `{= version}` bounds tying the family
together are kept.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01L9BGQT7XUuubV6C619DW4b
Upstream has renamed this package from coq-pil to rocq-pil: hferee/rocq-pil
ships both coq-pil.opam and rocq-pil.opam.  The archive still only knows the
coq-* name, and only as a release.

It installs the same logpath as its coq-* twin, and upstream ships no
compatibility shim package the way math-comp/analysis does, so it declares
`conflicts: ["coq-pil"]`.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01L9BGQT7XUuubV6C619DW4b
Ten more packages with a live release and no dev version anywhere in the
archive.  Recipes come from upstream's in-tree opam file at the default
branch, except for coq-bedrock2-compiler, whose repository ships no opam file
at all -- that one is derived from the latest released recipe with the tarball
`url` replaced by a git one.

Notes on individual packages:

  * rocq-listz is on gitlab.inria.fr.
  * rocq-induction and strict-order-solver were missing `dev-repo:`; it is
    filled in from the homepage.
  * coq-ordinal's license was spelled "MIT License"; normalised to the
    SPDX "MIT".

Upper bounds on coq/rocq-core/rocq-stdlib are dropped where present, as in the
earlier commits.  coq-record-update already spells its bound `... | = "dev"`
and is left alone.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01L9BGQT7XUuubV6C619DW4b
… shims

Twelve packages have been renamed coq-* -> rocq-* upstream.  Until now the
rocq-* dev recipe and the coq-* dev recipe both built the same sources into
the same logpath, so the rocq-* side had to declare a blanket conflict on the
coq-* side and the two could never be co-installed.

Replace each `coq-<name>.dev` with a metadata-only compatibility package,

    depends: [ "rocq-<name>" { = version } ]

which is the shape `coq-mathcomp-finmap.dev`, `coq-mathcomp-bigenough.dev`
and `coq-hierarchy-builder.dev` already use in this archive.  Eight of them --
the math-comp/analysis family -- are upstream's own in-tree `coq-<name>.opam`
shim verbatim, minus the `version:` line (the directory name supplies it); the
other four (aac-tactics, libhyps, pil, relation-algebra) ship no shim upstream
and are synthesised from the metadata of the rocq-* recipe.  `coq-pil.dev` did
not exist at all and is new.

One small departure from the upstream text, to keep `opam lint` quiet:
`authors` is carried over to the multinomials and real-closed shims, which
omit it upstream.

The five blanket `conflicts: [ "coq-<name>" ]` added earlier in this branch
become `conflicts: [ "coq-<name>" { != version } ]`, so that they still
exclude the released coq-* builds but admit the shim.  The seven that carry an
upstream-authored version-scoped conflict already had this property and are
untouched.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01L9BGQT7XUuubV6C619DW4b
Fourteen .dev recipes in this PR let the solver select a released prover
instead of rocq master. This is not hypothetical: in job 7709746 every
package touched here was BUILT rather than skipped on the ocaml-4.09 job,
which rocq-runtime.dev cannot satisfy (it requires ocaml >= 4.14.0). A
build there is proof that some older prover was chosen.

Three shapes of defect, all fixed by naming the prover exactly:

  * a bare lower bound ("coq" {>= "8.14"}) excludes nothing old, so the
    4.09 solver walks back to whatever ancient release still resolves;
  * "rocq-prover" {>= "9.0"} is vacuous, because the metapackage's own
    version is the letters "meta.1", which outrank every numeric version.
    Worse, going through the metapackage removes all constraints on
    rocq-core. Its whole content is rocq-core + rocq-stdlib, so naming
    both directly is exact, not a narrowing;
  * no prover dependency at all, reaching a bounded sibling only through
    UNVERSIONED deps, so a released sibling can be selected and drag an
    old prover back in (the four Kruskal recipes).

Where the recipe already depended on "coq", the pin is written "coq"
{= "dev"} rather than switching to rocq-core. The shim chain is
coq.dev -> coq-core {= version} -> rocq-runtime {= version}, so this pins
rocq master exactly as rocq-core {= "dev"} would, while keeping the
coqc-providing compatibility binaries these legacy build systems invoke.

A pinned rocq-core {= "dev"} also pins rocq-stdlib transitively: released
rocq-stdlib.9.0+rc1 requires rocq-core {>= "9.0" & < "9.1~"}, which dev
violates. A bare companion "rocq-stdlib" beside a dev pin is therefore
not a hole and is left alone.

Effect on CI: these packages stop building on ocaml-4.09 and become
honest per-compiler skips, which is the correct signal for a dev recipe.
Any green they produced there was about a prover this PR is not adding
support for.

Left unfixed, deliberately: three recipes carry generated/mirrored
headers (coq-record-update.dev and rocq-mathcomp-multinomials.dev from
meta.yml, rocq-libhyps.dev from the released archive recipe).
coq-record-update.dev was already safe. rocq-libhyps.dev IS edited here
despite its marker, because it mirrors a released archive recipe rather
than an upstream generated file, and a .dev recipe legitimately diverges
from the released one on exactly this axis.

Also left unfixed: twelve recipes whose prover bound can still select an
old prover but which were SKIPPED, not built, on 4.09 (one of them,
rocq-mathcomp-multinomials.dev, is also in the generated list above).
They already behave correctly; changing them would be an unmeasured edit.

The archive's seven stale core-dev tarball checksums (invalidated when
the coq/coq -> rocq-prover/rocq rename changed the directory name inside
the generated /archive/refs/tags/ tarballs) are an independent defect and
are NOT fixed here.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01L9BGQT7XUuubV6C619DW4b
Every recipe this PR adds to or touches in extra-dev exists to test a
package's development branch against Rocq's development branch.  Most of
them constrained the prover with a bare floor instead -- "coq" {>= "8.14"},
"rocq-core" {>= "9.0"}, and so on.  A bare floor is satisfied by every
released prover as well as by dev, so when dev is unavailable the solver
walks backward instead of reporting that there is nothing to test.  That
is not hypothetical: on the ocaml-4.09 job rocq-pil.dev resolved coq
8.20.dev, coq-stdpp 1.12.0 and coq-equations 1.3.1+8.20, and coq-pil.dev
then pulled that in through its shim.  Five recipes failed on that job for
no reason other than having been built against a prover they do not target.

Constrain each prover dependency to {= "dev"}.  On the compilers that
matter this changes nothing -- the retry plans on the 4.09 job already show
the solver choosing rocq-core dev for these recipes once the compiler is
free.  What changes is that 4.09 stops manufacturing failures and reports
an honest per-compiler skip.

Two recipes needed more than a bound:

  * coq-hol-light-real-with-{N,nat} asked for "rocq-prover" {>= "9.0"}.
    That bound is vacuous -- opam sorts letters above digits, so the
    metapackage version meta.1 satisfies it -- and core-dev carries no
    rocq-prover.dev at all, only 9.3.dev.  Replaced with rocq-core and
    rocq-stdlib at dev.

  * rocq-pil asked for coq-stdpp {>= "1.11.0"}, and every coq-stdpp in the
    archive caps coq below 8.21~, which is what dragged it back to Coq
    8.20.  Only rocq-stdpp 1.13.0 admits a dev prover, so the dependency
    moves to the rocq- twins.  The logical paths (stdpp, Equations) are
    unchanged by that rename.

rocq-cakeml-extraction is deliberately left loose.  It pins
rocq-metarocq-erasure-plugin {>= "1.4" & < "1.5.2"}, and
rocq-metarocq-utils 1.5.1+9.2 requires rocq-core {>= "9.2~" & < "9.3~"},
so pinning its prover to dev would make it uninstallable rather than
testable.  Raising that MetaRocq bound is a claim about whether
cakeml-backend master builds against MetaRocq master, which is not settled
here.

The compatibility shims -- coq-aac-tactics, coq-libhyps, coq-pil,
coq-relation-algebra and the coq-mathcomp-* family -- are untouched.  They
carry no prover dependency of their own; the constraint belongs on the
rocq- twin they pin with {= version}, and that twin now has it.

This is unrelated to the archive's seven stale core-dev +rc1 checksums,
which are an independent defect and are not fixed here.  These recipes
should name dev because dev is what they are for, not as a way around a
checksum.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01L9BGQT7XUuubV6C619DW4b
Two corrections to the commit before this one.

coq-record-update.dev and rocq-mathcomp-multinomials.dev both open with

  # This file was generated from `meta.yml`, please do not edit manually.
  # Follow the instructions on https://github.com/coq-community/templates

so their bounds belong in the upstream meta.yml, not here.  Reverted.
Both can still select a released prover -- coq-record-update.dev admits
coq-core 8.17 through 9.2, rocq-mathcomp-multinomials.dev admits any
rocq-core >= 9.0 -- and that is now a reported finding rather than a
local edit.  The check that missed them grepped for the dune marker
("generated by dune") and read its own silence as "no generated files",
which is the same failure shape as a bound that admits everything.

The rest of the revert drops constraints that were never in scope.  A
companion "rocq-stdlib" or "coq-stdlib" beside a dev-pinned rocq-core or
coq-core cannot select a released stdlib: rocq-stdlib 9.0+rc1 requires
rocq-core {>= "9.0" & < "9.1~"} and rocq-stdlib 9.2.0 requires
{>= "9.1" & < "9.4~"}, and dev satisfies neither.  Pinning those
companions changed no solution, so they are restored to what they were.
Same for the unconstrained "rocq-core" beside a dev-pinned rocq-runtime in
rocq-induction, and the unconstrained "coq-core" in the
coq-mathcomp-classical shim, whose prover constraint reaches it through
the rocq- twin it pins with {= version}.

What remains from that commit is twelve recipes, each with exactly one
binding prover constraint moved to {= "dev"}, plus rocq-pil's move to the
rocq- stdpp and Equations packages, which was needed because every
coq-stdpp in the archive caps coq below 8.21~.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01L9BGQT7XUuubV6C619DW4b
The recipe depended on "rocq-stdlib" {= "dev"} and named no rocq-core at
all. A dev-pinned stdlib does not pin the core: rocq-stdlib.dev's own
bound is

  "rocq-core" {>= "9.2" | = "dev"}

which is a disjunction, and core-dev supplies four numeric versions
satisfying its first branch -- 9.2.dev, 9.2+rc2, 9.3.dev, 9.3+rc1 -- any
of which the solver may take instead of master.

So the recipe was BOUNDED but not PINNED. That is still a real
improvement on what it replaced (a "coq" {< "8.21~"} branch admitting any
ancient coq: the floor moved from Coq 8.20 to 9.2), which is why this was
easy to miss -- the direction of travel was right and the destination was
not reached. But a green on it would have been evidence about 9.2/9.3,
not about rocq master.

The closure argument used elsewhere in this batch runs core -> stdlib: pin
rocq-core {= "dev"} and every released rocq-stdlib is excluded by its own
cap on rocq-core. It does NOT run stdlib -> core, because rocq-stdlib.dev
constrains rocq-core with a disjunction rather than an equality. Pinning
the stdlib alone therefore closes nothing, and this was the only recipe in
the changed set with that shape.

Also correcting the wording of a claim in e3a41f1, which cannot be
amended: it says "every coq-stdpp in the archive caps coq below 8.21~".
That is false for coq-stdpp 1.11.0, which caps at < "9.1~"; only 1.12.0
uses 8.21~. The conclusion it supports is unaffected -- every coq-stdpp
cap is an upper bound and dev exceeds every numeric version, so no
coq-stdpp in the archive admits a dev prover, and rocq-pil still had to
move to the rocq- twins.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01L9BGQT7XUuubV6C619DW4b
Both have been renamed coq-* -> rocq-* in `released`, but `extra-dev` still
only carries the old coq-* name, so nothing in this archive tracks their
master branches under the name the release uses.

Each recipe is upstream's own in-tree `rocq-<name>.opam` from the default
branch, with the `version: "dev"` line dropped (the directory name supplies
it) and a `url` block appended.  No constraint is relaxed or added.
`rocq-color` additionally gets the `dev-repo` field it is missing upstream,
so that `opam lint` is clean.

Each declares `conflicts: ["coq-<name>"]`: the coq-* dev recipe already in
this archive builds the same sources and installs to the same logpath, so the
two cannot be installed together.  A later commit on this branch turns those
coq-<name>.dev recipes into pure compatibility shims
(`depends: ["rocq-<name>" {= version}]`) and narrows these conflicts to
`{!= version}` accordingly.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01L9BGQT7XUuubV6C619DW4b
coq-hol-light, rocq-hollight-logic, rocq-hollight-logic-unif and
rocq-mathcomp-hollight-real-with-N.  All are recent (0.0.0 / 1.0.x,
`rocq-prover >= 9.0`, no upper bound), so the dev recipes carry upstream's
constraints verbatim.

rocq-hollight-logic-unif is taken from Deducteam/rocq-hollight-logic-unif,
which is where the released tarball comes from; the released recipe's
`dev-repo:` points at Deducteam/rocq-hollight-fole instead, which is a
different repository.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01L9BGQT7XUuubV6C619DW4b
rocq-typed-extraction, rocq-typed-extraction-plugin, rocq-ceres-bytestring
and rocq-concert{,-examples}.  All sit on top of MetaRocq, which already has
a dev in extra-dev, and all are capped at `< 9.2~` in their latest release,
so nothing in this stack currently tracks Rocq master.

The `< 9.2~` upper bounds on rocq-core/rocq-stdlib are dropped for the reason
described in the Kruskal commit on the parent branch; the `{= version}` bounds
tying the family together are kept, and every package they name gets a .dev
here or already has one.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01L9BGQT7XUuubV6C619DW4b
Six packages from the MILC project, released at 2.2.0 with
`rocq-core >= 9.0 < 9.2~` in their dependencies.

The released recipes declare
`dev-repo: "git+https://lipn.univ-paris13.fr/rocq-num-analysis.git"`,
which 404s. The repository is served from the group's GitLab at
depot.lipn.univ-paris13.fr/mayero/rocq-num-analysis (default branch
`master`); these recipes use that, and correct `dev-repo:` to match.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01L9BGQT7XUuubV6C619DW4b
coq-trocq-{std,hott} and their example packages. Released at 0.4.0 with
`coq >= 8.20 < 9.1` / `< 9.2`; those upper bounds are dropped so the
recipes are selectable on a dev switch.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01L9BGQT7XUuubV6C619DW4b
Upstream has renamed both from coq-* to rocq-*: infotheo master ships
rocq-infotheo.opam and ssprove main ships rocq-ssprove.opam.  The archive
still only knows the coq-* names, and only as releases.

Each installs the same logpath as its coq-* twin, and neither upstream ships a
compatibility shim package the way math-comp/analysis does, so each declares
`conflicts: ["coq-<name>"]`.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01L9BGQT7XUuubV6C619DW4b
Sixteen more packages with a live release and no dev version anywhere in the
archive.  Recipes come from upstream's in-tree opam file at the default
branch, except for coq-ctree and rocq-sims, whose repositories ship no opam
file at all -- those are derived from the latest released recipe with the
tarball `url` replaced by a git one.

Notes on individual packages:

  * coq-vst-lib comes from VST's `lib/coq-vst-lib.opam`, not the root.
  * rocq-laproof: VeriNum/LAProof still calls the package coq-laproof
    in-tree, but the archive only has the rocq- name, so no conflict arises.
  * rocq-robot-rocq comes from affeldt-aist/coq-robot's `robot-rocq.opam`.
  * rocq-navi comes from affeldt-aist/rocqnavi, which is where the releases
    are cut; its default branch really is `mca2html`.
  * rocq-marble is on gitlab.inria.fr.
  * coq-pprint was missing `dev-repo:`; it is filled in from the homepage.

Upper bounds on coq/rocq-core/rocq-stdlib are dropped where present, as in the
earlier commits.  coq-vcfloat already spells its bound `... | = "dev"` and is
left alone.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01L9BGQT7XUuubV6C619DW4b
Four more packages have been renamed coq-* -> rocq-* upstream.  Until now the
rocq-* dev recipe and the coq-* dev recipe both built the same sources into
the same logpath, so the rocq-* side had to declare a blanket conflict on the
coq-* side and the two could never be co-installed.

Replace each `coq-<name>.dev` with a metadata-only compatibility package,

    depends: [ "rocq-<name>" { = version } ]

which is the shape `coq-mathcomp-finmap.dev`, `coq-mathcomp-bigenough.dev`
and `coq-hierarchy-builder.dev` already use in this archive.  None of these
four (coinduction, color, infotheo, ssprove) ships a shim upstream, so all are
synthesised from the metadata of the rocq-* recipe.  `coq-infotheo.dev` and
`coq-ssprove.dev` did not exist at all and are new.

One departure from the upstream text, to keep `opam lint` quiet:
`coq-coinduction` keeps the SPDX `LGPL-3.0-or-later` it already had here
rather than upstream's `GNU LGPL`.

The four blanket `conflicts: [ "coq-<name>" ]` added earlier in this branch
become `conflicts: [ "coq-<name>" { != version } ]`, so that they still
exclude the released coq-* builds but admit the shim.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01L9BGQT7XUuubV6C619DW4b
rocq-typed-extraction.dev and rocq-typed-extraction-plugin.dev both depend on
`rocq-elm-extraction {= version}` and `rocq-rust-extraction {= version}`, but
neither of those has a dev recipe -- only releases.  On a dev switch `version`
is `dev`, so both requirements are unsatisfiable and the two packages land in
`Packages that can never be installed:`, which is the one condition that fails
the archive's CI gate outright.

Both are built from the same repository by the same `configure.sh`, so the
recipes are upstream's in-tree opam files with `version:` dropped and a `url`
block appended, exactly like the rest of the stack.  This does not make the
stack build against Rocq master -- it only turns an unsatisfiable dependency
into an ordinary build result.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01L9BGQT7XUuubV6C619DW4b
JasonGross and others added 28 commits August 18, 2026 15:09
The .dev recipe was still carrying the released one's depends block:
`coq >= 9.0`, the `coq-mathcomp-*` names at 2.5.0/1.15.0/2.0.0 floors,
and coq-mathcomp-algebra-tactics. All of that is wrong for a recipe whose
`url` tracks upstream master. The repository recipe never notices,
because `url { src: }` means the source tree's own robot-rocq.opam is not
consulted.

Take the floors from that file:

  rocq-hierarchy-builder     1.10.0
  rocq-mathcomp-*            2.6.0
  rocq-mathcomp-analysis     1.17.0
  rocq-mathcomp-real-closed  2.0.6

The 2.6.0 floor is forced by the source, not chosen for safety.
quaternion.v line 6 reads

  From mathcomp Require Import ring_tactic field_tactic.

Those two modules were moved out of algebra-tactics and into
mathcomp/algebra/ by mathcomp commits 5180dfc49 ("Retrieve ring tactic
from algebra-tactics", adds algebra/ring_tactic.v) and 02803924
("Retrieve field tactic from algebra-tactics", adds
algebra/field_tactic.v). `git tag --contains` reports exactly one tag for
each: mathcomp-2.6.0. So below 2.6.0 that Require has nothing to resolve
against, which is also why coq-mathcomp-algebra-tactics drops out of the
depends list at the same time as the floor goes up -- the floor and the
removal are the two halves of one substitution.

Keep `coq`, do not rename it to `rocq-core`, and pin it to dev. robot's
Makefile generates Makefile.coq by running coq_makefile, and coq_makefile
ships in coq-core, not rocq-core: in a switch with both installed at dev,
coq-core.changes lists `bin/coq_makefile` and rocq-core.changes lists
none. `coq.dev` reaches rocq-runtime through `coq-core {= version}` and
rocq-stdlib through `coq-stdlib`, so the dev prover and the dev Stdlib
that `From Stdlib Require Import NsatzTactic` needs both follow from the
one constraint.

`= "dev"` rather than a floor: `>= "9.0"` permits dev but does not
require it, and when both a released and a dev version are permitted the
solver is free to take the released one. That would leave the one recipe
whose job is to exercise dev solvable entirely against released packages.
Only an equality forces it.

opam lint: Passed.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01L9BGQT7XUuubV6C619DW4b
`gh repo view affeldt-aist/coq-robot` answers
`nameWithOwner: affeldt-aist/robot-rocq`: the repository was renamed and
the old name only resolves through GitHub's rename redirect. The recipe
works today because git follows that redirect, but a redirect is not a
name -- once the original owner creates anything under the freed
`coq-robot`, the redirect stops and `url { src: }` starts fetching a
different repository, or nothing.

Point homepage, dev-repo, bug-reports and url at the canonical name.

Not taken from upstream's own robot-rocq.opam, which is generated from
meta.yml and says `https://github.com/affeldt-aist/robot` -- a third name
that resolves to nothing at all (`Could not resolve to a Repository`).
`shortname: robot` plus a template that does not add the project's actual
prefix produces a URL that has probably never existed. So the header's
"generated from meta.yml, please do not edit manually" cannot be followed
here: regenerating would replace a working URL with a dead one.

Verified, all three names, same command:

  affeldt-aist/robot      -> Could not resolve to a Repository
  affeldt-aist/coq-robot  -> affeldt-aist/robot-rocq   (redirect)
  affeldt-aist/robot-rocq -> affeldt-aist/robot-rocq   (canonical)

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01L9BGQT7XUuubV6C619DW4b
rocq-mathcomp-classical.dev capped rocq-mathcomp-algebra at
`(>= "2.6.0" & < "2.7~")`, and coq-mathcomp-word.dev caps
coq-mathcomp-ssreflect at `(>= "2.4" & < "2.7~")`. Since opam sorts
letters above digits, `< "2.7~"` excludes `dev` outright, so neither
recipe could select mathcomp master at all -- .dev recipes unable to use
the dev dependency they exist to test. Add the `| (= "dev")` branch to
each.

Both new branches bind: rocq-mathcomp-algebra.dev and
coq-mathcomp-ssreflect.dev both exist in extra-dev, the latter as a shim
onto `rocq-mathcomp-ssreflect {= version}`. Worth stating, because a
widening naming a version that does not exist lints clean and changes
nothing.

The cap is stale as a correctness claim: mathcomp-analysis master builds
clean against mathcomp dev, 96/96 (task rocq-prover#32).

WHAT THIS CHANGES IN THE SOLVER -- corrected. An earlier draft of this
commit argued the widening was near-inert, on the grounds that across
pipeline 1457864 "14 plans resolved rocq-mathcomp-ssreflect 2.6.0 and
only 10 dev, including cases where dev was permitted". Task rocq-prover#38
falsified that: it was a preference read off a denominator artifact. The
release was not chosen over dev, it was the only version the ceiling
permitted. rocq-prover#38's discriminator is the same-plan free-package control --
within those very plans, every mathcomp package NOT carrying a 2.7~
ceiling resolved dev. The ceiling is what forced the release, so
widening it should make the solver actually select mathcomp dev here,
not merely tolerate it.

That refines the older caution rather than repealing it. "Permitting dev
is not selecting dev" stays true in general: a bound admits, it does not
choose, and a green whose plan nobody read is evidence about whatever
the solver actually took. What rocq-prover#38 removes is the narrower inference
that these two recipes would go on resolving 2.6.0. The expectation here
is now dev -- which is the reason to read the plan, not a licence to
skip it.

SCOPE, and a difference from the copy of this change that was drafted
for the green batch. Only the mathcomp lines are touched. This branch
does not carry the prover pins from 90010d5, e3a41f1 and 977a400,
so rocq-mathcomp-classical.dev still reads
`rocq-core {(>= "9.0" & < "9.4~") | (= "dev")}` -- a menu, not a pin --
and coq-mathcomp-word.dev still reads `coq-core {>= "8.19"}`, unbounded
above. Both are real defects, and an unbounded prover is precisely how a
recipe walks backward into Coq 8.16. They are left alone here because
pinning them would duplicate the green batch's work onto a branch that
has diverged from it, which is a reconciliation decision rather than a
port fix.

A PREDICTION FROM THE GREEN BATCH, restated because its original home
was dropped and its figure was wrong. If all five of the 4.09 job's
failures share one cause -- a prover bound loose enough to reach Coq
8.16 -- then the bound fixes in 90010d5, e3a41f1 and 977a400
should clear them WITHOUT anyone touching the archive's stale core-dev
tarball checksums: the recipes stop reaching 8.16 at all, so the
`Bad checksum` lines disappear while the archive recipes stay broken. If
they persist, the shared-driver claim is wrong and there is a further
path to 8.16 that nobody has found.

The earlier draft sized that defect at "seven stale +rc1 checksums".
Wrong in both count and shape: it came from grepping only
`/archive/refs/tags/`, which misses the equally broken `/archive/<TAG>`
spelling of the same generated endpoint, and misses the md5-era recipes
entirely. Measured in task rocq-prover#39 by fetching and rehashing every distinct
tarball: 36 core-dev recipes over 19 URLs, of which 32 over 16 URLs were
still stale, most of them betas rather than +rc1. They remain an
independent defect, not fixed here.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01L9BGQT7XUuubV6C619DW4b
The sources require only HB's structures, all_ssreflect and all_algebra.
Compiling the file and asking Print Libraries what loaded gives 77 math-comp
libraries under boot, order, algebra, finite_group and ssreflect, and none
under classical, boolp or finmap, so neither rocq-mathcomp-classical nor
rocq-mathcomp-finmap belongs in depends:.

Both were blocking dev resolution. The released rocq-mathcomp-classical
versions cap rocq-mathcomp-algebra below 2.7~, and dev sorts above 2.7~, so
declaring classical excluded the dev math-comp and forced 2.6.0 through the
{= version} locks. rocq-mathcomp-finmap is the [required by] requirer on the
plans that resolve released ssreflect 2.6.0.

The build also ran coq_makefile while depending on rocq-core, which does not
ship it -- coq-core owns that binary. rocq makefile is the same generator, and
the rocq binary comes from rocq-runtime, which rocq-core pins at {= version}.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01L9BGQT7XUuubV6C619DW4b
1aa0bca1d pinned the prover with `coq {= "dev"}` and gave the reason: a
floor permits dev but does not require it, and when both a released and a
dev version are permitted the solver is free to take the released one.
That argument was applied to the prover and not to the libraries, which
were left on floors -- ssreflect and friends at 2.6.0, analysis at
1.17.0, real-closed at 2.0.6.

The libraries need it more than the prover does. The port carries a fix
at rot.v:866 that retargets an `ACl` permutation to the operand order
math-comp *dev* produces; it is order-sensitive by construction. It was
measured against math-comp 78cb0653 (2.6.0 plus 8 commits, installed as
dev) and analysis 0653637 (1.17.0 plus 1). It has never been run against
released 2.6.0. So `>= "2.6.0"` is not a conservative default, it is an
untested claim: it lets the one recipe whose job is to exercise dev
resolve against a stack nobody verified, and the resulting failure at
rot.v:867 would read as "the port does not work" when it means "the
recipe permitted something we never built".

Every package pinned here has a .dev recipe in extra-dev, and every one
is installed at .dev in the switch the port was verified in, so the pins
name the configuration that was actually measured rather than a hoped-for
one. analysis is the one exception to "installed in the switch": it comes
from a separate prefix, whose own opam file declares version "dev".

No information is lost by dropping the numbers. 2.6.0 remains the true
source floor -- quaternion.v requires mathcomp's ring_tactic and
field_tactic, which exist only from 2.6.0 -- and the released recipe still
carries it. Under `= "dev"` the floor is simply not the binding
constraint.

opam lint: Passed.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01L9BGQT7XUuubV6C619DW4b
…th-comp deps

The recipe pins rocq-core to dev but left its five math-comp dependencies at
{>= "2.4.0"}. Released rocq-mathcomp-boot.2.6.0 depends on rocq-core {>= "9.0"}
with no upper bound, and a lower bound cannot exclude dev, so released 2.6.0 is
a legal solution alongside rocq-core dev. Where released math-comp is available
the solver prefers it, so the floors do not merely permit the released
resolution, they select it, and the dev-against-dev build this recipe exists to
exercise silently does not happen.

That matters more here than elsewhere: this package's breakage is itself
math-comp-versioned. It needs Set SsrOldRewriteGoalsOrder because math-comp 2.6
stopped setting the flag for its users, so leaving the math-comp version to the
solver is backwards on the one package whose failure depends on it.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01L9BGQT7XUuubV6C619DW4b
rocq-hollight-logic.dev and rocq-hollight-logic-unif.dev address
mathcomp.boot.{choice,ssrbool}. That path ships only from
coq-mathcomp-ssreflect 2.5.0, and no coq-mathcomp-classical floor
implies it: every published classical version -- 1.14.0 included --
permits ssreflect 2.4.0, and rocq-mathcomp-ssreflect.2.4.0 really
exists in released/. The two path styles are disjoint across the
boundary (measured in the dev switch: mathcomp/ssreflect/choice.vo
absent, mathcomp/boot/choice.vo present), so the requirement has to
be stated on ssreflect directly.

Both rows are pre-existing recipe bugs rather than port regressions.
They are green today only because a dev switch happens to resolve
mathcomp dev -- the constraint is not doing the work, the switch is.

Not applied to rocq-mathcomp-hollight-real-with-N.dev: its sources
carry no fully-qualified mathcomp.ssreflect/boot path at all. Every
mathcomp reference is either a bare module name, resolved by load-path
search and so agnostic to the 2.5.0 split, or mathcomp.classical.*,
which did not move. Adding the floor there would narrow what is
installable with no breakage to point at.

rocq-hollight-logic.dev's floor is correct only together with the
upstream source fix: #main (881963b) still uses mathcomp.ssreflect.*
in terms.v, theorems.v and reproduce. The recipe tracks #main, so it
picks the fix up once merged.

Static evidence only: constraint reading plus opam lint/parse. Not
built -- building means installing into a degraded switch.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01L9BGQT7XUuubV6C619DW4b
The algebra dependency was a menu, not a pin: it permitted dev without
forcing it, so the recipe could still solve entirely on released mathcomp
2.6.0.

Adding "rocq-core" {= "dev"} did not close this. That fix works against
mathcomp 2.5.0, whose boot caps the prover at < 9.2~, but boot 2.6.0
declares "rocq-core" {>= "9.0"} with no upper bound, so a dev prover is
happy alongside released 2.6.0. The released arm survives because
hierarchy-builder 1.10.2 and 1.10.3 both carry an explicit dev disjunct;
had 1.9.0's < 9.1~ cap been the only one available, boot's >= 1.9.0
floor would have excluded it on its own.

Pinning the library instead propagates through the {= version} locks:
algebra dev forces order and finite-group to dev, which force boot to
dev, and every shim from 2.5.0 up locks boot to its own released
version, so no released member can be selected.

Consumers were checked for the reverse problem. rocq-mathcomp-reals
always takes this recipe and constrains nothing else in the family;
rocq-hollight-logic and -unif reach it through the coq-mathcomp-classical
shim and both permit a dev ssreflect. coq-mathcomp-cad pins ssreflect
2.2.0, which needs coq < 8.21~ and so cannot coexist with a dev prover,
and rocq-num-analysis-subset caps classical below dev; neither can select
this recipe at all.

Two constraints in the block are dead and are now marked as such in the
file rather than removed. The hierarchy-builder floor of 1.8.0 never
binds: no 1.8.0 was ever published, the lowest is 1.9.0, and boot already
requires >= 1.9.0. The bare finmap dependency is closed only transitively,
by the algebra pin plus every published finmap permitting a dev ssreflect.
Neither is worth changing, but a recipe that states its intent beats one
that relies on a chain holding somewhere else.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01L9BGQT7XUuubV6C619DW4b
…rges

The previous comment said the recipe "picks the fix up automatically once
merged", which reads as "nothing to do, it will go green on its own". It will
not: #main still addresses mathcomp.ssreflect.{choice,ssrbool}, so the sources
need pre-boot paths while the floor forbids pre-boot mathcomp. The row is
expected RED until Deducteam merges the source patch.

Also record how the red will present. The floor does not make the row
unsatisfiable -- coq-mathcomp-classical 1.14.0/1.15.0 permit ssreflect 2.5.0 in
their numeric arm outright, and 1.11.0..1.13.0 keep their `| (= "dev")` arm,
which satisfies >= "2.5.0". So it solves and fails at BUILD time with a Rocq
error rather than skipping as `not installable`, and a reader expecting a skip
would wrongly conclude the constraint did not take.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01L9BGQT7XUuubV6C619DW4b
…if dep

rocq-hollight-logic.dev asked for "rocq-hollight-logic-unif" {>= "0.0.0"}, which
also admits the released 0.0.0. That row is installable against a dev prover --
its own dep is the unbounded floor "rocq-prover" {>= "9.0"}, and a floor cannot
exclude dev.

Worse, selecting it re-opens the hole the sibling commit just closed. 0.0.0 caps
coq-mathcomp-classical <= "1.13.0"; every classical at or below 1.13.0 caps
ssreflect < "2.5~" numerically; so this recipe's own >= "2.5.0" ssreflect floor
leaves only classical's `| (= "dev")` arm. The result is 0.0.0's pre-boot
sources built against post-boot mathcomp. The boot floor lives only in the .dev
unif recipe, so the dep has to name it.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01L9BGQT7XUuubV6C619DW4b
The ssreflect dependency was a menu, not a pin. It admitted 2.4.0, 2.5.0
and 2.6.0, and a range is excluded only if every member of it is. 2.4.0
and 2.5.0 are capped below a dev prover, so reading the bottom of the
range suggests the row is already closed; 2.6.0 is not, because it
reaches rocq-mathcomp-boot.2.6.0, which declares "rocq-core" {>= "9.0"}
with no upper bound. The member that decides a range is usually the top
one.

The point of the pin is to stop depending on solver preference. This row
does resolve to dev today, and did so before this change: opam maximises
versions and dev sorts above every numeric one, so dev wins by default
once it is permitted at all. That is a fact about preference, not about
admissibility. Released 2.6.0 remains selectable for any solve where dev
mathcomp becomes unattractive -- a red dev build, or a sibling pinning an
older mathcomp -- and the recipe should not be relying on a tie-break to
express which one it means.

This is the same hole as rocq-mathcomp-classical.dev, reached through the
same edge.

The bare coq-mathcomp-algebra dependency needs no change. Versions 1.6
through 2.3.0 reach ssreflect through coq-mathcomp-fingroup {= version},
and 2.4.0 onwards are shims over rocq-mathcomp-algebra, whose {= version}
locks on order and finite-group land on the same boot. Pinning ssreflect
therefore closes algebra too. Both facts are now stated in the file.

No consumer is affected. All four recipes that depend on coq-mathcomp-word
cap it below dev -- coq-ssprove 0.2.4 and 0.3.0 at < 3.3, coq-ssprove
0.3.1 and rocq-ssprove.dev at < 3.5 -- so none of them can select this
recipe at all.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01L9BGQT7XUuubV6C619DW4b
86 of infotheo's 87 .v files open with

    From mathcomp Require Import all_boot

and 45 of them also require all_order. Both umbrellas ship from
rocq-mathcomp-boot / rocq-mathcomp-order, and released/ carries neither
package below 2.5.0: the only version directories present are 2.5.0,
2.6.0 and dev. So no solution at ssreflect 2.4.0 can compile these
sources, and the declared floor describes a configuration that cannot
work.

Worth naming because the obvious probe says otherwise: mathcomp 2.4.0
does install boot/ and order/ directories, so `test -d` passes on both.
They are empty. Counting entries is the only check that discriminates.

Stated on ssreflect alone, which is sufficient and is the whole fix:
coq-mathcomp-ssreflect.2.5.0 requires rocq-mathcomp-ssreflect
{= version}, which requires rocq-mathcomp-boot {= version} and
rocq-mathcomp-order {= version}. Declaring boot/order here as well
would add nothing.

The sibling 2.4.0 floors are deliberately left alone. At 2.4.0 the core
stack still locks downward -- rocq-mathcomp-algebra.2.4.0 requires
fingroup {= version}, which requires ssreflect {= version} -- so raising
ssreflect raises fingroup, algebra, solvable and field with it.

Latent, not visible today: per the solver's newest-permitted preference
it picks 2.6.0/dev and the hole never fires. Like the two hollight rows
in 6fc3d12, this is a pre-existing recipe bug rather than a port
regression; the constraint is not doing the work, the switch is.

One interaction, checked and benign: coq-mathcomp-algebra-tactics 1.2.5
and 1.2.6 cap ssreflect at < 2.5~, so the new floor excludes them. 1.2.7
(< 2.6~) and .dev remain above this recipe's own >= 1.2.6 floor, so the
formula stays satisfiable; against mathcomp 2.6.0 only .dev qualifies.

Static evidence only: source grep against
github.com/affeldt-aist/infotheo#master, constraint reading across
released/, and opam lint. Not built -- building means installing into a
degraded switch.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01L9BGQT7XUuubV6C619DW4b
(cherry picked from commit a444b95b8f193985ebec52d0caa8710ee554d942)
6 of the 52 .v files in coq-community/coqeal open with a Require of
`all_boot`, all of them under theory/, which is exactly what this recipe's
`build: [make -j]` compiles:

  theory/closed_poly.v    theory/jordan.v
  theory/companion.v      theory/perm_eq_image.v
  theory/frobenius_form.v theory/smith_complements.v

`all_boot` ships from rocq-mathcomp-boot, and released/ carries no version of
that package below 2.5.0 -- the only version dirs are 2.5.0, 2.6.0 and dev.
So `{>= "2.3"}` admitted a range whose lower half cannot build these sources.

Which limb of the rule this is. Screening a source for the boot split has
three outcomes, not one, and only the first wants a floor:

  Require all_boot / all_order / mathcomp.boot.*  -> FLOOR {>= "2.5.0"}   <- this
  qualified mathcomp.ssreflect.<mod>              -> source rewrite
  all_ssreflect, or bare ssreflect/choice/ssrbool -> nothing; both still
                                                     resolve at dev

The measured limb here is the first: all_boot present, no qualified
mathcomp.ssreflect.* paths. A floor is wrong for the third limb, and a ceiling
would be actively harmful anywhere, since only a ceiling can exclude dev.

Why the bound goes on ssreflect and not on the bare coq-mathcomp-algebra
sitting next to it: a constraint on a sibling reaches ssreflect only through
whatever that sibling itself declares. algebra's own dependency is
`{= version}`, so at 2.4.0 it locks the stack *downward* and would not lift
the floor.

What this does not do: it fixes which mathcomp resolves, never whether the
prover is dev. That is a separate line and a separate change.

Evidence root: /data/tmp/claude-1005/port/infotheo/srcprobe (shallow clone of
coq-community/coqeal); recipe read from extra-dev/packages on branch
dev-packages-needing-ports, 421 .dev recipes in that population.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01L9BGQT7XUuubV6C619DW4b
(cherry picked from commit bb2f7b8d91ab06a04a68956786c06e319c749078)
…mpossible

3 of the 10 .v files in math-comp/real-closed open with a Require of
`all_boot` -- theories/polyrcf.v, theories/qe_rcf_th.v, theories/realalg.v --
all under theories/, which is what `build: [make -j]` compiles.

`all_boot` ships from rocq-mathcomp-boot, and released/ carries no version of
that package below 2.5.0. `{>= "2.4"}` therefore admitted a range whose lower
half cannot build these sources.

Which limb of the rule this is. The boot-split screen has three outcomes and
only the first wants a floor:

  Require all_boot / all_order / mathcomp.boot.*  -> FLOOR {>= "2.5.0"}   <- this
  qualified mathcomp.ssreflect.<mod>              -> source rewrite
  all_ssreflect, or bare ssreflect/choice/ssrbool -> nothing; both still
                                                     resolve at dev

Measured limb here is the first. A floor is wrong for the third, and a ceiling
is the expensive error anywhere, since only a ceiling excludes dev outright.

The bound goes on ssreflect rather than on the bare rocq-mathcomp-algebra and
rocq-mathcomp-field beside it: a sibling reaches ssreflect only through what
the sibling declares, and both declare `{= version}`, which locks the core
stack downward instead of lifting it.

rocq-mathcomp-bigenough {>= "1.0.0"} is deliberately untouched -- bigenough is
a satellite on its own version line, not part of the 1.6...2.6.0 core series,
so comparing its floor against 2.5.0 would be a category error.

Unlike the sibling recipes in this series, this row's prover line is already
`rocq-core {= "dev"}`, so nothing here is masking a released prover. The floor
still only fixes which mathcomp resolves; it says nothing about the prover in
general.

Evidence root: /data/tmp/claude-1005/port/infotheo/srcprobe (shallow clone of
math-comp/real-closed); recipe read from extra-dev/packages on branch
dev-packages-needing-ports, 421 .dev recipes in that population.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01L9BGQT7XUuubV6C619DW4b
(cherry picked from commit 84c90377d818c51e31f6733f765f07d24e2b760a)
…not a bump

Read the diff carefully: this is an ADDED dependency line, not a raised bound.
The recipe declared no ssreflect dependency at all, so there was no floor here
to bump -- which is why this row survived a screen keyed on low floors.

3 of the 15 .v files under examples/std require `all_boot`:

  examples/std/int_to_Zp.v
  examples/std/flt3_step.v
  examples/std/square_and_cube_mod7.v

and examples/std is precisely the subtree the recipe builds:
`build: [make "-C" "examples/std"]`. So these three files are not incidental
repository content; they are the deliverable. `all_boot` ships from
rocq-mathcomp-boot, which released/ carries only at 2.5.0, 2.6.0 and dev.

Why the line names ssreflect and not the coq-mathcomp-algebra already present.
A bound on a sibling reaches ssreflect only through what that sibling itself
declares, and algebra declares `{= version}` -- a lock that pins the core stack
downward rather than lifting a floor. This is the row where the temptation to
constrain the sibling is strongest, because algebra is sitting right there and
looks like the natural place. It is not.

Which limb of the rule this is. The boot-split screen has three outcomes and
only the first wants a floor:

  Require all_boot / all_order / mathcomp.boot.*  -> FLOOR {>= "2.5.0"}   <- this
  qualified mathcomp.ssreflect.<mod>              -> source rewrite
  all_ssreflect, or bare ssreflect/choice/ssrbool -> nothing; both still
                                                     resolve at dev

Measured limb is the first. Note the two false markers in the third row: they
look pre-boot and resolve fine, so screening on them yields a ceiling -- and a
ceiling is the expensive error, since only a ceiling excludes dev outright.

Deliberately NOT changed here: the prover line is `coq {>= "8.20"}`, a
floor with no upper bound and no dev arm, so this row can still resolve a
released prover and green having exercised no dev at all. A mathcomp floor
cannot reach that; it fixes which mathcomp resolves, never which prover.
Left for the prover-line pass so two changes do not collide in one dep block.

Evidence root: /data/tmp/claude-1005/port/infotheo/srcprobe (shallow clone of
coq-community/trocq); recipe read from extra-dev/packages on branch
dev-packages-needing-ports, 421 .dev recipes in that population.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01L9BGQT7XUuubV6C619DW4b
(cherry picked from commit 42881e64d6cfb69bb1fd5e23ec24718a12adeb30)
….dev

Both are `.dev` recipes tracking a moving branch, and neither required a dev
prover. infotheo declared a BARE `"coq"` with no constraint at all; laproof
declared `"coq" {>= "9.0"}`, a floor with no ceiling. Both permit a dev prover
without ever forcing one, so either row can go green having exercised no dev
code -- the shape rocq-prover#52's promotion gate exists to catch. Replace both with
`"coq" {= "dev"}`.

The mathcomp floors already on these recipes cannot substitute for this. A
dependency's version constrains the prover only through what that dependency
itself declares, and no choice of ssreflect forces dev:

  rocq-mathcomp-boot.2.5.0  ("coq" {>= "8.20" & < "8.21~"}
                             | "rocq-core" {>= "9.0" & < "9.2~"})   capped
  rocq-mathcomp-boot.2.6.0  "rocq-core" {>= "9.0"}                  floor only
  rocq-mathcomp-boot.dev    ("coq" {>= "8.20" & < "8.21~"}
                             | "rocq-core" {>= "9.0" | = "dev"})    a MENU

The last arm is the decisive one: it names dev as an OPTION, and its other
disjunct `>= "9.0"` is satisfied by rocq-core.9.1.dev -- a real package core-dev
builds from a release branch, not a phantom. So even ssreflect.dev leaves the
solver free to pick 9.1.

NO BUILD WAS RUN BEHIND THIS CHANGE, and stating that is part of the change.
infotheo is parked under a do-not-rebuild constraint, so the usual "verify by
installing" was unavailable for it and neither row was compiled. The evidence
here is entirely a constraint reading, and it is one-directional: what is shown
is that nothing in the archive FORCES a dev prover for these rows, which is
what makes the edit necessary. It is not a claim that the rows now build.

Screened before pinning, since pinning dev on a row whose closure forbids it
converts a misleading green into a silent skip: every dependency of both
recipes ships a `.dev` version, and none is provably capped below a dev prover.
That screen is also one-directional -- it found no blocker, which is weaker
than establishing satisfiability.

Deliberately NOT changed: laproof's `"coq-mathcomp-ssreflect" {>= "2.4.0~"}`
still sits below the 2.5.0 boot/order boundary. Raising it needs the same
source-keyed evidence that justified the infotheo floor in a444b95b8 (which
files require all_boot / all_order), and that evidence has not been gathered
for LAProof. Guessing a floor without it is the error this series keeps
finding. Left for the deferred source-keyed pass.

Stacked on a444b95b8 deliberately: that commit rewrites the same `depends:`
block of the same file and is NOT on dev-packages-needing-ports, so basing this
there instead would have produced a conflicting edit to one block.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01L9BGQT7XUuubV6C619DW4b
(cherry picked from commit 3abf10a7fd1454ffb46f7f40db46261b72a42dd6)
Twelve iris recipes in the archive carry a stdpp dev escape arm --
eleven coq-iris releases naming coq-stdpp and rocq-iris.4.5.0 naming
rocq-stdpp -- and none of them can be satisfied, because no stdpp
package at version dev exists in any of the three repositories.

This adds the rocq-stdpp side. It closes the rocq-iris.4.5.0 arm, which
is the only one of the twelve that names a package the upstream project
still publishes. The eleven coq-stdpp arms are left open on purpose: the
std++ team stopped publishing anything under the coq- name in August
2025 and widened rocq-stdpp's conflicts field to retire it, so closing
those arms means resurrecting a name upstream deliberately dropped.

The recipe is upstream's own rocq-stdpp.opam from stdpp master, with the
url pointed at the tracked branch and the two prover menus tightened to
require dev, as in f55c8a1.

stdpp master at 45d12a56 builds against Rocq 9.4+alpha with no source
change: 55 of 55 .vo, no error output, deprecation warnings only.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01L9BGQT7XUuubV6C619DW4b
Both .dev rows track validsdp master but had drifted years behind the
opam files upstream maintains in that same repo. The first build step ran
./autogen.sh && ./configure; upstream deleted autoconf, so that step exits
127 with "./autogen.sh: not found" and neither row has ever compiled a .v
file. Drop it, and drop conf-autoconf with it.

Take the dependency sets from upstream's coq-validsdp.opam and
coq-libvalidsdp.opam: coq-mathcomp-analysis is replaced by
coq-mathcomp-reals-stdlib, coq-paramcoq is gone, and the multinomials,
coqeal, interval and osdp floors move up to the ones upstream declares.
Add validsdp's run-test target.

Two places deviate from upstream on purpose. Upstream writes the prover and
mathcomp-field constraints as menus that permit dev without requiring it;
a .dev row tracking master has to require dev, so both are pinned. And
upstream's "< 5~" cap on coq-interval is not carried over, because opam
orders dev above every numeric version, so that cap would forbid
coq-interval.dev.

The package name stays coq rather than rocq-core: both Makefiles build via
$(COQBIN)coq_makefile with COQBIN taken from `which coqc`, and rocq-core
ships neither binary.

This does not turn either row green. Upstream master does not yet carry
the Rocq dev port, so a clean clone still fails at libvalidsdp/misc.v:80 --
now mid-compile rather than in build step 1. The url stays pointed at
upstream.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01L9BGQT7XUuubV6C619DW4b
…floor

These rows track a moving branch but constrain the prover with a bare floor
like {>= "8.20"}, or with nothing at all. opam orders dev above every numeric
version, so a floor admits dev without requiring it and the solver stays free
to pick a released prover. A .dev row can then go green against Coq 8.20
while never once building against the dev compiler it exists to test.

Pin coq, coq-core and rocq-core to {= "dev"}, and rocq-stdlib with them on the
rows that declare it.

All 15 are rows this branch added, so this only tightens our own work.
rocq-mathcomp-boot is left alone on purpose: its prover atom already admits
dev, and what lets a released prover in there is a separate capped
coq {>= "8.20" & < "8.21~"} arm that upstream wrote and asked in the file to
keep.

Every row was re-checked for satisfiability from the patched text afterwards.
Tightening a row whose dependencies cap the prover below dev turns a
diagnosable floor into a recipe no solver can satisfy, which is the worse
state; coq-mathcomp-cad is exactly that case, through an exact-pinned
ssreflect 2.2.0, and is deliberately not among these 15.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01L9BGQT7XUuubV6C619DW4b
The dep was unconstrained, so an extra-dev solve could satisfy it with
released `rocq-partial-orders.1.0`.  categories' Rocq-dev compatibility
depends on partial-orders' own Rocq-dev port (the HB `of` -> `&` rewrite
lives in both repos), so the .dev row has to name the .dev sibling — the
same shape the row already uses for rocq-core and rocq-stdlib.

The url{src} is deliberately left pointing at damien-pous/categories#main;
the row stays red until the port lands upstream.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01L9BGQT7XUuubV6C619DW4b
rocq-elpi-json.dev and rocq-elpi-xml.dev both depended on a bare
"rocq-elpi" with no version constraint.  The archive carries twelve
rocq-elpi versions (2.5.0 through 3.5.0, plus dev), so an unconstrained
atom admits all twelve and the solver is free to build a .dev app
against a released library; "dev" merely sorts highest, which is a
preference and not a constraint.  Pin both to dev.

This does not force a dev prover: rocq-elpi.dev's own prover line is a
plain "rocq-core" {>= "9.0"} floor.  That row is upstream's and is left
alone here.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01L9BGQT7XUuubV6C619DW4b
coq-riscv.dev tracked master but wrote all three of its dependencies as
"floor or dev" menus.  opam sorts dev above every numeric version, so
{>= "8.18~" | = "dev"} and {>= "8.18~"} admit exactly the same set: the
dev arm adds nothing and the floor is what actually binds.  A row whose
whole purpose is to track master could therefore resolve against a
released prover, coqutil, or record-update.  Pin all three to dev.

Upstream's disjunction is kept as a disjunction rather than collapsed,
and both arms are pinned.  Pinning the second arm is redundant today --
coq-fiat-crypto-with-bedrock publishes no version but .dev here -- and is
written anyway so that publishing a released one later cannot quietly
reintroduce a released dependency.

All three pinned versions resolve on this branch: coq.dev, coq-coqutil.dev
and coq-fiat-crypto-with-bedrock.dev come from upstream, and
coq-record-update.dev is added by bf05c00, an ancestor of this commit.
That is why this cannot be split out and sent against upstream master on
its own -- there the record-update pin would name a version that does not
exist, which is strictly worse than the floor it replaces.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01L9BGQT7XUuubV6C619DW4b
Both hollight-logic rows depended on "rocq-mathcomp-hollight-real-with-N"
{>= "0.0.0"}, a floor every version satisfies.  The archive has two: the
released 0.0.0 and the .dev row this branch adds.  0.0.0 constrains the
prover no more tightly than "rocq-prover" {>= "9.0"}, and a floor cannot
exclude dev, so it is genuinely selectable on a .dev row rather than
merely sorting below dev -- the same defect already written up a few
lines further down for hollight-logic's unif dependency.

Only the .dev recipe tracks master alongside these rows, so name it.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01L9BGQT7XUuubV6C619DW4b
`"coq" {(>= "8.16" & < "8.19~") | = "dev"}` is not the floor-or-dev menu
that f902bba36 tightened fifteen of.  Those menus were neutral: a bare floor
admits dev as well, so deleting the dev arm changed nothing and pinning it
merely stated what opam's version order already preferred.  Here the
released arm is a capped interval, it is the *other* arm, and it genuinely
selects -- every Coq from 8.16 up to but not including 8.19 satisfies it.

The row tracks VeriNum/vcfloat master and exists to test it against Rocq's
development branch.  A solver that answers with Coq 8.18 is not degrading
gracefully; it builds something nobody asked about and reports the result
under the dev row's name.  So delete the released arm.  What remains,
`{= "dev"}`, was already an arm of the same menu -- this narrows the
admitted set and adds nothing that was not admitted before.

The row is absent at upstream/master and added by this branch's 8b651c4,
so it is ours to tighten.  That also explains why the earlier prover-pinning
pass missed it: 8b651c4 lands after e3a41f1 and 977a400, so the row
did not exist when those ran.

Satisfiability was re-derived from the patched text rather than inferred
from the row's pre-patch verdict: with `coq` pinned to dev, coq-flocq,
coq-interval, coq-compcert and coq-bignums all still admit a dev prover, so
the row remains resolvable.  coq-mathcomp-cad rode along unpatched in the
same fixpoint as an in-graph negative control and correctly came out unable
to reach dev, which is the check that stops a `{= "dev"}` being written into
a row whose real cap lives in a dependency.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01L9BGQT7XUuubV6C619DW4b
…arm capped

All five carried

  (("coq-core"  {>= "8.20" & < "8.21~"} & "coq-stdlib") |
   ("rocq-core" {>= "9.0"  & < "9.2~"}  & "rocq-stdlib"))

and now carry the same shape with every atom at {= "dev"}.

opam sorts `dev` above every numeric version, so `< "8.21~"` and `< "9.2~"`
both exclude it. Every arm caps, so no arm rescues the other and the group as
a whole forbids the one prover these rows exist to test. A flat tokenizer that
descends into the parentheses scores the row PERMITTED, because no single atom
is the whole formula.

It does NOT follow that the rows never resolved. `< "9.2~"` still admits
rocq-core.9.1.dev, and rocq-prover#49 measured exactly that: all six built on 9.1.dev,
57-71 actions each. So the defect never presented as a red row. It manufactured
greens that had exercised no dev prover, which is the failure mode rocq-prover#52's
promotion gate exists to catch and the harder one to notice.

The cause is faithfulness. Each depends: block is a byte-identical copy of the
corresponding released 2.2.0 block -- verified by diffing all six against
released/packages/rocq-num-analysis*/2.2.0 -- where both caps are correct,
because 2.2.0 really is a Coq 8.20 / Rocq 9.0-9.1 release. Copied onto a row
that tracks depot.lipn master the same text is wrong. On any copied constraint
the floors carry over unchanged and every upper bound has to be re-justified
against dev or dropped.

Both arms are pinned rather than collapsed to the rocq-core one. Which naming
the build needs is a source question this patch does not answer: coq-core.dev
is a live package, not a dead alias -- it depends on rocq-runtime {= version}
and supplies the coqc-named binaries a coq_makefile-generated Makefile calls,
which is the mismatch rocq-prover#43 swept for. Keeping both arms leaves that choice
exactly where it was and changes only the version.

The two stdlib atoms were unconstrained and are now pinned too, so the solver
cannot pair rocq-core.dev with rocq-stdlib.9.0+rc1.

rocq-num-analysis.dev, the metapackage, is deliberately untouched: it declares
no prover at all, only its three siblings at {= version}, so it inherits this
tightening rather than needing its own copy. Five rows, not six.

All five are absent at upstream/master and added by this branch's 7a8aa98, so
this only tightens our own work.

WHAT THIS DOES NOT FIX. All six rows still cannot resolve a dev prover, and the
reason is now a single edge: rocq-num-analysis-subset.dev caps
coq-mathcomp-ssreflect {>= "2.3" & < "2.6~"}, which excludes 2.6.0 -- the
oldest mathcomp that reaches dev (rocq-prover#70's bound). The admitted set is exactly
{2.3.0, 2.4.0, 2.5.0} and none of the three is dev-reachable. The other four
rows and the metapackage arrive at that same edge through {= version} chains,
so the whole family is gated on it.

That cap is left alone on purpose. Raising it is not a metadata change: it
asserts that these sources build against mathcomp 2.6/dev, which nobody has
measured, and rocq-prover#70 ruled explicitly against making that assertion from the
recipe side. The measurement is rocq-prover#105's.

Re-derived from the patched text rather than inferred from the pre-patch
verdict. Before: all six fail at the OR group. After: the OR group passes on
every row and the first failure moves to the ssreflect cap, which is the
discriminating change. Two in-graph controls held across both runs --
rocq-stdlib.dev free, coq-mathcomp-ssreflect.2.5.0 capped. Every top-level item
was scored, not just the first failure, and the other three interval caps are
satisfiable rather than merely undetected: coq-mathcomp-classical
{>= "1.8" & < "1.15~"} via 1.11.0-1.14.0, coq-coquelicot {>= "3.4" & < "3.5~"}
via 3.4.4, coq-flocq {>= "4.2" & < "4.3~"} via 4.2.1/4.2.2 -- each checked for
a non-empty admitted set first, since the fixpoint treats a dependency with no
matching version as satisfied. Relaxing only the ssreflect cap, as an in-memory
counterfactual, frees all six.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01L9BGQT7XUuubV6C619DW4b
…wer)

Line 22 was a capped-interval-or-dev menu:

  "coq-core" {(>= "8.17" & < "9.3") | (= "dev")}

which admits 15 of the archive's 17 coq-core versions, all the way back to
8.17+rc1. `dev` is one option among many, and it is not the one opam prefers
for any reason a `.dev` row can rely on. Now `{= "dev"}`: 1 admitted.

This re-applies half of what 977a400 reverted. That revert's stated reason
does not hold for this row. It read the header

  # This file was generated from `meta.yml`, please do not edit manually.

as meaning our bounds belong upstream. But this path is ABSENT at
upstream/master and was added by our own bf05c00 (positive control:
rocq-elpi.dev is present at upstream/master through the same probe). The header
is a copy artifact -- it travelled with the text when bf05c00 lifted it out
of tchajed/coq-record-update's generated opam file, and it describes THAT
repo's file. Nothing regenerates the archive row, so editing it diverges from
no generator.

The revert's SECOND argument was right, and is why only one line moves here.
977a400 also restored the stdlib companion, on the grounds that pinning it
changed no solution. It does not, and the line is left alone:

  - every coq-stdlib.8.x requires "coq-core" {= version}, so with coq-core at
    dev the whole first arm dies -- and it caps at < "9.0" anyway, so it never
    admitted dev;
  - rocq-stdlib.9.0+rc1 requires rocq-core {>= "9.0" & < "9.1~"} and
    rocq-stdlib.9.2.0 requires {>= "9.1" & < "9.4~"}; each rocq-core.X requires
    rocq-runtime {= version}, and coq-core.dev requires rocq-runtime {= dev},
    so neither released rocq-stdlib can co-exist with it.

What survives is `= "dev"` alone. Pinning line 22 forces rocq-stdlib.dev
already, so restoring the companion pin would assert something about stdlib
naming that this change does not need to assert.

Kept as coq-core rather than switched to rocq-core, deliberately. coq-core
publishes `dev` (core-dev), and its synopsis is "Compatibility binaries for Coq
after the Rocq renaming ... compatibility binaries to call Rocq through
previous Coq commands like coqc coqtop". This row's build is
`make -j%{jobs}%` over a coq_makefile-generated Makefile, which calls coqc by
name. Moving to a rocq-core arm would satisfy the solver and remove the
binaries the build runs -- rocq-prover#43's mismatch. The findlib hazard that gutted
coq-core.<X> at dev does not reach here: this is a pure .v library with no
OCaml plugin and no findlib query.

Attribution, since it decided how this was handled: 977a400 is an agent
commit of this session, not a ruling by Jason. Every commit on this branch is
authored `Jason Gross <jason@theorem.dev>` because the git identity is shared,
so the author field cannot separate his decisions from ours; the
`Claude-Session` trailer can, and it names this session. Treating it as his
call parked a ready patch behind a person who never saw it.

Verified with controls both ways: opam lint --safe passes on the patched file
and on the pre-patch baseline (so no warning was introduced), and fails rc=1 on
a deliberately malformed control. Admitted-version counts re-run after a
reversed-argument call to satisfies() returned 17/17 for every input including
a control that must admit nothing -- caught by that control, not by inspection.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01L9BGQT7XUuubV6C619DW4b
coq-coqeal.dev constrains the prover with

    "coq" {(>= "8.20" & < "9.1~") | (= "dev")}

An OR is a menu, not a requirement. On a compiler where the dev prover cannot
be installed the solver simply takes the other arm, so the `| (= "dev")` arm
protects nothing -- it makes dev permitted, never required. The capped arm here
admits coq 8.20.x, 9.0.0, 9.0.1 and 9.0.dev, any of which lets this .dev row go
green without ever building against the compiler it exists to test.

Pin the prover to {= "dev"}, matching the treatment coq-riscv.dev already got.

Satisfiability re-checked from the patched text, since tightening a row whose
closure cannot reach dev turns a diagnosable floor into a recipe no solver can
satisfy -- the worse state. All seven non-prover deps have a .dev row in
extra-dev and every one is a shim onto its rocq- twin at {= version}, so they
resolve to rocq-*.dev. "coq" {= "dev"} pulls coq-core.dev and coq-stdlib.dev;
coq-core.dev and rocq-core.dev are siblings over the same rocq-runtime {= version},
and coq-stdlib.dev routes through rocq-stdlib.dev to rocq-core.dev. Nothing in
the closure conflicts.

This does not change the opam-build:4.09.0 job, and that is worth stating rather
than implying otherwise. coq-coqeal.dev is already excluded from that job by its
elpi closure: coq-elpi {>= "2.4.1"} resolves no lower than coq-elpi.2.4.0, and
every coq-elpi at 2.0 or above floors ocaml >= 4.10.0, while 2.5.0 and later are
shims onto rocq-elpi, which floors ocaml >= 4.10.0 and pulls elpi >= 2.0.7 at
ocaml >= 4.13.0. The job pins ocaml-base-compiler < 4.11.0. The bound this commit
fixes is therefore inert on 4.09.0 today; what it protects is the 4.14.2 and
5.3.0 legs, where the dev prover IS installable and the capped arm remains a
live alternative the solver may take for closure reasons.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01L9BGQT7XUuubV6C619DW4b
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
@JasonGross
JasonGross force-pushed the dev-packages-needing-ports branch from 588fb82 to 62a0ba0 Compare August 18, 2026 15:09
@coqbot-app coqbot-app Bot removed the needs: rebase PR should be synchronized with the master branch by rebasing. label Aug 18, 2026
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.

1 participant