1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
#!/usr/bin/env bash
# forjar pre-push: quality gate + quorum gate.
#
# TRACKED, unlike `.git/hooks/pre-push`, which git does not version. Install with
# `make install-hooks` (or scripts/install-hooks.sh). An uninstalled hook gates
# nobody, which is why the quorum spec names "the gate is local" as a live
# failure mode and why CI must mirror it -- see docs/specifications/quorum-spec.md.
#
# Bypass with: git push --no-verify (recorded in the reflog)
[ ||
# READ GIT'S PRE-PUSH PROTOCOL BEFORE ANYTHING ELSE CONSUMES STDIN.
#
# git feeds one line per ref being pushed:
# <local ref> <local sha> <remote ref> <remote sha>
#
# The REMOTE ref is the one that matters. Reading the local branch name instead
# was a real bypass found in review: `git checkout -b main && git push origin
# main:real-feature` takes the main exemption while pushing a feature branch.
# Anything below that reads stdin would eat these lines, so they are captured up
# front and every later consumer gets </dev/null.
#
# THE LOCAL SHA IS KEPT TOO (#400). It used to be discarded, so the gate learned
# WHICH branch was being pushed and then resolved that branch's diff, receipt and
# falsification test from whatever happened to be checked out. `git push origin
# branch-B` from a branch-A checkout was refused with "no quorum receipt at
# .quorum/branch-B.json" while the receipt sat in branch-B's own commit. One
# line per ref, "<sha> <ref>", because a push can carry several.
pushed_refs=""
while ; do
[ || continue
pushed_refs="
"
done
FAILED=0
# THE QUORUM GATE.
#
# Runs per pushed ref, because one `git push` can carry several and each is a
# separate claim about a separate branch. A deletion arrives as an all-zero
# LOCAL sha (measured: local_ref=[(delete)] local_sha=[000...0]); the gate now
# recognises that explicitly and exits 0 saying so, which is what this comment
# used to claim without it being true.
#
# The loop reads a here-STRING, not a pipeline: `printf ... | while read` runs
# the body in a subshell, so a $FAILED set inside it is discarded and a failing
# gate would report ❌ and then exit 0. Each invocation still gets </dev/null so
# it cannot eat the remaining lines.
if [; then
while ; do
[ || continue
if out=""; then
else
|
FAILED=1
fi
done
else
# No refs on stdin means this was not invoked as a hook. UNMEASURED is not a
# pass anywhere else in this repo and is not one here either.
if out=""; then
else
; | ; FAILED=1
fi
fi
if [; then
fi