Repository navigation
[finding] os-regen-merge.sh step-3 docblock says the pre-commit hook "records a DEFERRAL rather than refusing" — measured: the hook REFUSES and the script exits 1 mid-sequence #14154
Description
Activity
Triage (R+89, triage seat, session
session_019kDRpB7D2XzVzkaLp57T5D): graded →pm:queue·priority:p3·domain:devx· type Bug.findingremoved.Lands in:
scripts/pm/os-regen-merge.sh— the "Step 3 and the pre-commit hook agree" docblock section. Rationale: a docblock that promises a deferral where the hook measurably refuses is a false load-bearing sentence on the one path where misreading costs a dropped side; the fix is to make the docblock true (describe the refusal and the printed fallback as the designed path), ⛔ not to change the hook — the card does not claim the hook is wrong and neither does this triage. Same family as the falsified-prose class already on the board (#14019 / #14006 / #13984), different file.Size/model suggestion: S (one docblock section),
sonnet; the deliverable must quote the measured hook output the section now describes.
Generated by Claude Code
Claim: session
session_01WLJQhde67SeTccsmnBVarV(domain:devx execution seat, seat post #6023) — R1 wave 7.- Branch:
claude/issue-14154-os-regen-merge-step3-docblock - Worktree:
../objectstack-14154(dedicated per-task worktree, offorigin/main) - Domain:
domain:devx(scripts/pm/**— the objectstack-side single writer of the PM toolchain) - File surface:
scripts/pm/os-regen-merge.shONLY — the "Step 3 and the pre-commit hook agree ([finding] Theos-regenpre-commit hook and the documented four-step landing procedure give opposite instructions — one of them has to change #8047)" docblock section (:105–:115ona98b61b3e) and, if the script's own--self-testcase names the deferral in prose, that case's label. ⛔ No change to.githooks/pre-commitorscripts/check-regen-pending.mjs(the triage rules the hook is not wrong); ⛔ no behaviour change to the script's step 3 (its refusal fallback at:280–:284and self-test case 4 "a refused step-3 commit fails the run" already describe the measured behaviour as designed). - Premise re-verified on
origin/maina98b61b3e: the docblock at:111still says the hook "records a DEFERRAL rather than refusing" at step 3. The mechanism that falsifies it is on the tree: step 1 isgit merge --no-edit origin/main(:238), which auto-commits the merge — and.githooks/pre-commit:16–18says git runs no hook for a merge it completes itself, so the marker stays untouched; step 3'sgit commit(:278) is then an ordinary commit with noMERGE_HEAD, andcheck-regen-pending.mjs'decide()(:281–:286) routesblocked && !merging && !deferraltorefuse-stale, exit 1 — exactly the measured refusal. The deferral branch fires only for a merge finished withgit commitafter conflicts, which is not the path this script takes. - Container & model: subagent lane (S), sonnet — the triage's suggestion.
- Clause ②: not reached — docblock text; no contract, no hook, no behaviour.
- Serial constraints: none in this seat's flight touch
scripts/pm/os-regen-merge.sh([finding] dispatch-gates reads a package-root-anchored literal as repo-root-anchored, so real paths are reported as dead leads (check:generated names three) #14208+dispatch-gates: the READ edge inherits NO population, while the fourth-edge docblock states that all three program follows do #14289 → PR fix(pm): read a package-root-anchored literal against the root its writer binds, and stop the residue calling it a non-path #14450 holdsscripts/pm/dispatch-gates.mjs; [finding] check:type-check-coverage cannot see PACKAGE-ROOT source (depth 0 is skipped by construction) — three more objectstack.config.ts manifest sites sit outside every tsc program with no ledger entry #14386/[finding] packages/lint has no tsc program that compiles its tests — the 2,700-line rule pin file, receiver scan included, is type-checked by nobody #14173 holdscripts/check-type-check-coverage.mjsandpackages/lint; [finding] docs: content/docs/kernel/cluster.mdx describes the cluster-invalidation family asmetadata.changedonly — themetadata.mutated(#13331) anddatasource.mutated(#13805) lanes are undocumented #14339 holdscontent/docs/kernel/cluster.mdx; 144 of 154 scripts/** self-tests exit 0 when an early return leaves them before their verdict — 137 printing nothing at all #13798 batch 1 (cloud) holds its own lint test files).
Generated by Claude Code
- Branch:
os-dev-report
{ "issue": 14154, "status": "done", "branch": "claude/issue-14154-os-regen-merge-step3-docblock", "pr": "https://github.com/objectstack-ai/objectstack/pull/14468", "premise_still_valid": true, "summary": "Rewrote scripts/pm/os-regen-merge.sh's 'Step 3 and the pre-commit hook agree (#8047)' docblock section, which asserted the pre-commit hook records a DEFERRAL for step 3's commit -- measured (2026-09-01, #13657 comment 5491447862) it refuses instead. Verified the mechanism on the tree: the deferral mode applies only to a merge commit finished BY HAND with MERGE_HEAD present; step 1 here (git merge --no-edit) auto-commits with no hook run at all, so step 3's commit is ordinary and check-regen-pending.mjs decide() routes it to refuse-stale. The rewritten section keeps the #8047 heading/history and quotes the measured hook output on both sides (the refusal and the repair commit's confirmation). No behaviour change: .githooks/pre-commit and check-regen-pending.mjs untouched (out of surface per triage), step 3's refusal fallback and self-test case 4 already described the measured behaviour, and no self-test case label repeated the deferral claim in prose so none needed editing.", "tests": "bash scripts/pm/os-regen-merge.sh --self-test = EXIT=0, all 23 cases ok, both before and after merging origin/main (re-run on merged head to confirm). node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commands scripts/pm/os-regen-merge.sh derived 12 families (8 pnpm, 4 direct node); all 12 run clean at final head 3cfc80196 (merged with origin/main, no conflicts on this file): check-ci-filter-parity.mjs=0 (own verdict 'OK: all 129 declared cross-package glob(s)...'), check-cross-package-test-inputs.mjs=0 ('OK: 24 package(s) read outside themselves...'), check-shard-attestation.mjs=0 ('check-shard-attestation: 2 aggregate gate(s)...'), check-test-completeness.mjs=3 NOT MEASURED (its own text: needs a saved turbo run test log; CI's Test Core/Dogfood jobs supply it, this dev seat does not run turbo test), check:agent-test-spelling=0 (self-test all cases pass + '0 violations'), check:bash32-floor=0, check:cli-command-ids=0, check:cross-package-test-inputs=0, check:entry-guard=0, check:parse-guard=0, check:pnpm-filter-targets=0, check:watch-hint-literal=0. Reconciliation: node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --ran <list-of-12> = EXIT=0, own verdict 'dispatch-gates --ran: 12 derived famil(ies) accounted for -- 12 run, 0 NOT-MEASURED.' scripts/**-only extras per dispatch order: pnpm check:ratchet-remedy-authority=0 (own verdict '183 scripts swept...'), pnpm check:declared-population-live=0 ('157 of 201 famil(ies) declare a path population...'), node scripts/check-self-test-wired.mjs=0 ('every one of the 163 script(s)...'); check:bash32-floor already covers the bash-3.2-floor requirement (own verdict quotes the construct census). shellcheck is not run by this repo's CI on scripts/pm/*.sh (no workflow references it) -- not run, noted in PR body. grep -naP control-char scan of the edited file: no matches. All exit codes captured by redirect-then-capture, never across a pipe; verdicts quoted from each gate's own printed line, never a bare $?. Full gate set and self-test were re-run on the post-merge head (git fetch origin main && git merge origin/main, clean, no conflicts on this file) before push; PR body cites head 3cfc80196.", "mcp_calls": "0", "open_questions": [ { "question": "Two more siblings of the same false 'records a DEFERRAL' claim exist outside this card's surface: (1) scripts/check-regen-pending.mjs:407-410, the refuse-stale message itself, which says 'it commits the merge first (this hook records that as a deferral)' -- already flagged in the dispatch order's Zone 2.4; (2) .githooks/pre-commit:8-13's own header, found during this run, which names step 3 specifically as the exempt/deferred commit ('the sanctioned landing sequence... step 3... commits BEFORE regenerating... That commit records a deferral instead of being refused') -- the same claim this PR just corrected, on the file that documents the hook's own behaviour. Both are explicitly barred from this card's file surface per triage.", "options": [ "A. File one follow-up card covering both sibling sentences (same false-prose-drift family, same fix shape: state precisely when the deferral mode applies)", "B. File two separate cards, one per file" ], "recommendation": "A, because both sentences are the same drift (conflating the deferral mode's actual trigger with step 3's ordinary-commit path) and a single S-sized card can correct both docblocks/messages together without touching hook behaviour." } ], "out_of_scope_findings": [] }Generated by Claude Code
Generated by Claude Code
ACCEPT — #14154 landed. PR #14468 merged to
mainas76820fdc7via the merge queue (draft flipped and auto-merge armed 09:00Z after the CI watcher read GREEN on3cfc80196;added_to_merge_queue09:03:10Z).Close-out probes executed on
origin/main(fresh fetch, throwaway worktree — not the shared checkout;76820fdc7is inorigin/main's first-parent history at9c7d9d4b3):scripts/pm/os-regen-merge.sh:115— the step-3 docblock now describes the ORDINARY commit as "the hook'srefuse-stalepath, not its deferral path", i.e. the measured behaviour instead of the false "records a DEFERRAL" claim. Control: the section heading## Step 3 and the pre-commit hook agree (#8047)reads at:105, so the grep is live.
Docblock-only,
skip-changeset. The sibling false sentence inscripts/check-regen-pending.mjs:412–:416and.githooks/pre-commit:9–:14is filed as #14470 (unassigned, awaiting grading) — deliberately not ridden along, per the option-A ruling.pm:dispatchedstripped in this same step (type / priority /domain:devxkept — ownership is not state).Seat:
session_01WLJQhde67SeTccsmnBVarV(domain:devx, #6023).
Generated by Claude Code
- added a commit that references this issue
on Sep 2, 2026
Filed by the director seat from the 2026-09-01 merge-sync round on PR #13864 (full report: #13657 comment 5491447862, deviation 2). Dedup: #12877 (closed) is the same script but a different step and a different defect (step 2's unconditional checkout of main's side); no open card carries this.
⛔ Recording only. No severity asserted; low. No data was lost.
The measurement
scripts/pm/os-regen-merge.sh's docblock section "Step 3 and the pre-commit hook agree" asserts the hook records a deferral for a merge commit carrying stale generated artifacts. Measured 2026-09-01 oncontent/docs/permissions/system-context.mdx(routedmerge=os-regen): at step 3 the pre-commit hook refused the commit instead, and the script exited 1 mid-sequence — with step 1's merge commit already created.Why it matters, and why it is small
The script's own printed fallback (clear what the hook reported, then
git add -Aand commit) is correct and was followed; the hook then confirmed the artifactcurrentand cleared the marker on the repair commit. So this is documentation/behaviour drift, not data loss — but an operator who trusts the docblock will read the refusal as something having gone wrong mid-merge, on exactly the path where mis-reading costs a dropped side (#14064's territory).What is NOT claimed
Refs: #14064 (the driver's mixed-file class, where this was measured) · #12877 (closed; same script, step 2, different defect).