Skip to content

tooling(pin): register the seven ported hook files, each at its own upstream ref - #9255

Merged
os-sales merged 1 commit into
mainfrom
claude/issue-8696-hooks-per-file-pin
Sep 12, 2026
Merged

os-sales merged 1 commit into
mainfrom
claude/issue-8696-hooks-per-file-pin

Conversation

@claude

@claude claude Bot commented Sep 12, 2026 •

Copy link
Copy Markdown
Contributor

Fixes #8696

Registers the seven remaining ported .claude/hooks/** files in scripts/upstream-port-pin.json, per file rather than as one batch. All seven took outcome (A) — registered at their own ref, with every difference declared as an exact text pair carrying a one-sentence why. None needed outcome (B), so there is no "not pinned, because …" row below.

⛔ No .claude/** byte moves: --resync was never run, --rewrite-governed-file was never passed, and the pin schema is untouched. The diff is the ledger file plus a changeset.

Per-file outcome

Ref column shows the short sha; each entry carries the full 40-character sha, as validatePin requires. "pairs" is the declared divergence count for that entry. The last column is what the same measurement gives at upstream origin/main today (c2520416c blob for every one of these paths), which is the alternative ref considered.

ported file upstream ref outcome pairs why, in one line at upstream main instead
.claude/hooks/guard-main-checkout.sh c2520416c registered 2 card requalification (objectui#7259 for upstream's #11809) and the dropped note about a numbered Prime Directive this repo's AGENTS.md does not have same ref — this IS upstream main's blob
.claude/hooks/guard-main-checkout-bash.sh 924f0fed1 registered 21 objectui paths and package names, upstream card numbers qualified with their repo, sibling-anchored framing, and the same missing-PD-number note 22 pairs
.claude/hooks/guard-main-checkout-bash.selftest.sh 924f0fed1 registered 10 specimen paths and package names this repo has, plus the same card requalification in the case headers 12 pairs
.claude/hooks/guard-shared-stash.sh 2b9f5810b registered 10 this repo is the ORIGIN of this hook, so the provenance paragraph runs the other way; plus its own self-test case-count note and three regions of upstream prose this copy has not taken 11 pairs
.claude/hooks/guard-shared-stash.selftest.sh 2b9f5810b registered 17 two repos each wrote their own twin of the backslash fix, so the pairs are between two versions of one section, plus the usual specimen localisation 19 pairs
.claude/hooks/guard-tree-enum.sh c074c57e4 registered 3 the measured incident is THIS repository's, so the prose reads in the first person, and the mirroring note points the other way 4 pairs
.claude/hooks/guard-tree-enum.selftest.sh c074c57e4 registered 6 same first-person framing plus specimen paths, scripts and packages this repo actually has 8 pairs

objectui#7953's blocker is gone as the card says: two of these (guard-tree-enum.sh and its self-test) did not exist upstream at the ledger-wide ref that card was measured against, and they are now pinned at c074c57e4, the commit that created them upstream.

How the ref was chosen, per file

The rule applied, stated so it can be argued with rather than inferred: take the newest upstream ref whose content this copy already tracks. A ref newer than that adds pairs that are upstream work this repo has not ported; a ref older than that adds pairs that hide upstream work this copy already has. Both directions were measured; the last table column is the newer-ref side of that measurement.

The operational reason the newest-ref default was not taken blindly: --resync applies the declared pairs FORWARD onto the new upstream text. A pair that declares "upstream has a paragraph we do not" therefore teaches every future re-sync to delete that paragraph again, permanently. At the chosen ref those regions are simply not pairs, and a later re-sync brings them across.

The rule also moves the other way, and did for one file. guard-shared-stash.selftest.sh reaches its smallest set (7 pairs) at 9f2280163, but that ref predates a fix this copy HAS — the whole backslash matrix collapses into one 39-line pair that reads as objectui-only work and hides the fact that upstream has an equivalent. 2b9f5810b costs 10 more pairs and is the honest one: there the pairs are between two versions of the same section, including the case-matrix rows each repo carries and the other does not.

For guard-main-checkout.sh the rule lands on upstream origin/main's own blob, and that entry has 2 pairs and zero executable lines.

Verdict lines, before and after

origin/main e7173d9db, node scripts/check-upstream-port-parity.mjs, exit 0:

✓ check-upstream-port-parity: 4 ported file(s) match objectstack-ai/objectstack modulo their declared divergences, each at its own pinned ref (3 distinct: bf10debd5, 70e77ec3b, 61362932b). (The digest is verified; the ref beside it is provenance and is NOT fetched.)

This branch, same command, exit 0:

✓ check-upstream-port-parity: 11 ported file(s) match objectstack-ai/objectstack modulo their declared divergences, each at its own pinned ref (7 distinct: bf10debd5, 70e77ec3b, 61362932b, c2520416c, 924f0fed1, 2b9f5810b, c074c57e4). (The digest is verified; the ref beside it is provenance and is NOT fetched.)

Every one of the seven new entries prints its own ✓ … byte-identical to objectstack-ai/objectstack@REF:PATH modulo N declared divergence(s). line.

The gate's self-test, run first as lint.yml runs it, exit 0: ✓ check-upstream-port-parity self-test: 58 cases pass — ….

What the new entries make visible

The point of a ledger row is that it can be read. Three of the new pairs say out loud that this copy is behind upstream, and they are labelled that way in their why rather than dressed as decisions:

  • guard-shared-stash.sh — upstream's recovery-by-scrollback paragraph, and the fourth alternative in both the header list and the printed remedy (commit the fix first, then take it out with a path-scoped checkout).
  • guard-shared-stash.selftest.sh — upstream's && twin and its git -C twin of the escaped-quote block case.

Acting on those means editing .claude/**, which this card forbids; they are now ledger rows instead of nothing.

Acceptance notes

Out-of-scope observations, noted rather than filed (neither is a reproducible defect, a declared-contract breach, nor a metadata trap):

  • .github/workflows/lint.yml line 307 still reads "Ported from objectstack scripts/check-bash32-floor.mjs … and deliberately NOT registered in scripts/upstream-port-pin.json — that ledger carries ONE global upstream.ref". Both halves have been false since objectui#8288 retired the field and objectui#8694 registered the file; objectui#8694 remains open as the card whose PR left the comment behind.
  • scripts/check-bash32-floor.mjs's "## Why this port is not YET pinned" section says "It is still NOT registered". Same staleness, same taker; that file is itself a pinned port, so repairing it is a divergence-declaring edit rather than a free one.

Neither is touched here: this PR's diff is the ledger plus a changeset, and widening it would put a governed-adjacent workflow edit into a PR whose whole claim is that it moved no ported byte.

Local verification

  • node scripts/check-upstream-port-parity.mjs --self-test → exit 0, 58 cases.
  • node scripts/check-upstream-port-parity.mjs → exit 0, 11 of 11 green.
  • node scripts/check-control-bytes.mjs → exit 0, 7441 tracked text files scanned.
  • node scripts/check-changeset-presence.mjs → exit 0; node scripts/check-changeset-claims.mjs → exit 0.
  • node scripts/check-governed-queue-guard.mjs --test on both changed paths → NOT GOVERNED, 2 paths against 5 surfaces.
  • pnpm exec vitest run scripts/__tests__/upstream-port-parity-wiring.test.ts → Test Files 1 passed (1), Tests 12 passed (12). This is the gate's own wiring suite and the only suite in the tree that reads the pin file; it asserts coverage, the per-entry ref, and that no pinned path falls inside lint.yml's ignore set — the last one being what a new entry could have broken.

All of the above were run on 7394d3df7, this branch's head after the final commit, against a clean working tree. The repo-wide farm is CI's run, not this seat's.

Drafted by an automated developer session; the session reference is session_01MCLBsUgfykL74aU716rzVK, written here as prose because footer blocks are rewritten on this platform.


Generated by Claude Code


Generated by Claude Code

…pstream ref

`scripts/upstream-port-pin.json` carried four entries; the seven remaining
ported `.claude/hooks/**` files were unregistered, so an edit to any of them
was invisible to `check-upstream-port-parity`.

Each new entry names the upstream ref its digest was taken from, per file:
the ref at which this repo's copy already tracks upstream. Every difference
is declared as an exact text pair with a one-sentence reason. No hook byte
moves and the pin schema is unchanged.

Co-authored-by: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MCLBsUgfykL74aU716rzVK
@os-sales
os-sales marked this pull request as ready for review September 12, 2026 06:14
@os-sales
os-sales added this pull request to the merge queue Sep 12, 2026
Merged via the queue into main with commit 236a71f Sep 12, 2026
37 checks passed
@os-sales
os-sales deleted the claude/issue-8696-hooks-per-file-pin branch September 12, 2026 06:33
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.

devx: re-triage objectui#7953's ported .claude/hooks/** files against the per-file ref, per file rather than as one batch — item 3 of objectui#8385

2 participants