Skip to content

check:docs 的第一步是 gen:schema —— 修好 #4711 之后,「检查改工作区」仍从这里漏进来 #4723

Closed

Description

@os-zhuang

在实现 #4711(build-schemas.ts --check 不再写 json-schema.manifest.json)时撞到的,与该单是同一缺陷类别但不同入口,按 Prime Directive #10 单独记录。

现象

packages/spec/package.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」(check:authorable-surface 在 --check 模式下仍会写 json-schema.manifest.json —— 一个「检查」在改工作区 #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

  1. self-assigned this
    on Aug 6, 2026
  2. baozhoutao commented on Aug 6, 2026

    @baozhoutao
    Contributor

    认领:PM 循环第 6 轮(spec-tooling 车道,C 包 #5163 —— 本包最后一单)
    会话:session_01559M8FVm6W6vDLABL3jvdW
    分支:claude/issue-4723-check-docs-no-gen
    Worktree: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

  3. baozhoutao commented on Aug 6, 2026

    @baozhoutao
    Contributor

    验收:ACCEPT → PR #6000(转 ready + 挂 auto-merge)—— C 包(#5163)收官单

    前提在当前 main 上原样复现(staled manifest 被 check:docs 吃掉、md5 与 git status 双读数)。精化 B 落地,三点复核通过:

    1. 路线 A 被测量击毙而非偏好排除:「只写 gitignored 产物的模式」已经存在 —— 就是 --check 自己(重建 1609 个 schema、拒碰 tracked);A 反而要给 1639 行脚本加第四模式位、定义三对互斥、还保留 check:generated 里的重复生成。耗时表在 PR 正文(修后 check:docs 2.0s vs 修前 9.0s)。
    2. 被摘掉的 gen 步骤曾静默保证的新鲜度转成显式断言(json-schema/ 缺失或旧于 src 即红并给处方)—— 没有这一层,修复只是把「改工作区」换成更糟的「陈旧树假绿」;四方向护栏 + 有意的 .test.ts 排除都有实测。
    3. 生产者先于消费者由 reconciliation 强制(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

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

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions