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
uphold-gofmt, uphold-go-vet, uphold-go-build and uphold-go-test wrap the consumer toolchain, so 31 consumers run their Go gate from an uphold release instead of their own config #217
.pre-commit-hooks.yaml publishes four ids that run no uphold code: uphold-gofmt (gofmt -l ., tested for empty output), uphold-go-vet
(go vet ./...), uphold-go-build and uphold-go-test. hooks/lefthook.yml
carries the same four, conditioned on go.mod, merged wholesale into any
lefthook consumer that includes it. Each is a plain wrapper of a command from
the consumer's own toolchain.
A Go consumer wires gofmt, vet, build and test into its own lefthook or
pre-commit config; that is what those files are for. Shipping the same four
from uphold is a second copy of the consumer's gate, and the copy is the one
that couples the consumer's toolchain choice to an uphold release: the
consumer that wants staticcheck beside vet, or -race on its tests, or a
build tag, edits a rev: it does not own or transcribes the id back out.
The README defends them with the 24 hand-declared copies and the two gofmt
copies that could never fail. That was a real finding, and the fix for a
wrong gate in a consumer is a right gate in the consumer, not a gate moved
into a different tool. uphold hooks --identity exists to catch exactly the
drift the four ids were shipped to prevent, across repositories, without
owning the declaration.
Evidence
Fleet grep, 2026-09-21, every .pre-commit-config.yaml and lefthook.yml
under the Orgs tree and its submodules, clones excluded:
31 consumer configs reference at least one of the four ids, all in one
private organisation (Go connectors, derive kits and services), all through .pre-commit-config.yaml. The list is in the grep output, not here: a
private repository's name does not belong in a public tracker.
0 of the 31 run their own gofmt -l, go vet, go build or go test
beside the ids. The four ids are the only Go gate those repositories have.
1 consumer includes hooks/lefthook.yml as a lefthook remote and so gets
the four by merge.
So today this is not a duplicate to delete; it is a gate 31 repositories
would lose. Removal has to hand the gate back first.
Proposed
One fleet PR series, worktree per repo, that writes the four commands into
each of the 31 consumers' own .pre-commit-config.yaml (a local repo
with language: system, the same gofmt -l emptiness test) and drops
the four uphold-* ids from the HackingGate/uphold block. Roots last,
as the fleet bump recipe already does.
In the following uphold release, mark the four ids deprecated in .pre-commit-hooks.yaml and hooks/lefthook.yml: each entry's
description points at the consumer's own config as the place the gate
lives, and uphold hooks --identity is named as the cross-repository
check that catches a copy that drifted.
One release later, remove the four ids, the **Go repositories**
paragraphs under ## Install in the README, and the hooks/lefthook.yml
commands.
Not in scope
uphold-check, uphold-scan, uphold-scan-text, uphold-guard-* and uphold-supply-chain*: those run uphold's own code and are uphold's job.
What
.pre-commit-hooks.yamlpublishes four ids that run no uphold code:uphold-gofmt(gofmt -l ., tested for empty output),uphold-go-vet(
go vet ./...),uphold-go-buildanduphold-go-test.hooks/lefthook.ymlcarries the same four, conditioned on
go.mod, merged wholesale into anylefthook consumer that includes it. Each is a plain wrapper of a command from
the consumer's own toolchain.
A Go consumer wires gofmt, vet, build and test into its own lefthook or
pre-commit config; that is what those files are for. Shipping the same four
from uphold is a second copy of the consumer's gate, and the copy is the one
that couples the consumer's toolchain choice to an uphold release: the
consumer that wants staticcheck beside vet, or
-raceon its tests, or abuild tag, edits a
rev:it does not own or transcribes the id back out.The README defends them with the 24 hand-declared copies and the two
gofmtcopies that could never fail. That was a real finding, and the fix for a
wrong gate in a consumer is a right gate in the consumer, not a gate moved
into a different tool.
uphold hooks --identityexists to catch exactly thedrift the four ids were shipped to prevent, across repositories, without
owning the declaration.
Evidence
Fleet grep, 2026-09-21, every
.pre-commit-config.yamlandlefthook.ymlunder the Orgs tree and its submodules, clones excluded:
private organisation (Go connectors, derive kits and services), all through
.pre-commit-config.yaml. The list is in the grep output, not here: aprivate repository's name does not belong in a public tracker.
gofmt -l,go vet,go buildorgo testbeside the ids. The four ids are the only Go gate those repositories have.
hooks/lefthook.ymlas a lefthook remote and so getsthe four by merge.
So today this is not a duplicate to delete; it is a gate 31 repositories
would lose. Removal has to hand the gate back first.
Proposed
each of the 31 consumers' own
.pre-commit-config.yaml(alocalrepowith
language: system, the samegofmt -lemptiness test) and dropsthe four
uphold-*ids from theHackingGate/upholdblock. Roots last,as the fleet bump recipe already does.
.pre-commit-hooks.yamlandhooks/lefthook.yml: each entry'sdescription points at the consumer's own config as the place the gate
lives, and
uphold hooks --identityis named as the cross-repositorycheck that catches a copy that drifted.
**Go repositories**paragraphs under
## Installin the README, and thehooks/lefthook.ymlcommands.
Not in scope
uphold-check,uphold-scan,uphold-scan-text,uphold-guard-*anduphold-supply-chain*: those run uphold's own code and are uphold's job.code, run from uphold's own ladder. It is this repository as its own
consumer, and the argument above does not touch it.
localblock the 31 consumers get is not a new uphold artifact; it isthe consumer's file, and the consumer edits it.
What would close it
.pre-commit-hooks.yamlandhooks/lefthook.yml.## Installno longer describes them;docs/REFERENCE.mdno longer lists them.
consumer-owned.
Related: #215 (the matrix), #216 (the syntax rung beyond Rust, whose recipe
scope was dropped for the same reason).