You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
coq-kernel: the "no Admitted" gate exits 2 before it reads a file (bash array under dash) #3396
The Kernel PHI Admitted gate cannot fail for the reason it exists, and cannot pass for that reason either: under the container shell it dies on syntax before reading a single file.
The defect
.github/workflows/coq-kernel.yml, step Verify Kernel PHI layer has no Admitted, declares no shell: key, and neither does the job. The job runs in the coqorg/coq container, so the step shell is sh -e — dash. The body uses four bash-only constructs:
VFILES=() # line 61 of the body — the first one dash rejects
VFILES+=("coq/$f")
"${#VFILES[@]}"
done < <(grep -E "\.v$" coq/_CoqProject) # process substitution
The step comment already states the constraint — "This job runs in the coqorg/coq container, where the step shell is sh -e -- dash" — and the code below it then violates that constraint.
Measured
The step body was extracted verbatim from origin/master (89 lines, refusing to run if the extract does not contain VFILES) and run against a tree holding the 9 .v files coq/_CoqProject names, materialised from origin/master. Two shells × two states. /bin/sh on macOS is bash 3.2 and accepts arrays, so it is not a valid control here; /bin/dash was used.
shell
tree
exit
first line
dash
clean
2
body.sh: 61: Syntax error: "(" unexpected
dash
one Admitted. planted in coq/Kernel/Trit.v
2
body.sh: 61: Syntax error: "(" unexpected
bash
clean
0
reading 9 file(s) named by coq/_CoqProject
bash
one Admitted. planted
1
reading 9 file(s) named by coq/_CoqProject
Under the CI shell the gate returns the same thing whether or not an Admitted exists — it carries no information. Under bash it discriminates correctly. The bash row is the positive control: it proves the probe can tell the two states apart, so the dash row is a finding and not a broken probe.
Why it was not caught
The meta-gate written to protect this gate extracts the body from the YAML correctly and then runs it through subprocess.run(["bash", "-c", body]) — in a different shell from the one CI uses. It passes 13/13 and exits 0 on the same body that dash refuses. A gate and its guard disagreeing about the shell is the whole defect.
Separately, Coq kernel is not one of the four required contexts, so a red run here does not block a merge.
Repair
One line: shell: bash on the step, which is what the body was written for. Failure direction is safe — if bash were absent from the image the step fails loudly rather than passing silently.
The meta-gate needs the same shell as CI, or it will keep certifying bodies CI cannot run; that is the larger half and is filed here as context, not fixed by the one-line change.
CI confirms the local reproduction verbatim, and dates the outage.
When the defect entered
VFILES=() reached master in f460502 (2026-09-05 13:09 +07), the squash of #3238 — titled "Three checks that pass when their subject is out of reach". Before it, the step ran a two-file POSIX body: the 2026-09-04 master run (33863799898) shows step 10 concluding success and printing
OK: no Admitted in Phi.v or PhiFloat.v (both files read)
so the green history belongs to the old body, not to the array one. This is worth stating because a naive reading of the run list — a success on 09-04, failures after — invites the conclusion that something else broke.
What CI said on the commit that introduced it
Master run 33949034842, on f460502 itself. Step 10 was the only failing step, and its log reads:
Line 61, exit 2. The local reproduction against /bin/dash printed body.sh: 61: Syntax error: "(" unexpected and exited 2 — the same line number, the same message, the same code. The probe reproduced the runner exactly rather than merely resembling it.
What this changes about the original report
Nothing in the finding, but it sharpens the duration: the gate has been carrying no information since 2026-09-05 06:09 UTC, not since some older unknown point. Two days, not months.
It also names the reason it went unnoticed for those two days: Coq kernel is not one of the four required contexts, so a red run here blocks nothing — and #3397, the repair, auto-merged on the required four while the Coq run was still in progress.
Activity
fix(ci): run the Kernel Admitted gate under bash, not the container's…
gHashTag commentedon Sep 7, 2026
CI confirms the local reproduction verbatim, and dates the outage.
When the defect entered
VFILES=()reached master in f460502 (2026-09-05 13:09 +07), the squash of #3238 — titled "Three checks that pass when their subject is out of reach". Before it, the step ran a two-file POSIX body: the 2026-09-04 master run (33863799898) shows step 10 concluding success and printingso the green history belongs to the old body, not to the array one. This is worth stating because a naive reading of the run list — a success on 09-04, failures after — invites the conclusion that something else broke.
What CI said on the commit that introduced it
Master run
33949034842, on f460502 itself. Step 10 was the only failing step, and its log reads:Line 61, exit 2. The local reproduction against
/bin/dashprintedbody.sh: 61: Syntax error: "(" unexpectedand exited 2 — the same line number, the same message, the same code. The probe reproduced the runner exactly rather than merely resembling it.What this changes about the original report
Nothing in the finding, but it sharpens the duration: the gate has been carrying no information since 2026-09-05 06:09 UTC, not since some older unknown point. Two days, not months.
It also names the reason it went unnoticed for those two days:
Coq kernelis not one of the four required contexts, so a red run here blocks nothing — and #3397, the repair, auto-merged on the required four while the Coq run was still in progress.docs(now): entry for the ci-gates 598 skill section
docs(skill): ci-gates 598 — a gate and its guard must run the same sh…