Skip to content

feat(rocq): add Flocq/Gappa/Coq-Interval for machine-checked FP error bounds - #41

Merged
avrabe merged 1 commit into
mainfrom
feat/gappa-flocq-interval-toolchain
Jul 21, 2026
Merged

feat(rocq): add Flocq/Gappa/Coq-Interval for machine-checked FP error bounds#41
avrabe merged 1 commit into
mainfrom
feat/gappa-flocq-interval-toolchain

Conversation

@avrabe

@avrabe avrabe commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

Summary

Implements #37 / FEAT-001: machine-checked floating-point error-bound proofs (Gappa for rounding, Coq-Interval for approximation, Flocq underneath), for relay's flight-math kernels to raise assurance above their existing exhaustive-enumeration empirical bound.

  • rocq/extensions.bzl: adds coqPackages.flocq/interval/coquelicot (nixpkgs, already built against this toolchain's exact Rocq 9.0.1) and the standalone gappa binary (an external CLI, not a Coq plugin).
  • rocq/private/gappalib_repository.bzl (new): nixpkgs has no coq-gappa/gappalib-coq package at this pin — confirmed by enumerating coqPackages at the pinned commit. gappalib-coq (Gappa's Rocq support library, the Gappa.Gappa_library that gappa -Bcoq output Require Imports) is built from source against Flocq, the same way smpl is already built from source for this Rocq version. The interactive gappa tactic ML plugin (Gappa_tactic.v) is intentionally excluded — this toolchain drives gappa as an external CLI, never the in-Coq tactic.
  • rocq/toolchain.bzl: wires flocq/interval/coquelicot/gappalib into rocq_toolchain_info's extra_libs, toolchain-wide, same pattern as coqutil/hammer/smpl.
  • rocq/defs.bzl: adds the gappa_proof macro. Per rivet CC-002, Gappa's CLI output is never trusted directly — the macro always compiles the emitted proof term with rocq_library, so the target fails exactly like any other Rocq proof if the kernel rejects what Gappa produced.
  • examples/gappa_proof/: minimal template proving one f32 rounding bound end-to-end.
  • artifacts/requirements.yaml: REQ-002/DD-001/FEAT-001 updated to implemented, corrected to reflect that nixpkgs has no coq-gappa package (an inaccurate assumption in the original ask and in the rivet bootstrap pass), and reference the concrete Bazel test as verification evidence.

Test plan

  • bazel build //examples/gappa_proof:rounding_bound — real gappa binary emits the Rocq proof script via a genrule, coqc compiles it against the from-source gappalib-coq + nixpkgs Flocq
  • bazel test //examples/gappa_proof:rounding_bound_testPASSED
  • bazel test //tests/... — pre-existing failure reproduced identically on unmodified main (a local macOS linker issue in the Rust toolchain, unrelated to this change); this PR's new target doesn't depend on the Rust/rocq-of-rust path at all
  • rivet validate — PASS
  • buildifier formatting fixed on all touched/new files

Closes #37

🤖 Generated with Claude Code

https://claude.ai/code/session_011MptgyfLZuHYCbfpq1zDey

… bounds

Implements #37 / FEAT-001: enables machine-checked floating-point
error-bound proofs (Gappa for rounding, Coq-Interval for approximation,
Flocq underneath), for relay's flight-math kernels to raise assurance
above their existing exhaustive-enumeration empirical bound.

- rocq/extensions.bzl: add nixpkgs_package entries for
  coqPackages.flocq/interval/coquelicot (already built against the
  toolchain's exact Rocq 9.0.1) and the standalone `gappa` binary
  (an external CLI, not a Coq plugin).
- rocq/private/gappalib_repository.bzl: nixpkgs has no coq-gappa/
  gappalib-coq package at this pin, so gappalib-coq (Gappa's Rocq
  support library -- the `Gappa.Gappa_library` that gappa -Bcoq output
  Require Imports) is built from source against Flocq, the same way
  smpl is already built from source for this Rocq version. The
  interactive gappa tactic ML plugin (Gappa_tactic.v) is excluded --
  this toolchain drives gappa as an external CLI, never the in-Coq
  tactic.
- rocq/toolchain.bzl: wire flocq/interval/coquelicot/gappalib into
  rocq_toolchain_info's extra_libs, toolchain-wide, same as coqutil/
  hammer/smpl.
- rocq/defs.bzl: add the gappa_proof macro. Per rivet CC-002, Gappa's
  CLI output is never trusted directly -- the macro always compiles
  the emitted proof term with rocq_library, so the target fails like
  any other Rocq proof if the kernel rejects what Gappa produced.
- examples/gappa_proof/: minimal template proving one f32 rounding
  bound end-to-end. Verified locally: `bazel test
  //examples/gappa_proof:rounding_bound_test` -- PASSED (real gappa
  binary emits the proof, real coqc kernel-checks it).
- artifacts/requirements.yaml: REQ-002/DD-001/FEAT-001 updated to
  implemented, corrected to reflect that nixpkgs has no coq-gappa
  package (an inaccurate assumption in the original ask and in the
  rivet bootstrap pass), and reference the concrete Bazel test as
  verification evidence.

Closes #37

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011MptgyfLZuHYCbfpq1zDey
@avrabe
avrabe merged commit 7fc6a3b into main Jul 21, 2026
13 of 15 checks passed
@avrabe
avrabe deleted the feat/gappa-flocq-interval-toolchain branch July 21, 2026 19:04
avrabe added a commit that referenced this pull request Jul 21, 2026
)

* docs: gate README claims against live evidence (claim-verification)

Audited this repo's load-bearing claims after the badge fix (#36/#38) and
the Gappa/Flocq/Coq-Interval toolchain feature (#37/#41):

- Found the footer tagline still carried the retired flat-verification
  overclaim ("formally verified WebAssembly toolchain for safety-critical
  systems") -- the same overclaim #36 fixed in the badge, just relocated,
  and factually wrong on top (this repo has nothing to do with
  WebAssembly). Replaced with an accurate description.
- Toolchain Contents table and Examples section were stale after #41 --
  didn't mention Flocq/Coq-Interval/Coquelicot/Gappa or
  examples/gappa_proof. Updated both.
- Added claims.yaml + tools/claim_check.py (the claim-verification skill's
  reference implementation): each load-bearing README claim is bound to a
  predicate re-derived from the actual source (file-exists, count-min,
  count-max on the retired overclaims) rather than trusted as prose.
- Wired `claim-check` into CI as its own job: a stale or overclaiming
  README now fails the build the same way an un-kernel-checked proof
  fails a rocq_proof_test.

All 5 claims pass against current main: `python3 tools/claim_check.py
claims.yaml` -> 5/5.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011MptgyfLZuHYCbfpq1zDey

* fix(ci): use --break-system-packages for pip install in claim-check job

The self-hosted smithy runners are Debian/python3.12 with PEP 668's
externally-managed-environment guard, which refuses a bare pip install.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011MptgyfLZuHYCbfpq1zDey

---------

Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
avrabe added a commit that referenced this pull request Jul 22, 2026
… (DD-003)

Replaces the previous commit's coqPackages.mathcomp wiring, which doesn't
fix the bug: `nix build coqPackages.mathcomp` produces only a 1-file
umbrella re-export (lib/coq/9.0/user-contrib/mathcomp/all/all.vo), not
the mathcomp-boot package the original error names
("Cannot load mathcomp.boot.seq").

The real dependency closure, read off nixpkgs directly (not guessed):
`coqPackages.interval.propagatedBuildInputs` = bignums, coquelicot,
flocq, mathcomp-boot, mathcomp-fingroup. mathcomp-boot itself needs
hierarchy-builder, which needs the coq-elpi OCaml plugin, whose own
OCaml findlib deps (ppx_deriving.runtime, ...) go deeper still --
hand-wiring each as a separate nixpkgs_package + -Q flag doesn't scale
past this point.

- rocq/extensions.bzl: @rocq_interval_env is a single
  `coq_9_0.withPackages (p: [p.flocq p.interval p.coquelicot])`
  composition that resolves the entire transitive closure automatically
  (mathcomp-boot/fingroup, bignums, hierarchy-builder, coq-elpi and its
  OCaml deps) -- exactly the way nixpkgs is designed to solve this. Its
  own subdirs are already named Flocq/Interval/mathcomp/Bignums/HB/elpi,
  so exposing the tree needs no manual -Q reconstruction at all.
- rocq/private/rocq.bzl: new rocq_interval_proof rule compiles against
  this dedicated environment's own coqc (no -Q flags needed -- it has
  its own default load path baked in). The primary toolchain
  (coqutil/Hammer/smpl, rocq-of-rust) is untouched.
- examples/interval_proof/: a real smoke test -- Require Import
  Interval.Tactic, `interval` tactic discharges a goal. Verified:
  `bazel test //examples/interval_proof:smoke_test` -- PASSED. Nothing
  exercised this before (#41/#43 both went green on CI without proving
  the capability worked).
- artifacts/requirements.yaml: FEAT-001/REQ-002 back to implemented
  (genuinely this time); DD-003 records the verified decision and why
  hand-wiring the closure was rejected.
- README.md / claims.yaml: document the new capability and gate the
  claim the same way as the rest of this repo's doc claims.

Closes #43

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011MptgyfLZuHYCbfpq1zDey
avrabe added a commit that referenced this pull request Jul 22, 2026
…le without it (#43)

* feat(rocq): wire mathcomp into the toolchain (Coq-Interval dep)

Coq-Interval (added in #41) is present but UNUSABLE: `Require Import
Interval.Tactic` fails with "Cannot load mathcomp.boot.seq: no physical
path bound to mathcomp.boot" — Interval depends on Mathematical
Components, which the toolchain does not expose on the coqc load path.

This mirrors the Interval/Coquelicot wiring for mathcomp: a rocq_mathcomp
nixpkgs_package (coqPackages.mathcomp), a filegroup BUILD, the toolchain
`mathcomp` attr, and the extra_libs -Q binding (logical name `mathcomp`).

NOT YET VALIDATED end-to-end: on a consumer (relay) with a pinned
MODULE.bazel.lock, the module extension did not re-evaluate, so
rocq_mathcomp was not materialised and the smoke proof still failed with
the same error. Needs: (a) confirm `coqPackages.mathcomp` is the right nix
attribute (modern mathcomp is split into boot/ssreflect/algebra — a meta
vs component question), (b) confirm the `/mathcomp/` path pattern +
lib/coq glob match the nix output layout, (c) a lock refresh so the
extension re-runs. Filed so the approximation-layer FP proofs
(relay MATHF32-P04/P05) can proceed once green.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HvusAXYbHLyv3uTzfBcMbG

* fix(rocq): make Coq-Interval actually usable via coq_9_0.withPackages (DD-003)

Replaces the previous commit's coqPackages.mathcomp wiring, which doesn't
fix the bug: `nix build coqPackages.mathcomp` produces only a 1-file
umbrella re-export (lib/coq/9.0/user-contrib/mathcomp/all/all.vo), not
the mathcomp-boot package the original error names
("Cannot load mathcomp.boot.seq").

The real dependency closure, read off nixpkgs directly (not guessed):
`coqPackages.interval.propagatedBuildInputs` = bignums, coquelicot,
flocq, mathcomp-boot, mathcomp-fingroup. mathcomp-boot itself needs
hierarchy-builder, which needs the coq-elpi OCaml plugin, whose own
OCaml findlib deps (ppx_deriving.runtime, ...) go deeper still --
hand-wiring each as a separate nixpkgs_package + -Q flag doesn't scale
past this point.

- rocq/extensions.bzl: @rocq_interval_env is a single
  `coq_9_0.withPackages (p: [p.flocq p.interval p.coquelicot])`
  composition that resolves the entire transitive closure automatically
  (mathcomp-boot/fingroup, bignums, hierarchy-builder, coq-elpi and its
  OCaml deps) -- exactly the way nixpkgs is designed to solve this. Its
  own subdirs are already named Flocq/Interval/mathcomp/Bignums/HB/elpi,
  so exposing the tree needs no manual -Q reconstruction at all.
- rocq/private/rocq.bzl: new rocq_interval_proof rule compiles against
  this dedicated environment's own coqc (no -Q flags needed -- it has
  its own default load path baked in). The primary toolchain
  (coqutil/Hammer/smpl, rocq-of-rust) is untouched.
- examples/interval_proof/: a real smoke test -- Require Import
  Interval.Tactic, `interval` tactic discharges a goal. Verified:
  `bazel test //examples/interval_proof:smoke_test` -- PASSED. Nothing
  exercised this before (#41/#43 both went green on CI without proving
  the capability worked).
- artifacts/requirements.yaml: FEAT-001/REQ-002 back to implemented
  (genuinely this time); DD-003 records the verified decision and why
  hand-wiring the closure was rejected.
- README.md / claims.yaml: document the new capability and gate the
  claim the same way as the rest of this repo's doc claims.

Closes #43

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011MptgyfLZuHYCbfpq1zDey

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Toolchain: add Flocq + Gappa + Coq-Interval to enable machine-checked floating-point error-bound proofs

1 participant