Repository navigation
docs(os-regen): refuse the =false spelling, record the silent incoming-side drop, and scope os-regen-merge.sh to main - #18648
Conversation
…side drop, and scope the helper to main Three residual readings on the os-regen merge driver, one driver, one PR. 1. `-c merge.os-regen.driver=false` is now refused by literal spelling beside the empty-string one in both authoritative texts. Re-measured: it answers exit 1 on a pair that text-merges cleanly, cell for cell what the empty string does. 2. The silent incoming-side drop is reproduced and recorded: the merge result IS our side, so the merge commit's diffstat, `git diff` and `git status` all read clean over it. The four places it IS visible are named. 3. `os-regen-merge.sh` takes no base and hardcodes origin/main; a branch stacked on another feature branch is stated out of scope in the header, the usage text and the run output, with AGENTS.md's trunk-branch remedy. AGENTS.md is line-neutral at 1099/1099. Claude-Session: https://claude.ai/code/session_01Gqi43smmqjJ5sUrhfoPeKu Co-authored-by: Claude <noreply@anthropic.com>
维护者速读(终稿)skills 席 改了什么 — 两个文件,把 #15815 线程上遗留的三条 os-regen 驱动读数接进权威文本。 为什么改 — 三条读数是同一个驱动的三个面:① 读者按字面 grep, 风险与代价(含回滚) — 治理面,只改文本与提示;不动驱动、不动关卡、不放宽任何判据。③ 选的是「明写不支持并指路」而非加 席位意见 — 荐合。三条都按卡上的验收原样落:字面拒绝、先复现后记录、明写不支持并指路;行数零余量下原地 1099 行不变,没有买行也没有欠行。 你要做的(一个动作) — 认可 ③「不加 Generated by Claude Code |
Fixes #18343
Three residual readings on the
merge=os-regendriver, carried over from the #15815 thread. One driver, one PR — the card forbids splitting them, and the verification below was re-run together ona8f9e52fd7a67db44d5653aadf27dd396e386a16.Two landing files only:
AGENTS.md(§11 driver block) andscripts/pm/os-regen-merge.sh. The driver itself (.gitattributes,scripts/git-merge-regen.mjs) is untouched — reading 3's answer turned out to be "state it", so it demanded no line there.Reading 1 — the
=falsespelling is now refused by literal spellingThe card's finding: both authoritative texts refused only the empty string, so a reader grepping
=falsefound nothing in either. Fixed in both, folded into the existing refusal — no line added inAGENTS.md.AGENTS.md:606–:608, before:after:
scripts/pm/os-regen-merge.sh:143, before:after — both spellings named, with the reason the literal matters:
⛔ Not taken on the family argument. The card forbids resting on "mechanically the same family", so
=falsewas measured on its own, this tree, git 2.43.0, two pairs over a 200-line routed blob (packages/spec/spec-changes.json):-c …driver=-c …driver=falseCell for cell what the empty string does — a false POSITIVE on row 2, where the driver-free bare shared clone (GitHub's actual condition) correctly says exit 0. One difference worth recording, and it is in the worse direction: the empty string at least prints
error: cannot run : No such file or directory;=falseprints nothing at all. The measured column is recorded in the script header beside the 2026-08 table.Verification re-run (the card's own instrument, with its firing control):
Reading 2 — the silent incoming-side drop, REPRODUCED first
The card's acceptance is explicit: ⛔ reproduce before designing anything. Done first, in a scratch repo with this clone's real driver registered, on the routed path
packages/spec/spec-changes.json, both sides editing it, plus one ordinary hand-written file edited on the incoming side as a firing control.Direction A — the loss is real, and invisible:
Direction B — instruments that DO shout, on the same merge:
The mechanism, which is what makes it a rule and not an anecdote: the merged result IS our side, so it differs from the first parent in nothing — which is exactly why a merge commit's combined diffstat omits it and
git diffreads clean. "The tree is clean" is the symptom, not the all-clear.⟳notice on stderr naming the regeneration command. What is silent is everything after: the commit, its diffstat, and every ordinary post-merge read. A transient console line is not a check.AGENTS.md:584–:593, the change (in place, no line added):The script gets the full measurement as a new header section (
## What "SILENTLY" above means, measured — and why no post-merge check sees it), which also names the four places the drop IS visible, each of which has to be looked at on purpose. And the one per-path notice the script already prints where a drop happened gained the second half:Reading 3 — stacked branches: STATED, not fixed. Here is why
What I did: stated the limitation in the script's header, in its
--help, and in the run output before step 1 touches anything. Why not a--baseflag: becauseAGENTS.mdalready rules the form out, and building tooling for it would contradict a standing decision:The cost reading the card left unmeasured, now measured: 19 occurrences of
origin/main, of which 11 are executable sites (fetch, merge-base, the refusal message,git diffformain_edited, step 1'sgit merge, step 2'sgit restore --source=, step 3's commit message, step 4's printed grep target and three echoes) plus 2 self-test assertions that pin the literal stringgit restore --source=origin/mainat the source. So it is not the "two or three sites" half of the card's guess — but the cost is not the reason to decline; §2 is.The sharper half of reading 3, which the card's usage-text evidence does not show: on a stacked branch this helper does not refuse.
git merge-base HEAD origin/mainstill answers — with the trunk's fork point — so it runs, mergesorigin/maininstead of the parent branch, and step 2 takes main's side of generated artifacts the parent branch owns. A silently wrong answer, not an error, in the one situation the script exists to make safe. That is now the first thing its header says.--helpafter (new paragraph; the card's ⛔ "not something you discover by invoking it"):And at run time, printed before the fetch, so it is not discovered afterwards either:
AGENTS.mdcarries its half in the one place it names the helper —is the in-repo authority for landing one **ontomain**— rather than restating §2, which this file already carries once.AGENTS.mdpayment declaration — in place, line-neutral1099 → 1099. No line added, so nothing was bought and nothing is owed. ⛔ No re-wrap paid for anything: the block's local wrap (~90 chars, well under the 120-byte per-line budget) is unchanged, and the corollary bullet's first six lines are byte-identical to
main— only :606–:608 moved, three lines replaced by three.Both additions fit because their paragraphs' last lines were short. Where that was not quite enough, four word-level compressions inside the MERGE bullet paid the difference. Every one preserves its fact; listed so it can be checked without reading the diff:
for landing one of these branchesfor landing one onto \main``records that merge as a deferral and then holds you to itrecords it as a deferral and holds you to itthe immediately following commit must discharge itthe next commit must discharge itdefer on top of an outstanding one…rather than this onedefer onto an outstanding one…not this oneRatchet output on this head (
pnpm check:pm-skill-ratchet, exit 0):scripts/pm/os-regen-merge.shis not line-ratcheted: 1453 → 1521 lines, the header's existing style kept.Verification
bash scripts/pm/os-regen-merge.sh --self-teston this head: exit 0, 79 cases pass. ⛔ No existing criterion was relaxed and no self-test case was deleted — the two source-scan pins that police step 2's spelling still read exactly 1 and 0 against the head:bash -nexit 0. Control-character self-scan over both files: no hits (grep -naPexit 1).Repo-wide
pnpm lintnarrowed to the touched paths, with the narrowing proven rather than asserted: ① the covered population read fromeslint.config.mjsitself is**/*.{ts,tsx,mts,cts,js,jsx,mjs,cjs}— no config block matches.mdor.sh; ②--format jsonover both paths reports 2 files, 0 errors, exit 0; ③ the diff therefore contains zero files of any extension eslint configures, so it cannot move an untouched file's verdict in either direction.Derived gate list with exit codes
node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstackfrom this worktree (⛔ no hand-fed path list — the tool took its own change set vs merge base32be735e5): 29 families, 29 run, all exit 0.Reconciled:
--ranwith exit codes recorded ⇒29 derived famil(ies) accounted for — 29 run, 0 NOT-MEASURED (a DERIVED zero — all 29 recorded an exit code and none of them is 3).node scripts/pm/check-governed-merges.mjs --test AGENTS.md scripts/pm/os-regen-merge.sh⇒ exit 3, GOVERNED (AGENTS.md ×1 — the repo-root agent instruction file). Draft, four-piece; ⛔ no seat flips it ready, queues it or arms auto-merge — the maintainer's approval lands it.skip-changeset: nothing here sits under any package'sfiles[]—AGENTS.mdis a repo-root instruction file andscripts/pm/**is not published.Acceptance notes
Noted, not filed: the script's
--self-testhas no battery roster or verdict handshake, whichAGENTS.md's "Writing a--self-test" section now prescribes for new ones. It is a pre-existing shape, not something this PR introduces, and rewiring it would be a second change riding a rules PR. Who takes it: the next PR that adds a case to this self-test.维护者速读(草稿)
改了什么 —— 一张卡,三条关于 os-regen 合并驱动的残留读数,落在两个文件上。① 把
driver=false这个拼法按字面写进两处权威文本的拒绝句里(此前只拒空串,拿=false去搜的人两处都搜不到)。② 把"真合并会静默丢掉 incoming 一侧、而且合并后的常规检查一个字都不会说"这件事,先独立复现再记录下来。③os-regen-merge.sh不接 base:明写"栈式分支不支持"并指出该怎么办,没有去加--base。为什么改 —— 这三条的共同要害是读者按字面去搜、按常规去看,什么都看不到。①是搜不到:本仓刚栽过一次同样的跟头(报告写
section-7、树上是§7,复核者读出一个假零)。②是看不到:合并结果就是我们这一侧,所以合并提交的 diffstat 里它压根不出现,git diff读过去干干净净 —— 危险的不是丢内容,是丢了还伪装成干净合并。③是调用了才发现:而最需要它的场合(栈式分支)恰恰是它会悄悄给出错误答案的场合,不是报错。风险与代价(含回滚) —— 风险低。两个文件都是给人看的文本,没有运行时行为改变;脚本侧新增的是注释、
--help文案、一行运行时提示,加一条已有通知的下半句。AGENTS.md1099 → 1099,行数零净增,没有动天花板、没有靠折行筹行;为塞下新内容做的四处措辞压缩逐条列在上面的表里,每一条都不丢事实。脚本自检 79 例全过,两条钉住 step 2 写法的源码断言读数不变(1 和 0)。回滚就是 revert 这一个 commit,不牵动任何其它面。③ 为什么只写不修 ——
AGENTS.md多 agent 纪律 §2 已经裁定栈式分支不是受支持的形态,并逐字写明「⛔ No gate or merge-policy change is made for it」。给这个助手加--base就是在为那条裁决拒绝的形态造工具。代价也量了(11 处可执行站点 + 2 条钉字面的自检断言),但代价不是理由,§2 才是。若您认为该推翻 §2 这一条,那是另一张卡、另一个决定。席位意见 ——
你要做的 —— 读一遍上面「
AGENTS.mdpayment declaration」里的四行压缩对照表(那是本 PR 唯一改写了既有规则措辞的地方),认可即批准合并;这是受管面,需要您亲自点这一下。BASE HEAD,PATH) — GitHub's body sanitizer eats short angle-bracket fragments, fenced ones included. The tree's own text uses the angle-bracket spelling.🤖 Generated with Claude Code
https://claude.ai/code/session_01Gqi43smmqjJ5sUrhfoPeKu
Generated by Claude Code