Skip to content

finding: 「已发布 dist 不得含 tooling 产物」今天没有任何门看得见 —— 判据必须是产物级的,而 CI 没有全仓 build #4846

Description

@yinlianghui

发现来源

objectui#4836 / PR #4845 的实施。#4836 正文列了两条修法:修法一(targeted exclude)已由 PR #4845 对量到的四个包全部落地;修法二「排除判据统一机制化」经测量后判为当前不值得同 PR 建门,依据记在这里,单独立卡交分诊。不属于 #4845 的范围。

事实(实测,非推断)

PR #4845 用 TypeScript API 把 46 个 workspace 包的 build tsconfig 解析成真实程序文件表,再对候选包干净重建实测 dist,量到 4 个包把 tooling 物料 emit 进已发布的 dist/(core / plugin-designer / plugin-grid / plugin-view,共 9 个文件)。在那个有缺陷的状态下,仓内全部相关门一律退 0:

node scripts/check-type-check-coverage.mjs    rc=0
node scripts/check-phantom-dependencies.mjs   rc=0
node scripts/check-control-bytes.mjs          rc=0
node scripts/check-package-self-import.mjs    rc=0

也就是说:#4006 与 #4836 是同一形态的第二次和第三次发作(#4006 修 fields / plugin-editor,#4836 修另外四个包),两次都靠人肉发现,而不是靠门。

为什么便宜的静态判据不行(实测,这是关键)

最省事的写法是「build tsconfig 程序不得含 TOOLING_FILE」。实测它会红 5 个零缺陷的包:

包 程序含 tooling 实际 emit 为什么不能按这条门去「修」
@object-ui/plugin-charts 31 无 31 个全是 *.test.*,vite-plugin-dts 的 exclude 已挡住
@object-ui/cli 4 无 tsup 只从 entry 出料;测试在程序里正是它们拿到 tsc --noEmit 覆盖的方式
@object-ui/data-objectstack 38 无 同上
@object-ui/console 51 无 tsconfig noEmit:true,tsc 不写盘
@object-ui/test-support 1 无 private:true,不发布

按这条门去「修」cli / data-objectstack / plugin-charts,等于把 73 个测试挪出类型程序 —— 恰好是 #4006 的镜像失败(#4006 的教训是「覆盖对了是靠 emit 这个副作用对的」;这条门会反过来教人为了熄灭告警而删覆盖)。判据错在层次:tooling 文件在检查程序里是好事,在发射程序里才是缺陷,而「谁是发射程序」逐包不同(裸 tsc / tsup entry 卷 dts / vite-plugin-dts 自带 include+exclude 再与 tsconfig 合并),静态建模等于重写第三方插件的解析语义。

正确判据的成本(也是这张卡的实质内容)

唯一不误红的判据是产物级的:「任一已发布包的 dist/ 不得含 TOOLING_FILE」(或等价地对 npm pack --dry-run 的文件表断言)。它要求先 build,而今天 CI 没有任何 job 做全仓 build:

  • Build & E2E 只跑 pnpm --filter @object-ui/console exec vite build(该 step 的注释写明了为什么只建 console);
  • Type Check 经 turbo type-check 的 dependsOn: ["^build"] 只建出依赖闭包,叶子包不保证被建 —— 上面四个命中包里 plugin-designer 就是叶子。

所以不能把它写成「dist 存在才检查」的形态:那是因为没东西可查所以绿的空判决门,比没有门更坏(它会让下一次发作看起来已经被守住)。真实成本是「新增一个全仓 build 的 CI job」+ 一个 check:* 脚本,不是单写一个脚本。

顺带记一笔(同族的配置漂移,未动)

packages/plugin-grid/tsconfig.json 与 packages/plugin-designer/tsconfig.json 都写着 noEmit:false + declaration:true + composite:true,但两个包的 build 都是纯 vite build,没有任何流程对这两个 config 跑过 emit。今天无害(dts 由插件出),但它意味着一条 tsc -b 就会把整个程序写进 dist/。属于「配置声明了没人执行的 emit」,与本卡同族,一并记下不单独立卡。

为什么标 finding 而不是 pm:queue

今天没有用户面影响:PR #4845 已经把量到的四处全部修掉,dist/ 现在是干净的。这张卡记的是下一次同族发作没有东西拦得住,以及拦住它的真实代价。严重度交分诊裁。

关联:#4836(本卡来源,PR #4845)、#4006(同族,第一次发作)、#4394(phantom-deps 门的 tooling 层判据)、#4802(棘轮范式)。observation-class,未认领。

Activity

  1. os-zhuang commented on Aug 16, 2026

    @os-zhuang
    Contributor

    Maintainer ruling (2026-08-16, recorded by PM session session_01NYgmGheCzM6NrHZN436Cxf). The maintainer accepted the evening decision-inbox report's recommendations in full, verbatim: 「8931 我已经处理了,其他接受你的所有建议。」 For this card:

    Ruled: the artifact-level check lands as a RELEASE-time gate, not a per-PR CI job.

    • The criterion is the one this card measured as the only sound one: no published package's dist/ (equivalently, its npm pack --dry-run file list) may contain a TOOLING_FILE — asserted after a real build.
    • It wires into the release/prepublish flow (and may additionally run nightly), where the harm actually materializes, at zero per-PR cost. ⛔ Not a per-PR full-repo build; ⛔ and not a "check only if dist exists" form — the check must build (or fail loudly when it cannot), never pass vacuously.
    • The static-criterion route is rejected for the reason measured here: it reds 5 zero-defect packages and would teach the @object-ui/fields 与 plugin-editor 的 build 程序把测试文件一起编译,73 个 *.test.d.ts 落进已发布的 dist/ #4006 mirror-failure (moving tests out of type programs to silence it).
    • The noted config drift (plugin-grid / plugin-designer noEmit:false configs nobody executes) rides along as a cleanup item if cheap, else stays recorded.

    First-touch grading completes: label flipped needs-user-decision → pm:queue in the same stroke.


    Generated by Claude Code

  2. self-assigned this
    on Aug 16, 2026
  3. yinlianghui commented on Aug 16, 2026

    @yinlianghui
    CollaboratorAuthor

    【认领】objectui 分片 PM(session_01GTRjn8xBqp75dk7kFupVRt)批次 12 派发,os-dev 实施。分支:claude/issue-4846-published-dist-gate。

    按 2026-08-16 维护者裁定(评论 5307574139)执行:产物级门落 release/prepublish 流(可另加 nightly),判据 = 任一已发布包的 dist/(等价 npm pack --dry-run 文件表)不得含 TOOLING_FILE,真 build 后断言。⛔ per-PR 全仓 build;⛔「dist 存在才检查」的空判决形态 —— 建不出来必须响亮地红。静态判据路线按测量记录否决。plugin-grid / plugin-designer 的 noEmit:false 配置漂移便宜就搭车清理,否则留记录。

    文件面:scripts/(新 check 脚本)+ .github/workflows/(release/nightly 接线;⛔ 碰 per-PR 必跑 job)+(可选)packages/{plugin-grid,plugin-designer}/tsconfig.json + changeset。与在飞四单零交集(#4814 动 plugin-grid 的 src,非 tsconfig)。


    Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions