Skip to content

[CI][BUG] worktree 无 node_modules ⇒ 真 typecheck 只能去共享主 checkout 跑 —— 并行 lane 时互相污染彼此的门测量 #916

Closed

Description

@jinjunnn

这是什么

新建的 .worktrees/* 没有 node_modules,于是 typecheck 在 worktree 里恒假红。
CLAUDE.md 的应对是「判据只有两个:与 base fail-set 相同,或去主 checkout 跑真的」。

但同一份 CLAUDE.md 另一条写着「主 checkout 是共享场地」。 单条 lane 时两条都成立;
并行多条 lane 时它们互相矛盾 —— 每条 lane 为了拿真 typecheck 都要去动那一棵共享树。

今晚的实证(不是推演)

四条 lane 并行(#890/#893/#897/#913):

  • #897 与 #913 各自独立报告 worktree 里完全没有 node_modules,typecheck 假红;
    两者都只能去主 checkout 跑真的才敢下结论。
  • #897 在自己的门跑到一半时,在主 checkout 里看见了 #893 的改动
    (gate-file-registry.test.ts 出现 #893 的四层检查),它开始时主树是干净的。
    它没有动那份改动,而是加时间戳括号重跑(前 08:42:05Z status=[0]、
    后 08:45:58Z status=[0],HEAD 两次相同)来证明自己量的是自己的树。

没有造成错误结论 —— 但它靠的是实现方自己想到要做取证。 这正是 2026-08-02 那次
「把一道真闸门误诊成 1/5 间歇性 flaky」的同一形态:红了先问「这一刻树上是什么」。
那次查清用了一个专门的取证轮。

为什么值得修而不是靠纪律

「并行时别动主 checkout」这条纪律没法遵守 —— 因为 worktree 里拿不到真 typecheck,
去主 checkout 是当前工具链下的唯一出路。让人靠自觉去躲一个工具缺口,
下一次就是「谁先跑谁量到别人的树」。

方向(不是裁决)

给 worktree 一个 bootstrap:建完 worktree 后把各包的 node_modules 软链补齐
(CLAUDE.md 已经写了「新 worktree 还要补齐各包的 node_modules 软链」,
但今天没有任何东西自动做这件事,两条 lane 今晚都撞上了)。
冻结包另需 .ts-dist 缓存,一并处理。

做到之后,lane 就不需要碰共享树,上面那条矛盾自然消失。

判据

不能只断「脚本存在」或「软链存在」——那是断言产物不是行为。
判据落在能力上:在一棵全新建的 worktree 里跑 typecheck,
断言它不产生那一类 Cannot find module 'bun:test' / @types/bun 的假红
(即:worktree 自己就能给出可信结论)。
写完自己实施一遍绕过:把 bootstrap 摘掉,该判据必须转红。

关联

  • CLAUDE.md《本机验证陷阱》:「worktree 的 node_modules 是软链,typecheck 与 DOM 测试恒假红」
    与「主 checkout 是共享场地」——本票消除这两条之间的冲突。
  • 2026-08-02 变异实验窗口误诊事故(同形:量到的不是自己的树)。

复杂度:S

Activity

  1. self-assigned this
    on Aug 11, 2026
  2. jinjunnn commented on Aug 11, 2026

    @jinjunnn
    OwnerAuthor

    勘破(主 session 实跑,推翻了本票原本设想的修法)

    1. 全新 worktree 里 node_modules 一个都没有

    .worktrees/probe-916/node_modules                 MISSING
    .worktrees/probe-916/packages/ui-mac/node_modules MISSING
    .worktrees/probe-916/packages/ext/node_modules    MISSING
    

    bun run typecheck ⇒ exit 2,11627 条 error TS,头一条就是
    Cannot find module 'bun:test'。这就是今晚两条 lane 各自撞到的那个东西。

    2. CLAUDE.md 现在写的修法(「补齐各包 node_modules 软链」)是错的 —— 两点都错

    不够:我把主 checkout 里 29 个 node_modules 逐个软链过去,错误从 11627 只降到 8694,
    typecheck 仍然 exit 2。原因是 bun 的隔离式安装布局:真包在根 node_modules/.bun/ 里
    (实测 ghostty-web 在 node_modules/.bun/ghostty-web@github+.../node_modules/ghostty-web,
    @sentry/solid 在 node_modules/.bun/node_modules/@sentry/solid),各包 node_modules 里放的是
    指进那个 store 的链。逐包软链重建不出这张图。

    且有害:packages/ui-mac/tsconfig.json 的 outDir 是 node_modules/.ts-dist ——
    把 node_modules 软链到主 checkout,等于每条 lane 的 typecheck 都往共享树里写构建产物。
    那正好是本票要消灭的那种交叉污染,换了个地方发生。
    (packages/{app,desktop,ui-mac} 三处 .ts-dist 都在 node_modules 里面。)

    3. 正确修法就一句 bun install,而且很便宜

    全新 worktree 里:

    步骤 实测
    bun install exit 0,4694 packages,11 秒
    随后 bun run typecheck(ui-mac) exit 0,0 条 error,2 秒
    node_modules 真目录,不是指向主 checkout 的链
    packages/ui-mac/node_modules/.ts-dist worktree 本地真目录 ⇒ 不与任何人共享

    对照:同一时刻主 checkout 的 ui-mac typecheck 也是 exit 0 / 0 条 ——
    所以这从头到尾是环境问题,不是代码问题。

    这对修法的影响

    • 别做软链方案。做 worktree 创建后跑 bun install(11 秒,买断整类假红)。
    • 判据仍按票面:落在能力上 —— 新建 worktree 跑 typecheck 不产生 bun:test / @types/bun
      那一类假红,而不是断言「脚本存在」或「软链存在」。
    • CLAUDE.md 的那句话要一起改,但它在 alpha-work 仓,不在本仓 ⇒ 本票只改 alpha-code 侧的工具;
      文档更正我另行处理,免得跨仓混在一个 PR 里。
  3. added a commit that references this issue on Aug 13, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

type:choreMaintenance or operational work

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions