Skip to content

Commit cd8df64

Browse files
os-zhuangclaude
andauthored
docs(agents): criterion ③'s test is scoped to the branch's own commits — the unranged git log walked all of main and made force-with-lease dead letter (#18351)
Fixes #18178 ## The defect `AGENTS.md` Multi-agent §3 allows `--force-with-lease` only while all five criteria hold. Criterion ③ stated the bar — *nobody else has ever pushed it* — and then operationalised it as the author and committer sets of an **unranged** `git log` over the branch's remote ref. With no range that walks the branch's entire ancestry, all of `main` included, so the sets are main's whole history plus the agent and the test cannot pass for **any** branch cut from `main`. The stated criterion is satisfiable and right; only its operationalisation was impossible — a reader who follows the words never force-pushes, one who follows the intent does, and that divergence is the bug. The card was filed after the dev on #17330 declined to take a reading it could not prove and shipped four `wip:` commits plus a merge instead. ## The change One hunk, two lines, `AGENTS.md` :473–:474. The parenthetical is re-keyed to the branch's **own** commits — the range form `origin/main..` in front of the branch ref. Criteria ①②④⑤ are untouched, ③'s bar is untouched (same words, same strictness), and the file stays at its 1075-line ceiling with no new line. ```diff - `claude/issue-*`; ② this worktree created it; ③ nobody else has ever pushed it (the - author and committer sets of `git log origin/BRANCH` are you alone); ④ no open PR + `claude/issue-*`; ② this worktree created it; ③ nobody else has ever pushed it (the author and + committer sets of its own commits, `git log origin/main..origin/BRANCH`, are you alone); ④ no open PR ``` ⚠️ `BRANCH` above stands for the angle-bracket placeholder the file actually spells; this body writes the word instead, because a GitHub body sanitizer eats short angle-bracket fragments. The file itself is unchanged in that respect — read the diff for the real bytes. ## Ratchet and byte budget | reading | before | after | |:--|--:|--:| | `wc -l AGENTS.md` (ceiling 1075) | 1075 | 1075 | | line :473 | 90 B | 101 B | | line :474 | 88 B | 108 B | | lines :472 / :475 / :476 / :477 | untouched | untouched | | `git diff --stat` | — | 1 file, 2 insertions, 2 deletions | `scanLineLengths` (the gate's own scanner, budget 120 B) reports **0 offenders** on the edited file. ## Reverse verification Taken on this very branch, a real `claude/issue-*` branch, and on a constructed control. ⚠️ This checkout is **shallow**, so the unranged sets are truncated relative to the card's full-history reading (33 / 32 / 1); the *shape* is what reproduces, and it reproduces exactly. ``` BEFORE — today's literal test, on this branch git log --format='%an|%cn' origin/claude/issue-18178-force-with-lease-criterion-scope | sort -u -> 7 pairs (Claude|Claude, Jack Zhuang|GitHub, Leehom|GitHub, Warren Buffett|GitHub, claude[bot]|GitHub, os-elon-musk|GitHub, os-try-charles|GitHub) CONTROL — the same literal test on origin/main itself -> 6 pairs — the branch's 7 minus Claude|Claude, i.e. main's set plus the agent, exactly as the card measured. `comm -23` of the two sets prints one line: Claude|Claude. AFTER — the re-keyed test, same branch git log --format='%an|%cn' origin/main..origin/claude/issue-18178-... | sort -u -> 1 pair Claude|Claude (2 commits in range) FIRING CONTROL — the re-keyed test on a branch that genuinely has a second pusher (a throwaway local repo, two clones, two identities; no probe branch was pushed to origin) unshared branch, literal test -> 4 pairs (wrongly refuses) unshared branch, re-keyed test -> 1 pair (permits — correct) SHARED branch, re-keyed test -> 2 pairs Claude|Claude + os-try-charles|os-try-charles (still refuses — the bar is not loosened) ``` ## The one design choice: which scoped spelling The card proposed `$(git merge-base origin/main origin/BRANCH)..origin/BRANCH` and called it a proposal, not a prescription. This PR ships the plain two-dot range `origin/main..origin/BRANCH`. Both compute the same commit set — verified on the live branch and on both control branches, 1 / 1 / 2 pairs either way — and the two-dot form is one moving part fewer. The deciding measurement is how each **fails**: ``` # the substitution form, when merge-base returns nothing (shallow clone, unrelated # histories, a ref not fetched) — the range silently becomes HEAD..origin/BRANCH exit=0 pairs=0 on a branch a second agent had just pushed -> "you alone" is VACUOUSLY true, and the criterion permits exactly the clobber it forbids # the two-dot form under the same fault exit=128 fatal: ambiguous argument ... unknown revision -> loud, no verdict at all ``` That failure is live in this repository, not hypothetical: `git merge-base origin/main REF` exits 1 with empty output here for a branch whose base lies outside the shallow window. Preferring the spelling that cannot degrade into a different question is the same principle the card is about — a test that answers confidently and wrongly is worse than one that stops. ## 维护者速读(草稿) **改了什么** — `AGENTS.md` 多 agent 纪律 §3 里判断「分支是不是只有我一个人推过」的那条命令, 从 `git log` 加分支名(走遍整条祖先,包含整个 `main`),改成只看分支自己的提交(`origin/main..` 区间)。 正文两行,判据本身一字未动。 **为什么改** — 原命令对任何从 `main` 切出来的分支都必然返回「多人」,所以第五条允许的 `--force-with-lease` 实际上永远用不了:条文写着允许,测出来永远禁止。按字面读的 agent 从不 force-push, 按意图读的会,两种读法分叉本身就是缺陷。已经有一张卡的开发因此多推了四个 `wip:` 提交和一个 merge。 **风险与代价(含回滚)** — 改的是规则文本,不是代码,没有运行时影响。风险是「改松了判据」, 本 PR 用一个构造出来的、确有第二个推送者的分支做了发火对照:新命令仍然读出两组身份、仍然拒绝。 回滚成本 = 还原两行文字。 **席位意见** — (留空,待席位定稿) **你要做的** — 这是受管面(`AGENTS.md`),需要您的一次授权批准;批准前没有任何 agent 席位会合并、 入队或挂 auto-merge,PR 保持 draft。 ## Acceptance notes - noted, not filed: the ratchet's line-length verdict prints **only on failure** (`check-skill-line-ratchet.mjs` `run()` logs `lv.msg` under `if (!lv.ok)`), so a green run says nothing about the 120-byte axis for any file. Not a defect class — a silent green is the normal shape for that gate — measured positively here by calling `scanLineLengths` directly instead of reading the gate's silence. Bearer: none; noted for the next author who cites that gate's green as width evidence. - Scope held: `AGENTS.md` only, criterion ③'s parenthetical only; :472 and :475–:477 were not re-flowed and not touched. ## Landing Governed surface (`AGENTS.md`, Prime Directive #14) — `check-governed-merges.mjs --test` answers **GOVERNED**, 1 of 1 path. The PR stays **draft**; no reviewer was requested, no auto-merge armed, nothing flipped. It waits for the maintainer's authorized approval, which the owning seat requests. --- _Generated by [Claude Code](https://claude.ai/code/session_01HZfg2AwVX191qCizp88gQr)_ Co-authored-by: Claude <noreply@anthropic.com>
1 parent bce5270 commit cd8df64

1 file changed

Lines changed: 2 additions & 2 deletions

File tree

AGENTS.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -470,8 +470,8 @@ Even inside your own worktree, operate defensively:
470470
3. **Never force-push a *shared* branch, and never push `main`.** A force-push can
471471
clobber a parallel agent's work; `main` is shared — land all via PR. A branch is
472472
unshared, and `--force-with-lease` allowed, only while ALL FIVE hold: ① it is named
473-
`claude/issue-*`; ② this worktree created it; ③ nobody else has ever pushed it (the
474-
author and committer sets of `git log origin/<branch>` are you alone); ④ no open PR
473+
`claude/issue-*`; ② this worktree created it; ③ nobody else has ever pushed it (the author and
474+
committer sets of its own commits, `git log origin/main..origin/<branch>`, are you alone); ④ no open PR
475475
on it carries a reviewer or an approval (one does ⇒ a new branch and a fresh PR
476476
instead); ⑤ the push spells `--force-with-lease=<branch>:<sha you last pushed>`
477477
⛔ never bare `--force`. One criterion failing ⇒ the branch is shared.

0 commit comments

Comments
 (0)