Skip to content

Pre-push hook: restore to fmt-only per CLAUDE.md's documented contract - #7251

Merged
briansrls merged 1 commit into
mainfrom
hooks/pre-push-fmt-only
Jul 25, 2026
Merged

briansrls merged 1 commit into
mainfrom
hooks/pre-push-fmt-only

Conversation

@gunbai-bot

@gunbai-bot gunbai-bot Bot commented Jul 25, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Operator ruling, 2026-07-25: "Pre-push hook restored to fmt-only per CLAUDE.md's documented contract; the witness corpus belongs to CI, not the push path."

.githooks/pre-push was a shim that exec'd claim_batch --pre-push, which ran the affected-set witness corpus — and would cargo build -p v1-compiler --bin claim_batch from inside the push when the binary was missing.

That weight bought zero enforcement. A git hook is opt-in per clone (core.hooksPath), bypassable with --no-verify, and absent in container worktrees; commit_workflow's own commit_gate_rust_suite_removed_disposition already records it proven ineffective — #6658 landed an unformatted .rs on main and no hook caught it.

So it was the worst of both worlds by construction: no enforcement, but enough weight to make a legitimately-red mid-lane branch feel unpushable — which is the pressure that converts honest reds into workaround greens. That cost is not hypothetical; it was priced today on the namespace type-binding lane as three rounds of hand-import workarounds, one decorative gate, and the normalization of --no-verify. A check that cannot enforce should at least be instant.

CLAUDE.md line 118 already documents pre-push runs cargo fmt. This restores reality to the doc; it is not a policy change.

What changed

  • commit_workflow.dag — the doc-reachability CommitWitnessClaim enrollment is dropped from the GitPrePushHook surface, leaving CommitCargoFmtCheck as the only row. A githooks_pre_push_slimmed_to_fmt_disposition records the removal as intentional, with the fail-closed coverage check.
  • githooks_pre_push_emit.dag — the hook body is now derived from commit_gate_roster via project_local_tidy_checks, so the roster stays the single authority (§3). ensure_bins, the in-hook cargo build, and exec "$CLAIM_BATCH" --pre-push are gone.
  • githooks_pre_commit_emit.dag — emit_freshness_path_fn / emit_glob_case_arms move here, its only remaining consumer.
  • githooks_pre_push_cli.dag — the disposition note no longer claims the hook shims to claim_batch; claim_batch --pre-push is now an on-demand local runner with a named dissolve-on.
  • githooks_pre_push_emit_test.dag — flipped to guard the new shape.

Emitted hook, in full:

#!/usr/bin/env bash
# GENERATED by dag/gunbc/githooks_pre_push_emit.dag — DO NOT HAND-EDIT.
set -euo pipefail
ROOT="$(git rev-parse --show-toplevel)"
cd "$ROOT"
echo "[pre-push] cargo fmt --all --check"
if ! cargo fmt --all --check; then
  echo "[pre-push] rustfmt drift — run: cargo fmt --all   (then commit and re-push, or 'git push --no-verify' to skip)" >&2
  exit 1
fi

Nothing loses enforcement

Fail-closed verification before removal (DESIGN §5 — do not drop a check without confirming the authoritative boundary still covers it):

  • cargo fmt --all --check is a required-path CI build step (ci_fmt_gate_note; build runs it first and ci needs:[build]).
  • The witness corpus is the required ci floor via gunbc_ci_floor_batches, which also stamps the merge-admission receipt.
  • dag/test/claim/doc_reachability_witness_test.dag keeps its cadence through the floor's discovery-corpus scan (CiSpec.discovery_scan_dirs covers dag/test/claim) — it loses only its redundant second run on the push path.

Test plan

Verified by execution, not by reading:

  • GREEN — clean tree: exit 0 in 4.9s (was: corpus run, plus a possible cargo build).
  • RED (discriminating) — injected fmt drift: exit 1 with the located diff and the fix recipe. Reverted after.
  • githooks_pre_push_emit_witnesses → true (flipped to assert no claim_batch / no ensure_bins / no cargo build / no corpus, and that fmt is the body)
  • githooks_pre_push_plan_witnesses → true
  • commit_workflow_witnesses → true
  • generated_artifact_drift_witnesses → true
  • generated_artifact_gate main_wet → ExitSuccess (hook regenerated; committed bytes match the emitter)

Declined

Branch-level expected-red exemption machinery, per the ruling: building configuration so a non-authority check can be tolerated invests in a mechanism that should not carry this weight at all — slimming dissolves the need, including for the second red stretch the namespace lane has coming. No skip env var was added; the heavy arms are gone from the model, not hidden behind a toggle (DESIGN §5, no escape hatches).

For reviewer attention

dag/gunbc/plans/commit_workflow.dag carries a stale freeze marker: "#5924 frozen — .githooks/pre-push / githooks_pre_push_emit.dag / local_tidy_spec.dag are not edited until this sketch is approved and handler re-expression is witnessed byte-identical." Today's operator ruling directs exactly this edit and post-dates that sketch, and this change is a content change (which rows run) rather than the handler re-expression the sketch contemplates. Flagging it rather than silently proceeding — the plan doc's marker should be updated or retired.

🤖 Generated with Claude Code

