Skip to content

fix(pilot): run 的无人值守合并步骤补 --allow-trunk - #51

Merged
jhfnetboy merged 2 commits into
mainfrom
fix/run-allow-trunk
Aug 6, 2026
Merged

fix(pilot): run 的无人值守合并步骤补 --allow-trunk#51
jhfnetboy merged 2 commits into
mainfrom
fix/run-allow-trunk

Conversation

@jhfnetboy

Copy link
Copy Markdown
Member

问题:pilot 在自己的仓库上跑不完

run.md 全文没有 --allow-trunk,而 git-guard.sh 对 trunk 型 integration 缺这个 flag 直接 die
也就是说单主干仓库上 pilot run 走到合并那一步必然 exit 3 停住 —— 而 run.md:10 开头明写
「无人值守意味着半夜没人回答」。

Brood 自己就是单主干(.pilot.yml: base_branch: main / integration_branch: main),所以这条在本仓库当前就生效
照旧文档原样跑:

$ git-guard.sh merge-pr 45 --integration main --squash
git-guard: BLOCKED: integration 'main' is a trunk branch — merge PRs into an
  integration branch (e.g. preview), not trunk.                          rc=3

补上之后,它走到真正该停的地方:

$ git-guard.sh merge-pr 45 --integration main --squash --allow-trunk
git-guard: BLOCKED: --allow-trunk: PR #45 reviewDecision is 'CHANGES_REQUESTED',
  not APPROVED — refusing.

两份文档各自都对,合起来是断的

#48 刚合入的 doctor 第 4 步会把这种配置判为「这是合法配置,什么都不缺」,并提示合并时用 --allow-trunk
然后 run 拿着自己那条不带 flag 的命令走过去,断在合并。doctor 知道配置和合并 flag 是连着的,run 不知道。

改动

run.md 两处(§护栏摘要的示例块 + §1 的实际合并命令),各加一句单主干条件。纯文档,零运行时改动。

并把 --allow-trunk 的三个前提写明:分支保护要求审批、这个 PR 已 APPROVED、该分支开启 stale-dismissal
(#47 加的第三条),任一读不到都 fail-closed 拒绝,并指向 SKILL.md §doctor 第 4 步
所以这不是放宽 —— 是让文档跟上守卫的现实。

来源

PR#48 review 标 Medium,当时判「先于本批 PR 存在、不阻塞本 PR」记账。仓库 owner 复核在途账本时
要求单独修掉:它让 pilot 的核心能力(无人值守跑到交付)在 pilot 自己的仓库上跑不完,而账本里其余
open 项都没有这个性质。

preflight.sh run 4/4 通过。

https://claude.ai/code/session_01CmAW1q62bBtjT99inZeyLk

run.md 全文没有 --allow-trunk,而 git-guard 对 trunk 型 integration
缺这个 flag 直接 die。也就是说【单主干仓库上 pilot run 走到合并那步
必然 exit 3 停住】—— 而 run.md 开头明写「半夜没人回答」。

Brood 自己就是单主干(.pilot.yml: base_branch=main, integration_branch=main),
所以这条在本仓库当前就生效。照旧文档原样跑:

  $ git-guard.sh merge-pr 45 --integration main --squash
  git-guard: BLOCKED: integration 'main' is a trunk branch …    rc=3

补上之后走到真正该停的地方:

  $ git-guard.sh merge-pr 45 --integration main --squash --allow-trunk
  git-guard: BLOCKED: --allow-trunk: PR #45 reviewDecision is
    'CHANGES_REQUESTED', not APPROVED — refusing.

#48 刚合入的 doctor 第 4 步会把这种配置判为「合法配置,什么都不缺」,
然后 run 走到合并就断 —— 两份文档各自都对,合起来是断的。

不是放宽:--allow-trunk 仍要求分支保护要求审批 + PR 已 APPROVED +
该分支开启 stale-dismissal(#47 加的),三条任一读不到都 fail-closed。
文档里把这三条前提写明,并指向 SKILL.md §doctor 第 4 步。

来源:PR#48 review 标 Medium,当时判「先于本批 PR 存在、不阻塞」记账,
仓库 owner 复核后要求单独修 —— 它让 pilot 的核心能力(无人值守跑到交付)
在 pilot 自己的仓库上跑不完。

Claude-Session: https://claude.ai/code/session_01CmAW1q62bBtjT99inZeyLk
@jhfnetboy
jhfnetboy requested a review from clestons as a code owner August 6, 2026 04:26

@clestons clestons left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ APPROVE — [2-round,post-R2 全 Low → 按闸门规则跳过 Codex]

+8/-1、纯文档、零运行时改动,修掉的是 pilot 旗舰能力(无人值守跑到交付)在 pilot 自己仓库上的一条硬死路。

三条安全声明逐句核对过源码,全部属实

文案写的是「仍要求该分支的保护规则要求审批、这个 PR 已 APPROVED、且该分支开启了 stale-dismissal,三条任一读不到就 fail-closed 拒绝」。对着 git-guard.sh 逐条:

声明 实现 读不到时
保护规则要求审批 :322 [ "$approvals" -ge 1 ] || dieapprovalsrequired_pull_request_reviews.required_approving_review_count 解析 非数字/缺失 → :313/:317 die(还分了「没有保护规则」和「读不到(需 admin)」两种)
stale-dismissal :335 [ "$dismiss" = "1" ] || die,从同一份 $prot 解析(不会和上一条打架) 解析失败 → 空 → 同样 die
PR 已 APPROVED :341 [ "$decision" = "APPROVED" ] || die 空 → die

die() = exit 3。三条都在,三条都 fail-closed。 交叉引用「SKILL.md §doctor 第 4 步」也是真的(#48 已合进 main),措辞一致。

PR 描述里那两条报错我实跑复现过:不加 flag → integration 'main' is a trunk branch(rc=3);加上 → 真的过了 protection + dismiss 两道检查,停在 reviewDecision is 'CHANGES_REQUESTED', not APPROVED它确实解锁了流程,而且停在了该停的地方。

顺带独立复核了几处此前踩过坑的地方,head 上都是对的:--allow-trunk:197 消费、不会流进 gh pr merge;merge-pr 是 allowlist 不是 denylist,--admin/--repo/--delete-branch 都具名拒绝;protection 读的是 $integration,而 :347 又强制 base == integration,所以「拿到的保护证明」确实属于真正的合并目标。

#45 不冲突#45 已作为 19a5ed8 落 main,本 PR 自己这个 hunk 恰好删掉了那句过时的「受 allow_remote_cleanup 与 dirty-worktree 检查约束」,git merge-tree --write-tree 结果 CLEAN(tree a270454),合并后文案是连贯的。删掉那句也不构成信息丢失:allow_remote_cleanuprun.md:87 仍在,dirty 约束在 git-safety.md:28-30


后续项(全 Low,不阻塞)

1. run.md:70,79 —— 触发条件比脚本窄,同一类卡死换个配置就复现

文档判据是 integration_branch == base_branch,而脚本 :247-251is_trunk 是「名字 ∈ main|master|develop|release*|hotfix* == 仓库默认分支」。

所以 base_branch: main + integration_branch: develop 这种合法的双分支流develop 还在 run.md:73 的内置保护名单里)不满足文档判据 → agent 不加 flag → 实跑 merge-pr 51 --integration develop --squash 复现 integration 'develop' is a trunk branch,rc=3。这正是本 PR 要消灭的那类无人值守卡死,只是换了一种配置。

改法:判据改成「integration_branch 是主干名(main/master/develop/release*/hotfix*)或等于仓库默认分支」;或者反过来在 git-guard 里把 is_trunk 也纳入 == base_branch,让文档和脚本只有一个真相源。

2. run.md:81 —— 死路是被搬走了,不是被填上

§1 对新触及的这三道 gate 的 rc=3 没有任何恢复路径,而主循环 :59 明写「唯一允许停下的地方是 §3 和 BLOCKED」。而且开了 stale-dismissal 之后,APPROVED 这道 gate 天然有竞态:pr-monitor.sh 读到 APPROVED → 有人 push → 审批被撤 → git-guard.sh:341 die。无人值守正好在本 PR 解锁的那一步撞上未定义行为。

改法:加一行统一处置——「merge-pr rc=3 → 把该 task 标 BLOCKED、原样贴 stderr、回主循环做下一个」,顺手把下面那条 admin-token 的情形也覆盖了。

3. run.md:82 —— 漏了「读保护规则需要仓库 admin 权限」

无人值守用非 admin token 时,gh api repos/…/branches/main/protection 读不到 → :317 rc=3 cannot read branch protection … unverified protection is the same as none。这句读起来像策略违规,实际是 token 权限问题——这是这条流程仅剩的一种死法。建议同句补一句:「读保护规则需仓库 admin 权限;报 cannot read protection 先查 token scope,不是分支没保护」。

4. 同一组前置在仓库里有 4 份、2 个版本

  • SKILL.md:92(doctor 第 4 步):三条 ✅
  • run.md:82(本 PR):三条 ✅
  • SKILL.md:47(硬约束 2):只两条,漏 stale-dismissal
  • reference/git-safety.md:18-22只两条,同样漏

建议收敛成一处(doctor 第 4 步),其余三处改成引用,杜绝第五份副本。

5.(Info)run.md:84 —— 「git-guard 会校验 PR base == integration_branch」与实现顺序相反:base 校验在 :345,排在三道 allow-trunk gate 之后。无安全影响(合并前仍会校验),但单主干仓库上 base 写错时,先看到的是 protection 报错而不是 base 报错。


2-round:R1a/R1b DeepSeek-v4-flash(R1a 1 条自相矛盾被驳回——它先质疑第三条前置不存在、SKELETON 里又说三条都在;R1b S1 的「夸大安全性/漏 fail-closed」两半被原文驳回,只保留 admin-rights 那半并降为 Low;S2「stale-dismissal 不充分」被脚本 :259-278 自己的注释驳回)→ R2 Opus 独立评审(读真源 + 对 Brood/main 实跑只读校验 + git merge-tree#45 合并)→ post-R2 severity gate 全 Low,按 skill 规则跳过 Codex R3 → R4 Opus 终裁 + 全量复扫(补出触发条件比脚本窄这条实跑复现的 Low、第四份分叉副本、以及 :84 的顺序描述)。

@jhfnetboy
jhfnetboy merged commit 1a91dc4 into main Aug 6, 2026
5 checks passed
@jhfnetboy
jhfnetboy deleted the fix/run-allow-trunk branch August 6, 2026 04:51
@github-actions github-actions Bot locked and limited conversation to collaborators Aug 6, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants