在实现 #4711(`build-schemas.ts --check` 不再写 `json-schema.manifest.json`)时撞到的,与该单是同一缺陷类别但**不同入口**,按 Prime Directive #10 单独记录。 ## 现象 `packages/spec/package.json`: ```json "check:docs": "pnpm gen:schema && tsx scripts/build-docs.ts --check", ``` `gen:schema` 是**生成器**,不是检查:它在 `json-schema.manifest.json` / `authorable-surface.json` 陈旧时会把这两个 **tracked** 文件写掉。于是 `check:docs`(以及包含它的 `check:generated`)仍然是一条「跑一次门禁,工作区被改」的路径 —— 正是 #4711 的现象,只是换了个入口。 ## 实测(在 #4711 的修复分支上,即 `--check` 自身已经不写了) ``` manifest staled by hand: 94234b0acb9f79122580537e997dd84b $ git status --porcelain packages/spec/json-schema.manifest.json M packages/spec/json-schema.manifest.json $ pnpm --filter @objectstack/spec check:docs check:docs exit=0 manifest after check:docs: 94ddfeb6032474c1e62661a0fd6dca03 $ git status --porcelain packages/spec/json-schema.manifest.json ← 空:本地改动被这条「检查」吃掉了 ``` ## 为什么修完 #4711 之后这条反而更值得看一眼 `check:generated` 的执行顺序里 `check:authorable-surface` 在前、`check:docs` 在后(`scripts/check-generated.ts` 的 `GATED` 表),而且它**不会因为前面失败就停**。所以在 manifest 陈旧的情况下,跑一次 `check:generated` 的结果是: 1. `check:authorable-surface` 红,报「manifest is out of date,去跑 gen:schema」(#4711 修好的部分); 2. 随后 `check:docs` 里的 `gen:schema` **把它写好了**; 3. 开发者回头一看工作区 —— 干净的,或者多了一个自己没写的 diff。 一份红色报告配一个已经被悄悄修好的文件,比修之前更难解释。 ## 关于 CI 线上不会漏(干净 checkout + 顺序执行),这条主要是本地/agent 并行开发的困惑成本,以及「一个名字叫 check 的脚本会写 tracked 文件」这个语义漏洞本身。 ## 可能的方向(需要维护者定,不要照抄) `build-docs.ts` 需要磁盘上的 `packages/spec/json-schema/`(gitignored 产物),这才是 `check:docs` 前面挂 `gen:schema` 的原因。所以至少三条路: - **A. 给 `build-schemas.ts` 一个「只写 gitignored 产物」的模式**(例如 `--no-snapshots`),`check:docs` 用它。改动最小,但多一个模式位,得想清楚它和 `--check` 的关系。 - **B. 让 `check:docs` 依赖 `build` 的产物**而不是每次现场生成。语义最干净(检查就是检查),代价是它不再自足,顺序依赖要写进 CI 与文档。 - **C. `build-docs.ts` 改成直接从 Zod 源产出内存里的 schema**,不再经过磁盘。最彻底,改动也最大。 倾向 B 或 A;但这会动到 `check:generated` / 合并驱动(`scripts/regen-artifacts.mjs`)对「check 证明 currency」的假设,值得先拍板再动手。 关联:#4711(同类缺陷,manifest ratchet 自身,已修)、#4675 / PR #4702(生成物合并驱动 —— 「a plausible generated file is an invisible error」)、#4203 / #4232(`check:generated` 分类不一致的历史)。
Activity
baozhoutao commentedon Aug 6, 2026
认领:PM 循环第 6 轮(spec-tooling 车道,C 包 #5163 —— 本包最后一单)
会话:
session_01559M8FVm6W6vDLABL3jvdW分支:
claude/issue-4723-check-docs-no-genWorktree:
objectstack-issue-4723域:
domain:spec-tooling文件面:
packages/spec/package.json(check:docs/ 相关 script 构成)、packages/spec/scripts/check-generated.ts(顺序与分类如需)、.github/workflows/**(若调用方需显式先跑 gen)、相应测试、.changeset/*.md或 skip-changeset。⛔ 不碰packages/spec/src/**、不碰 build-schemas.ts 三门语义(#5807/#5851/#5902/#5971 的 45 沙箱测试须全绿)。(越界即停,报告说明)PM 裁决框架(第三档):倾向「把
gen:schema从check:构成里摘出,由调用方(CI / check:generated)显式先跑」—— 即正文路线 B 的精化,两位 dev 的必答项输入:#4759 dev(「check 不写盘」是其探针 A 可信的前提)、#4725 dev(新删行门必须随--check走、共享单一 git 解析)。前提 = check:docs 对磁盘json-schema/的依赖可由「先跑 gen 的显式步骤」满足且 CI 顺序可表达;若实测发现 A(--no-snapshots 模式)代价更小,报告论证后可选 A,⛔ 不选 C(重构 build-docs 内存化,超出本单)。Generated by Claude Code
baozhoutao commentedon Aug 6, 2026
验收:ACCEPT → PR #6000(转 ready + 挂 auto-merge)—— C 包(#5163)收官单
前提在当前 main 上原样复现(staled manifest 被 check:docs 吃掉、md5 与 git status 双读数)。精化 B 落地,三点复核通过:
--check自己(重建 1609 个 schema、拒碰 tracked);A 反而要给 1639 行脚本加第四模式位、定义三对互斥、还保留 check:generated 里的重复生成。耗时表在 PR 正文(修后 check:docs 2.0s vs 修前 9.0s)。readsSchemaTree声明 + 叙述行),不再靠 GATED 表顺序的巧合;build-schemas.ts门禁语义零触碰(36 沙箱测试原样绿),与 json-schema.manifest.json 的「deliberate removal」删行仍是纪律而非门禁 —— #4650 的同类洞,上移一层(整 schema 级) #4725 dev 预告的「删行门随 --check 走」约束吻合。验收标准逐字兑现:staled 投影下单跑 check:docs 与全跑 check:generated,均报告而非修复(md5 不变、
git status的 M 仍在)。反向验证 2 红如预测;CI 25 项零红。范围外发现 #6008(check:merge-driver 的 --self-test 无 workflow 在跑,邻近词反查过零命中)按纪律另立。C 包 17 单至此全部处置完毕 —— 收官账目待本 PR 落地后发 #5163。
Generated by Claude Code