观察类发现,在 #3657 / PR #3681 (删除未接线的 prettier devDependency)的逆向验证环节撞到。今天没有任何用户或 CI 会碰到它 ;严格说它落在 #3657 被裁决收窄后的文件面(根 package.json + pnpm-lock.yaml)之外,故未顺手改,单独记在这里。
事实
PR #3681 删掉了根 package.json 的 prettier@^3.9.6。删除本身是干净的:node_modules/.bin/prettier 不再存在,lockfile 里 grep 'prettier@3' 零命中。
但假红陷阱没有随之消失 。在本仓 worktree 里,删除之后:
$ pnpm exec prettier --version
3.8.1 # 不是被删的 3.9.6,也不是 changesets 的传递依赖 2.8.8
$ pnpm exec prettier --check scripts/check-doc-links.mjs
Checking formatting...
[warn] scripts/check-doc-links.mjs
[warn] Code style issues found in the above file. Run Prettier with --write to fix.
exit=1 # 未改动内容,依然假红
来源是 pnpm exec 在仓内找不到时沿 PATH 兜底,而容器镜像里预装了一份全局 prettier:
$ command -v prettier
/opt/node22/bin/prettier -> /opt/node22/lib/node_modules/prettier/bin/prettier.cjs
它和 eslint、typescript、ts-node 等一起躺在 /opt/node22/lib/node_modules/,是镜像构建时装的(Mar 31),与本仓无关。
后果
#3657 描述的那个「看起来像自己闯的祸」的假红 —— agent 改完两行,跑 prettier --check 收尾,看到自己碰过的文件报 warn,顺手 --write 重排几千行 —— 在任何装有全局 prettier 的环境 里依然成立。删依赖解决的是「仓库声明了一条没人用的依赖」,没有、也无法解决「pnpm exec prettier 仍然可用且默认值与本仓风格不符」。
反过来说,这也意味着这个陷阱本来就不是 由那条 devDependency 独家造成的:即使在它被删之前,一台装了全局 prettier 的机器上也会有同样表现。
影响
零用户可见影响,零 CI 影响(没有 workflow 跑 prettier,见 #3657 的四类接线复测)。成本纯粹是 agent 工效:后来的 agent 仍可能被这个假信号带偏,而且现在更隐蔽 —— 仓里已经搜不到 prettier 了,撞上的人更难顺藤摸瓜找到解释。
处置方向(分诊定,我不预设)
倾向 #3657 里没被采纳的三号方案,现在它不再是「止血」而是唯一能真正闭合的那一半 :
文档护栏 :在 AGENTS.md 的「测试纪律 / 门禁」一带写明「本仓不以 prettier 做格式门禁,格式交给 eslint,别跑 prettier --check / --write」。成本极低,直接命中根因(人/agent 的误用),且不依赖环境里有没有全局 prettier。
机械护栏 :加一份只用于「拒绝」的 .prettierignore(全量忽略)或一条把 prettier 挡回去的检查。能拦住命令,但会让人误以为本仓在用 prettier,语义上更糊涂。
不处理 :接受它,理由是 prettier 是未接线的 devDependency:无配置、无 lint 集成、无工作流,prettier --check 对全仓假红 #3657 的主要成本(那条死依赖)已经消除,剩下的只是通用工具的通用行为。
我倾向 1;2 的语义副作用大于收益,3 的话建议至少在 #3657 关闭时把这条残留写进结论,别让下一个人重新发现一遍。
Generated by Claude Code
观察类发现,在 #3657 / PR #3681(删除未接线的 prettier devDependency)的逆向验证环节撞到。今天没有任何用户或 CI 会碰到它;严格说它落在 #3657 被裁决收窄后的文件面(根
package.json+pnpm-lock.yaml)之外,故未顺手改,单独记在这里。事实
PR #3681 删掉了根
package.json的prettier@^3.9.6。删除本身是干净的:node_modules/.bin/prettier不再存在,lockfile 里grep 'prettier@3'零命中。但假红陷阱没有随之消失。在本仓 worktree 里,删除之后:
来源是
pnpm exec在仓内找不到时沿 PATH 兜底,而容器镜像里预装了一份全局 prettier:它和
eslint、typescript、ts-node等一起躺在/opt/node22/lib/node_modules/,是镜像构建时装的(Mar 31),与本仓无关。后果
#3657 描述的那个「看起来像自己闯的祸」的假红 —— agent 改完两行,跑
prettier --check收尾,看到自己碰过的文件报 warn,顺手--write重排几千行 —— 在任何装有全局 prettier 的环境里依然成立。删依赖解决的是「仓库声明了一条没人用的依赖」,没有、也无法解决「pnpm exec prettier仍然可用且默认值与本仓风格不符」。反过来说,这也意味着这个陷阱本来就不是由那条 devDependency 独家造成的:即使在它被删之前,一台装了全局 prettier 的机器上也会有同样表现。
影响
零用户可见影响,零 CI 影响(没有 workflow 跑 prettier,见 #3657 的四类接线复测)。成本纯粹是 agent 工效:后来的 agent 仍可能被这个假信号带偏,而且现在更隐蔽 —— 仓里已经搜不到 prettier 了,撞上的人更难顺藤摸瓜找到解释。
处置方向(分诊定,我不预设)
倾向 #3657 里没被采纳的三号方案,现在它不再是「止血」而是唯一能真正闭合的那一半:
AGENTS.md的「测试纪律 / 门禁」一带写明「本仓不以 prettier 做格式门禁,格式交给 eslint,别跑prettier --check/--write」。成本极低,直接命中根因(人/agent 的误用),且不依赖环境里有没有全局 prettier。.prettierignore(全量忽略)或一条把 prettier 挡回去的检查。能拦住命令,但会让人误以为本仓在用 prettier,语义上更糊涂。prettier --check对全仓假红 #3657 的主要成本(那条死依赖)已经消除,剩下的只是通用工具的通用行为。我倾向 1;2 的语义副作用大于收益,3 的话建议至少在 #3657 关闭时把这条残留写进结论,别让下一个人重新发现一遍。
Generated by Claude Code