diff --git a/.claude/skills/t27b-loop/SKILL.md b/.claude/skills/t27b-loop/SKILL.md index ef9506f488..7cee3bc747 100644 --- a/.claude/skills/t27b-loop/SKILL.md +++ b/.claude/skills/t27b-loop/SKILL.md @@ -97,4 +97,8 @@ Append one line to the loop ledger memory (`t27b-loop-ledger.md`): the time, wha - **Two sessions can take the same ledger issue.** #10853 (bare `sqrt`) and #10862 (`@truncate`) both closed #10837, and each stayed red alone: one lacked the rows the other had, and the other lacked the slots. Before you open a PR for an issue, run `gh pr list --search ""`. If a sibling PR exists, merge its branch into yours (fetch it as `refs/heads/`), and say "Carries #N" in the body. - **A cap lowered to the exact count leaves no room for rows other PRs still need.** #10853 set `max_not_pass` to 129. eval_hslm and ngram_hslm still needed two blocked rows, so the combined PR set 130. That is still below master's 139, so it does not raise the cap. Recount after every merge: `blocked` + `codegen` = cap. - **The Mac hook refuses any Bash text that contains the words of a test command**, even inside a heredoc for a PR body. Write PR bodies with the Write tool. -- **A merge of master that changes `lefthook.yml` is refused by the own-language pre-commit hook**, because the gate file is owner-only and the merge commit carries master's edit to it. Never `--no-verify`. Instead, `git merge --abort`, make the branch's side of each conflicting file equal master's (for the ledger: master's rows plus only the lane's rows) in a normal commit, then check `git merge-tree --write-tree HEAD FETCH_HEAD`. rc 0 means GitHub can squash it with no conflict (#10862). +- **A merge of master that changes `lefthook.yml` is refused by the own-language pre-commit hook**, because the gate file is owner-only and the merge commit carries master's edit to it. Never `--no-verify`. Instead, `git merge --abort`, make the branch's side of each conflicting file equal master's (for the ledger: master's rows plus only the lane's rows) in a normal commit, then check `git merge-tree --write-tree HEAD origin/master`. rc 0 means GitHub can squash it with no conflict (#10862). +- **`FETCH_HEAD` is whatever the last `git fetch` brought, not master.** In a loop over several branches, each `git fetch origin ` overwrites it, so a later `git merge-base B FETCH_HEAD` compares a lane with itself. It reports no lane rows and a merge-base equal to the branch tip. Fetch master into a named ref once, `git fetch origin master:refs/remotes/origin/master`, and use `origin/master` (or its sha) for every merge-base, row diff and merge-tree check (#10792 stack, 2026-10-19). +- **Every branch in a stack carries its base PRs' rows.** After the base merges, those rows are already on master, so diff the lane's rows against master's rows (`comm -23 lane.add master.rows`), not against the merge-base. Only the rows master still lacks go into the rebuilt ledger. For the six-PR t27f stack that was one row (`glyph57`), plus one more on #10800. +- **Auto-merge squashes the head it saw go green, and a push in flight can miss it.** #10862 merged at 330dd0aef while 186c3ab6d, the commit with its last two ledger rows, was still being pushed. Master then reported both specs UNLISTED. After a PR with `--auto` merges, compare `gh pr view N --json headRefOid` with the lane's last commit. If they differ, carry the missing commit in the next PR at once (#10889 carried those rows). +- **A seal conflict cannot be resolved by the make-it-match recipe while master's diff carries `lefthook.yml`.** Both sides change the same seal lines against an old merge base, so any third value conflicts again. Instead, set the branch's seal to master's in a normal commit (the merge is now clean), let GitHub write the merge with `gh api -X PUT repos/gHashTag/t27/pulls/N/update-branch -f expected_head_sha=`, then re-save the seal on the lab from the merged head and push it (#10806).