Skip to content

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

Description

@HackingGate

What

.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

  1. 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.
  2. 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.
  3. 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.
  • The fail-closed property is tested, not proven: extract the evaluator core and verify it with Verus #213: Verus over this binary's own evaluator core is a gate on uphold's own
    code, run from uphold's own ladder. It is this repository as its own
    consumer, and the argument above does not touch it.
  • The local block the 31 consumers get is not a new uphold artifact; it is
    the consumer's file, and the consumer edits it.

What would close it

Related: #215 (the matrix), #216 (the syntax rung beyond Rust, whose recipe
scope was dropped for the same reason).

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions