fix(spec): gen:schema clears only its own outputs, sparing gen:openapi's openapi.json - #6200
Merged
Merged
Conversation
…i's openapi.json `build-schemas.ts` opened by removing `packages/spec/json-schema/` itself, but that directory has two writers: this generator emits `<category>/<Name>.json` plus `objectstack.json`, and `gen:openapi` emits `openapi.json`. `pnpm build` hid the damage (`gen:schema && gen:openapi` rewrites it last), while every entry point that stops after `gen:schema` — `check:authorable-surface`, and therefore `check:generated` — left the artifact deleted, with no gate over it and the tree gitignored. The clean is now scoped by a declared ownership registry (`scripts/lib/json-schema-out-dir.ts`): the sweep stays total, and exempts only top-level entries another generator declares. `build-openapi.ts` imports the artifact name from that registry so the declaration cannot drift from it. Fixes #5371 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014wsZeReNTqiceBfLb5Pyf5
|
The latest updates on your projects. Learn more about Vercel for GitHub. 1 Skipped Deployment
|
Contributor
📓 Docs Drift CheckNo hand-written docs reference the 0 changed package(s). ✅ |
os-zhuang
marked this pull request as ready for review
August 7, 2026 10:57
This was referenced Aug 7, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #5371
问题
packages/spec/json-schema/有两个写入方:gen:schema(build-schemas.ts)写json-schema/{category}/{Name}.json与打包的objectstack.json;gen:openapi(build-openapi.ts)只写一个文件openapi.json。而
build-schemas.ts的清场是把目录本身删掉(fs.rmSync(OUT_DIR, { recursive: true }),origin/main:285),于是顺手抹掉了兄弟生成器的产物。pnpm build看不见这件事,因为它是gen:schema && gen:openapi && tsup,openapi.json总是最后被重写;凡是停在gen:schema之后的入口都会中招 ——check:authorable-surface就是原地跑build-schemas.ts --check,check:generated又跑它。整棵树 gitignored、gen:openapi无门禁(check:generated自己打印Generated but ungated (2): gen:openapi, gen:sbom),所以没有任何东西报告这个洞,红只会在两个包之外冒出来:@objectstack/rest的 openapi 路由测试expected 503 to be 200,对着一份根本没碰过它们的 diff。四次独立复现(#5371 本身,以及 #5126 / #5588 / #5672 实施途中),每次一整圈归因成本。前提复核(重新定价)
按派单要求先在
origin/main(80f7dc6a3)复核 #5837 分片(PR #6069)之后的现状,前提成立:OUT_DIR仍是path.resolve(PKG_DIR, 'json-schema')(:73),分片改的是json-schema.manifest/与authorable-surface/两个已入库产物的目录布局,不是OUT_DIR;fs.rmSync(OUT_DIR, { recursive: true, force: true, … })仍在:285,仍然整目录清场;openapi.json仍然只由build-openapi.ts:179写入同一目录;build-schemas.ts只写 category 目录与objectstack.json,gen:sbom写的是 monorepo 根的sbom.json,不在此列。修法(正文候选①:各生成器只拥有并清理自己的输出)
新增
packages/spec/scripts/lib/json-schema-out-dir.ts,承载所有权登记表与清场函数:FOREIGN_JSON_SCHEMA_ARTIFACTS—— 声明「住在json-schema/下、但属于别的生成器」的产物,值是写回它的命令,这样文件不见时读一行就知道补救办法;clearOwnedOutputs()—— 逐个删除顶层条目、保留登记表声明的那些,目录本身留下;重试与退避形状原样保留(CI 文件系统竞态是它们存在的理由),删不掉的条目报告而不是吞掉;build-openapi.ts从这张表 import 自己的产物名(OPENAPI_ARTIFACT_NAME),而不是再拼一次字符串 —— 改名时声明跟着走,登记表无法与它保护的生成器脱节(declared = enforced,不是一句注释)。为什么排除项是 deny-list 而不是 allow-list(写在 lib 头部):「只删我产出的路径」读起来更像所有权的字面拼法,却恰恰会破坏清场本身的目的 —— category 目录是从
build-schemas.ts自己的Protocol表推导的,某个 namespace 离开该表的当天,它的目录也就离开了 allow-list,json-schema/{gone}/会活过之后每一次 build,并且随发布包一起出货(json-schema在 spec 的files白名单里)。deny-list 保持清扫是全量的 —— 这正是「no stale files remain」一直以来的含义 —— 只放行另一个生成器已声明的产物。验收证据(按 issue 描述的顺序端到端跑)
完整 build 之后单独跑
gen:schema,并预先埋入 stale 探针:openapi.jsonmd5 前后一致:f6f36414a6e969e849624cf955fdc914;埋入的zzStaleProbe.json/zzstalecat/均已被清掉(清场仍是全量的)。pnpm --filter @objectstack/spec check:generated→ 10/10 全绿,且openapi.json仍在(17 个顶层条目)。@objectstack/rest:62 files / 854 tests 全绿;单独跑两个当事文件rest-openapi-route.test.ts+rest-endpoint-surfaces-served-only.test.ts→ 24/24 绿。假红不再复现。反向验证(方向:预测为红,实测为红)
把删掉的肢体装回去(在清场前补一句
fs.rmSync(OUT_DIR, { recursive: true })),新增的两条端到端 pin 立刻转红,且报的正是现场四次报告里的那条ENOENT:脚手架已移除,
git diff无残留。测试
两层,缺一不可:
scripts/json-schema-out-dir.test.ts(新,7 例,毫秒级)—— 嵌套目录、退避次数、删不掉的条目如何上报、缺目录时的 no-op,以及把旧的整目录 rm 作为对照记下来;scripts/build-schemas-check-mode.test.ts里新增#5371describe(2 例,真实沙箱跑真实脚本)—— 写模式与--check各一条。--check单列,因为它才是现场报告的触发点:一个名字里带check:的命令删掉构建产物,正是这个坑难以联想到的原因。单测无法替代它:如果调用方哪天改回fs.rmSync(OUT_DIR, …),只有跑真实脚本的这一半会红。变更集
无 changeset,改用
skip-changeset标签:scripts/不在@objectstack/spec的files白名单里(dist/json-schema/liveness/prompts/llms.txt/README.md/src/**/*.zod.ts/CHANGELOG.md/api-surface/spec-changes.json),本 PR 全部改动都在scripts/与测试里;发布产物字节不变(pnpm build里gen:openapi依旧最后写openapi.json)。即 pr-automation 说的 route 2:本 PR 不发布任何东西。仍然留在门口的另一半 —— #5757
按 #5371 的分诊交叉链接说明:本 PR 采用的是候选①,所以门禁缺口依旧存在 ——
openapi.json被运行时读盘,却没有任何 freshness / existence 门禁(check:generated自报Generated but ungated (2))。本 PR 不关闭 #5757;它在此落地后晋级入队。这里只是不再有兄弟生成器主动删它。门禁与本地验证
pnpm --filter @objectstack/spec typecheck✓(tsc --noEmit+check:test-typecheck,debt 台账未变)pnpm exec eslint(本 PR 全部改动文件)✓pnpm check:nul-bytes✓(5920 个文件),并对改动文件做了越界自扫(grep -naP)✓pnpm check:published-files✓Generated by Claude Code