Operator ruling 2026-07-25: "Pre-push hook restored to fmt-only per
CLAUDE.md's documented contract; the witness corpus belongs to CI, not
the push path."

The hook was a shim that exec'd `claim_batch --pre-push`, which ran the
affected-set witness corpus and would cargo-build claim_batch from
inside the push when the binary was missing. That weight bought zero
enforcement — a hook is opt-in per clone (core.hooksPath), bypassable
with --no-verify, absent in container worktrees, and commit_workflow's
own dispositions already record it PROVEN ineffective (#6658 landed an
unformatted .rs on main and nothing caught it).

Worst of both worlds by construction: no enforcement, but enough weight
that a legitimately-red mid-lane branch feels unpushable — pressure that
converts honest reds into workaround greens. Priced receipt: three
rounds of hand-import workarounds, one decorative gate, and the
normalization of --no-verify on the namespace type-binding lane today.
A check that cannot enforce should at least be instant.

CLAUDE.md already documents "pre-push runs cargo fmt" — this restores
reality to the doc rather than changing policy.

Mechanism: the hook body is now DERIVED from commit_gate_roster's
GitPrePushHook enrollments via project_local_tidy_checks, so the roster
stays the single authority and re-heavying requires a roster edit the
emit witness reds on. The doc-reachability enrollment is dropped from
that surface (it keeps its cadence through the floor's discovery-corpus
scan of dag/test/claim). emit_freshness_path_fn / emit_glob_case_arms
move to githooks_pre_commit_emit, their only remaining consumer.

Nothing loses enforcement: cargo fmt is a required-path CI build step
(ci needs:[build]), and the witness corpus is the required `ci` floor
that also stamps the merge-admission receipt.

Verified by execution:
  - clean tree  -> exit 0 in 4.9s (was: corpus run + possible cargo build)
  - fmt drift   -> exit 1, located diff + fix recipe (discriminating RED)
  - githooks_pre_push_emit_witnesses  true (flipped to guard the new shape)
  - githooks_pre_push_plan_witnesses  true
  - commit_workflow_witnesses         true
  - generated_artifact_gate main_wet  ExitSuccess (hook regenerated)

Declined, per the ruling: branch-level expected-red exemption machinery.
Building configuration so a non-authority check can be tolerated invests
in a mechanism that should not carry this weight; slimming dissolves the
need. No skip env var added — the heavy arms are gone from the model,
not hidden behind a toggle (DESIGN §5 no-escape-hatches).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@gunbai-bot gunbai-bot Bot changed the title namespace Pre-push hook: restore to fmt-only per CLAUDE.md's documented contract Jul 25, 2026
@gunbai-bot
gunbai-bot Bot marked this pull request as ready for review July 25, 2026 21:47
@briansrls
briansrls merged commit fa868c5 into main Jul 25, 2026
5 of 10 checks passed
@briansrls
briansrls deleted the hooks/pre-push-fmt-only branch July 25, 2026 23:17
briansrls added a commit that referenced this pull request Jul 26, 2026
…fires when that lands) (#7254)

* WIP: namespace

* chore: regenerate drifted generated artifacts (ci auto-heal)

* Dissolve the commit-workflow sketch — its own trigger fired

gunbc.plans.commit_workflow declared: "Delete when gunbc.commit_workflow is
the sole roster authority, both handlers emit from it byte-identically, and
this sketch is superseded by the landed model." All three conjuncts verified
by execution, so the sketch dissolves rather than being maintained (DESIGN §6:
let the mark on the carrier be the authority, no parallel-ledger docs).

Verified before deleting:
  - sole roster authority: ci_spec.dag gunbc_ci_floor_gates / _regen_floor_gates
    / _floor_witness_entries and local_tidy_spec.dag local_tidy_checks all
    project from commit_gate_roster; no competing roster remains.
  - both handlers emit from it: ci_yaml_emit via the projected gate lists,
    githooks_pre_push_emit via project_local_tidy_checks.
  - checkpoint 2's dissolution target commit_workflow_projection_scaffold is
    gone from the corpus (the sketch's own prose was its last mention).

Also retires two stale freeze markers the sketch left behind, which asserted
that .githooks/pre-push / githooks_pre_push_emit.dag / local_tidy_spec.dag
"are not edited". That freeze was discharged when handler re-expression landed,
and is now superseded outright by the fmt-only hook ruling (2026-07-25). The
second copy lived in plans/branch_merge_admission_model.dag, which also cited
the deleted module as its deferral precedent; both re-pointed at the carrier
disposition that actually governs.

docs/plans/commit-workflow.md was hand-authored (HandAuthoredDocBind), not a
registered generated artifact, so it deletes with its authority; the
doc_graph_roots bind row and the ROADMAP shelf-sketch link go with it.

Green by execution: doc_graph_has_no_orphan_docs, _has_no_dangling_links,
_hand_authored_slugs_not_registered, _registered_plan_roots_all_admitted,
_universe_is_nonempty all true; generated_artifact_gate main_wet reaches a
byte-idempotent fixed point with ROADMAP.md as the only projection delta.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* WIP: namespace

---------

Co-authored-by: Brian Searls <briansrls@gunb.ai>
Co-authored-by: gunbc-ci-auto-heal <gunbc-ci-auto-heal@users.noreply.github.com>
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant