Skip to content

fix(spawn): 刷新 no-mistakes gate,使 worktree push 能创建流水线 run#136

Open
JJ22007 wants to merge 1 commit into
kunchenguid:mainfrom
JJ22007:fm/nm-gate-fix
Open

fix(spawn): 刷新 no-mistakes gate,使 worktree push 能创建流水线 run#136
JJ22007 wants to merge 1 commit into
kunchenguid:mainfrom
JJ22007:fm/nm-gate-fix

Conversation

@JJ22007

@JJ22007 JJ22007 commented Jun 29, 2026

Copy link
Copy Markdown

问题

no-mistakes 模式的项目里,crewmate 在自己的 treehouse worktree 里跑完整流水线时,git push no-mistakes <branch> 不会创建流水线 run。

post-receive hook 报错 invalid gate path: .,daemon 拒绝该 gate,于是没有 run 被创建;之后 no-mistakes rerun 又报 no previous run for branch。结果就是 crewmate 无法在隔离工作流里通过 gate 校验后再交付,违背了 firstmate 的设计约定。

根因

no-mistakes仓库身份(origin URL) 维护一个共享 gate:主 clone 和它的每一个 linked / treehouse worktree 共用同一个 bare repo 与 post-receive hook。并没有「每个 worktree 一个 gate」这种东西 —— 在 worktree 里跑 no-mistakes init 只会刷新这同一个共享 gate。

旧版本 no-mistakes 安装的 post-receive hook 用的是相对 gate 路径:git 执行 hook 时 GIT_DIR 是相对的(.),所以传给 daemon 的 --gate 就是 .,被判为 invalid gate path: .。新版本改用绝对路径 --gate "$(pwd)",但这个修复只有在重新跑一次 no-mistakes init 刷新已存在的 bare repo hook 后才会生效。而 firstmate 只在「添加项目」时跑一次 init,之后从不刷新,所以用旧版本初始化过的 gate 会一直带着坏 hook。

注:daemon 实际跑流水线用的是 ~/.no-mistakes 下每个 run 独立的临时 worktree,不会动主 clone,因此共享 gate 模型本身是健全的 —— 唯一的缺口就是这个陈旧 hook。

修法

  • 新增 bin/fm-nm-gate.sh:对给定的项目 clone 幂等地刷新 gate(即 section 6 已授权的 no-mistakes init 例外),把陈旧 hook 原地修好。带护栏、尽力而为:非 git 目录 / 无 origin / 未装 no-mistakes / init 失败都只告警并 exit 0,从不阻塞;只做 git remote/config 设置,绝不改动项目文件。
  • bin/fm-spawn.sh:仅对 no-mistakes 模式的 ship 任务,在启动 crewmate 前调用该 helper 刷新主 clone(PROJ_ABS)的共享 gate —— 主 clone 的 bare repo 正是 worktree push 的目标,刷新它即可自愈。direct-PR / local-only / scout / secondmate 都不触发。
  • AGENTS.md:在 spawn 小节记录这个自愈步骤。

端到端验证证据

完全隔离的临时仓库(自带 origin 与 gate,验证后 eject 清理)上复现并验证:

=== STEP A: 陈旧 hook(相对 gate)-> push 必须失败 ===
hook gate line (stalened):  set -- --gate "$GIT_DIR" \
remote: no-mistakes: notify-push failed for refs/heads/feat-x (exit 1):
remote: invalid gate path: .
>> reproduced: invalid gate path
runs after stale push:  no runs yet.

=== STEP B: fm-nm-gate.sh 修好 gate ===
nm-gate: refreshed /private/tmp/nm-e2e.XXXX/clone
hook gate line (healed):    set -- --gate "$(pwd)" \

=== STEP C: 经修复后的 gate push -> 必须创建 run ===
>> no gate error on push
remote:   * Pipeline started
runs after healed push:
  running      feat-x               ea4a327a  2026-06-29 21:56
run rows mentioning feat-x: 1

RESULT: PASS - stale gate failed, healed gate created a run

helper 单元测试 tests/fm-nm-gate.test.sh 覆盖用法错误 / 非 git 目录 / 无 origin / 正常刷新(断言确实调用了 init)/ 未装 no-mistakes / init 失败仍非致命,全部通过。fm-spawn-batchfm-teardown 等相关测试仍绿;改动前后 ~/.no-mistakes 的仓库记录数不变(无污染)。

本地 fm-tangle-guard / fm-secondmate-* 的失败是既有问题(fm-brief.sh 在 bash 3.2 下的 apostrophe-in-heredoc 解析错误,已有独立 PR),与本改动无关,CI(bash 5)下通过。

Add bin/fm-nm-gate.sh and call it from fm-spawn for no-mistakes-mode ship
tasks. An older no-mistakes left a post-receive hook with a relative gate
path, so a crewmate pushing from a treehouse worktree failed with 'invalid
gate path: .' and no pipeline run was created. The idempotent no-mistakes
init refreshes the shared gate hook; running it at spawn self-heals stale
gates without touching project files. Best-effort and non-fatal.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant