Skip to content

Commit 6db1f6d

Browse files
ci: add Coq build oracle workflow (closes #227) (#231)
## Summary Closes #227 — adds `.github/workflows/coq-build.yml` so the standing directive "for proof PRs, the toolchain build is the ONLY merge oracle" is machine-enforced. ## Today's incident motivating this PR #224 admin-merged 7 min after PR #223; all 17 governance/scanner checks were green; `coqc` was not run; main broke with `tfuneff_lambda_retype_l1_m already exists`. Hotfix #226 restored compilation; #227 was filed in parallel asking for the oracle gap to be closed at workflow-level. ## What the workflow does - Triggers on PR + push-to-main, scoped to `formal/**` paths (only fires when proofs change). - Container: `coqorg/coq:8.18` (matches `formal/Justfile`'s pinned toolchain). - Builds via the same recipe `formal/Justfile all` uses: ``` coq_makefile -f _CoqProject -o build.mk make -f build.mk ``` - After a clean build, runs `Print Assumptions preservation_l2_via_l1` and prints the tail. Any new `Admitted.` / `Axiom` slippage shows as a workflow-output diff. ## What this PR does NOT do - Branch-protection / required-check designation is **owner's call** (admin-only in GitHub Settings). The workflow file ships first so the check identity exists; one green run on main lets you mark it required. ## Test plan - [ ] First CI run on this PR builds `formal/_CoqProject` clean - [ ] `Print Assumptions preservation_l2_via_l1` output appears in the log - [ ] (Manual, post-merge) Mark `Coq build — formal/_CoqProject` as a required check ## Refs - Closes #227 - Refs #229 (sibling — the broader "no Coq oracle" surface this closes) - Refs #226 (hotfix that motivated this) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent df6d7b5 commit 6db1f6d

1 file changed

Lines changed: 80 additions & 0 deletions

File tree

.github/workflows/coq-build.yml

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
# SPDX-License-Identifier: PMPL-1.0-or-later
2+
# Copyright (c) 2026 Jonathan D.A. Jewell (hyperpolymath) <j.d.a.jewell@open.ac.uk>
3+
#
4+
# coq-build.yml — type-checks every module in `formal/` (Rocq/Coq).
5+
#
6+
# Standing directive [[feedback_proof_pr_build_oracle_is_only_truth]]:
7+
# for proof PRs, the toolchain build is the ONLY merge oracle. Until
8+
# this workflow existed, the rule relied entirely on human discipline
9+
# — admin-merge could and did land a broken main when PR #224
10+
# duplicated `tfuneff_lambda_retype_l1_m` and all 17 unrelated
11+
# governance/scanner checks went green (see #227, hotfix #226).
12+
#
13+
# This is now a HARD GATE: any PR (or push to main) that breaks
14+
# `coq_makefile`-driven compilation of `formal/_CoqProject` fails
15+
# here BEFORE the admin-merge button is reachable for the auto-bot.
16+
#
17+
# The job also `Print Assumptions`-checks the load-bearing top-level
18+
# theorem `preservation_l2_via_l1` (TypingL2.v) so any new `Admitted.`
19+
# / `Axiom` slippage shows up as a diff in the workflow output.
20+
21+
name: Coq Build (formal/)
22+
23+
on:
24+
pull_request:
25+
paths:
26+
- 'formal/**'
27+
- '.github/workflows/coq-build.yml'
28+
push:
29+
branches: [main]
30+
paths:
31+
- 'formal/**'
32+
- '.github/workflows/coq-build.yml'
33+
34+
permissions:
35+
contents: read
36+
37+
concurrency:
38+
group: ${{ github.workflow }}-${{ github.ref }}
39+
cancel-in-progress: true
40+
41+
jobs:
42+
coq-build:
43+
name: Coq build — formal/_CoqProject
44+
runs-on: ubuntu-latest
45+
# coq:8.18 matches the toolchain pinned by formal/Justfile and the
46+
# local developer setup. Pin to a digest later once a stable
47+
# known-good image is decided on; for now the floating tag mirrors
48+
# `make` semantics — "what the maintainer's machine has".
49+
container:
50+
image: coqorg/coq:8.18
51+
52+
steps:
53+
- name: Checkout repository
54+
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
55+
56+
- name: Coq version (provenance)
57+
run: |
58+
coqc --version
59+
coq_makefile --help 2>&1 | head -1 || true
60+
61+
- name: Build formal/ via coq_makefile (the merge-oracle command)
62+
working-directory: formal
63+
run: |
64+
# Mirrors `formal/Justfile`'s `all` recipe:
65+
# coq_makefile -f _CoqProject -o build.mk
66+
# make -f build.mk
67+
# (Plain `make` instead of `just` so we don't need `just` in
68+
# the container — the recipe is two lines.)
69+
coq_makefile -f _CoqProject -o build.mk
70+
make -f build.mk
71+
72+
- name: Print Assumptions of load-bearing theorem
73+
working-directory: formal
74+
run: |
75+
# Surfaces any new Admitted / Axiom additions feeding into
76+
# preservation_l2_via_l1 (Phase D top-level result). A diff
77+
# in this output between PRs is the canonical "did this PR
78+
# introduce a new admit" signal.
79+
echo 'From Ephapax Require Import TypingL2. Print Assumptions preservation_l2_via_l1.' \
80+
| coqtop -R . Ephapax 2>&1 | tail -40

0 commit comments

Comments
 (0)