Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions .githooks/pre-commit
Original file line numberDiff line numberDiff line change
Expand Up@@ -5,6 +5,18 @@
# which `pnpm install` runs. Cheap by construction: with no pending marker it
# exits before doing any work, which is every commit that did not just merge a
# generator-owned artifact (#4675).
#
# One commit is exempt, and only one: the MERGE commit itself, which the
# sanctioned landing sequence (`scripts/pm/os-regen-merge.sh`, step 3) commits
# BEFORE regenerating, so that "what main brought" stays readable apart from
# "what the change produces". That commit records a deferral instead of being
# refused; the immediately following commit must discharge it, and
# `.githooks/pre-push` refuses the push if none ever does (#8047).
#
# ⚠️ git does not run this hook for a merge it completes ITSELF — only for one
# you finish with `git commit`. A clean auto-committed merge therefore lands
# with the marker untouched and the refusal falls on the next commit, which is
# the same collection point either way.

if [ -z "$OS_SKIP_REGEN_CHECK" ]; then
node "$(git rev-parse --show-toplevel)/scripts/check-regen-pending.mjs" || exit 1
Expand Down
24 changes: 24 additions & 0 deletions .githooks/pre-push
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
#!/bin/sh
# Copyright (c) 2026 ObjectStack. Licensed under the Apache-2.0 license.
#
# The collection half of the os-regen deferred merge (#8047). `pre-commit` may
# accept a MERGE commit whose regeneration is deferred to the next commit — but
# at the moment it decides, that next commit does not exist yet, so it can only
# RECORD the deferral. Something has to be the event that notices the deferral
# was never discharged. Only two events can follow a merge commit: another
# commit (which `pre-commit` already refuses while the artifacts are stale) and
# the push. This is the push.
#
# Registered by the same `core.hooksPath=.githooks` that registers `pre-commit`,
# so it needs no change to `scripts/setup-git-hooks.mjs` and no separate opt-in.
#
# Cheap by construction, exactly like `pre-commit`: with no pending marker the
# script exits before doing any work, which is every push in this repo that did
# not just defer a merge. The ref list git writes on stdin is drained and
# ignored on purpose — the marker is per-worktree state, not per-ref state, so
# which refs are being pushed cannot change the answer.

if [ -z "$OS_SKIP_REGEN_CHECK" ]; then
cat >/dev/null
node "$(git rev-parse --show-toplevel)/scripts/check-regen-pending.mjs" --pre-push || exit 1
fi
12 changes: 12 additions & 0 deletions AGENTS.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -364,6 +364,18 @@ Even inside your own worktree, operate defensively:
`$GIT_DIR/os-regen-pending` and `pre-commit` refuses the commit until those
artifacts check clean. Sequence after a merge unchanged from §9: rebuild, then
`check:generated --fix` — you just cannot forget it. Worth knowing:
- **The MERGE commit itself is the one exemption, and it is a deferral, not a
pass** (maintainer ruling 2026-08-12). `scripts/pm/os-regen-merge.sh` is the
in-repo authority for landing one of these branches, and its step 3 commits
the merge **before**
regenerating on purpose: the driver exits 0 while silently dropping one side, so
only a separate regeneration commit on a known-good base lets a reviewer read
"what main brought" apart from "what the change produces". `pre-commit` records
that merge as a deferral and then holds you to it — the immediately following
commit must discharge it (every commit until then is refused, and a second merge
cannot defer on top of an outstanding one), and `.githooks/pre-push` refuses a
push that still owes one. ⛔ So this step never needs `--no-verify`, which was
the old spelling and skips *every* pre-commit check rather than this one.
- **The driver is a LOCAL facility** — the merge queue rebuilds server-side where no
custom driver runs, so the three hottest artifacts are **sharded** per
category/entry (`authorable-surface/`, `json-schema.manifest/`, `api-surface/`) to
Expand Down
Loading
Loading