Uh oh!
There was an error while loading. Please reload this page.
test(cli): #5000 前提被证伪 —— build/validate 一直按注册表 schema 解析,补上它缺的那份证据 - #5380
Conversation
…y schemas (#5000) #5000 measured that `os build` / `os validate` never parse `page` metadata through `PageSchema`, so an undeclared page-component key shipped into the artifact and #4001's "all three example apps validate clean" was empty evidence on the page surface. Re-measured on origin/main the claim does not hold: both commands parse the whole stack through `ObjectStackDefinitionSchema`, whose `pages` element is the schema `getMetadataTypeSchema('page')` returns. The issue's repro and its own negative control (`responsiveStyles.large` -> `.lg`) both exit non-zero today, and `os build` writes no artifact for a rejected stack. Nothing pinned either half of that, so this adds the evidence the issue found missing: - per registered metadata type, one undeclared key gets the same verdict from the write-path gate and from the schema the CLI parses through (the three structurally-different carriers -- field, translation, view -- are named and asserted at their real positions), plus a reconciliation that fails when a newly registered type is classified by nobody; - the two commands act on that parse, run through the real binary, with a control case (same stack, no planted key) that must exit 0. Behavioural rather than schema-instance identity on purpose: spec ships one bundle per entry point, so the root entry's embedded `PageSchema` and `@objectstack/spec/kernel`'s registry copy are never `===` (filed as #5379). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VkPSGsX9o17MsGv3Lbxu2w
The latest updates on your projects. Learn more about Vercel for GitHub. 1 Skipped Deployment
|
📓 Docs Drift CheckNo hand-written docs reference the 0 changed package(s). ✅ |
…ate ledger (#5000) `api` landed in DEFAULT_METADATA_TYPE_REGISTRY / BUILTIN_METADATA_TYPE_SCHEMAS on main (#5271 -> #5312) after this branch was cut, and the reconciliation case did its job: an unclassified registered type fails until someone decides how the CLI reaches it. Measured rather than assumed. The stack DOES carry it (`apis:`, ADR-0121, still declared on main), and the CLI and the write path reach the same schema — but `ApiEndpointSchema` is a plain `z.object`, so an undeclared key on an endpoint is dropped on BOTH paths. That is not a CLI divergence, it is a #4001 shape the campaign has not reached; the strictness ledger still files all of `api/` as "wire, tolerant by design", which stopped being true when the type was registered. Filed as #5384, a sub-issue of #4001. So `api` gets its own ledger row with the honest claim: the CLI is no looser than the write path, and the #3786 pre-parse layer still names the key so the author is not left with silence. When #5384 closes the shape, the agreement assertion goes red and the row moves into GATED_AT — the ratchet working. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VkPSGsX9o17MsGv3Lbxu2w
baozhoutao
commented
Aug 5, 2026
已合入新 main 并处理 |
Uh oh!
There was an error while loading. Please reload this page.
Fixes#5000
结论先说:前提不成立,所以本单没有实现新门
#5000 说
objectstack build/validate不会把 page 元数据按PageSchema解析,因而 ADR-0089 D3a 早该拒绝的键一路通过并写进产物。按 Prime Directive「issue 是线索不是规格」,先在origin/main(2f6516e)上复核 —— 复现不出来。两条命令都把整个 stack 过ObjectStackDefinitionSchema,而它的pages元素就是getMetadataTypeSchema('page')返回的那个 schema,和MetadataManager.validate/GET /api/v1/meta/ Studio 表单同一道门。PM 裁定里「让
os validate变成真门」的那件事,已经是现状,所以本 PR 不加门,只补 #5000 真正指出的那个缺口:没有任何东西钉住这件事。实测证据(均在
origin/main+ 本分支,2026-08-05)definePage的即时 parse 分开,配置写成纯对象字面量(不走defineStack/definePage):顺带说明 issue 当时为何会看到 exit 0 的一个可能:它改的是
examples/app-showcase,那里每个 page 都走definePage,而definePage会先抛;真要区分「命令闸没闸」必须绕开工厂。另一个更可能的机制是当时packages/spec/dist陈旧(AGENTS.md §9 那个陷阱)—— CLI 消费 dist,而它们的对照脚本走 src,同一份 schema 两个判决,正好长成 issue 描述的那个不对称。两者都无法事后证实,只作为记录。responsiveStyles.large写成.lg)现在也是红的,且带处方:逐类型测量(24 个已注册元数据类型):21 个在 stack 根部由同一个 schema 实例承载(
objects/pages/flows/ …);另外 3 个是结构性差异而非漏洞 ——field嵌在objects[].fields、translation在 stack 上是 locale 束(TranslationBundleSchema)而注册表是行形状TranslationItemSchema、view注册表是 view metadata type-schema is a no-op for runtime shapes: ViewItem/personalization bodies strip to {} under ViewSchema #3095 的四成员联合而 stack 承载其中的容器成员。三者的未声明键都被 CLI 这条路拒绝(objects.0.fields.title/translations.0.en-US/views.0)。三个示例应用(PM 要求的 build 侧测量):
app-showcase/app-crm/app-todo的validate全部 exit 0(warning 43 / 4 / 4 条,均为既有 author-time 建议)。也就是说 build 侧没有存量违规需要豁免,不需要降级成 warning,也不需要开硬化后续单 —— build 已经是硬门(拒绝即不出产物,上面第 1 条实测)。本 PR 做了什么
只加一个测试文件
packages/cli/test/metadata-type-schema-gate.test.ts(7 个用例,无生产代码改动、无 spec 改动):objectstack build/validate从不按 PageSchema 解析页面元数据:ADR-0089 D3a 早就该拒绝的键一路通过,#4001 的「三个示例应用 validate 全过」对 page 面是空证 #5000 的一般形式)。os build另断言没写产物。外加对照用例:同一个 stack 不种缺陷时必须 exit 0 —— 否则这三条会因为无关原因而红着通过,那正是objectstack build/validate从不按 PageSchema 解析页面元数据:ADR-0089 D3a 早就该拒绝的键一路通过,#4001 的「三个示例应用 validate 全过」对 page 面是空证 #5000 自己踩到的坑。A 与 B 分开写是因为它们独立失效:A 绿 B 红 = schema 严格但命令吞了判决(#3782 的形状);B 绿 A 红 = 命令在一个没人核对过是否规范的 schema 上闸(#4409 量到的 23/26)。
反向验证(方向事先声明)
预测:把
validate.ts里 parse 失败的分支临时短路,只有 B 的两条 validate 用例变红,A 的 schema 层用例与 build 用例保持绿。实测完全一致 —— 且值得记一笔:短路后命令仍以非零退出(下游result.data为 undefined 引发崩溃),光断言退出码是抓不住的,是那条「输出里必须出现那个键 / ADR-0089 D3a」的断言在干活。这就是这两条用例不只看 exit code 的原因。为什么用行为等价而不是实例同一性
@objectstack/spec按 entry 分别打包,root entry 内嵌的PageSchema和@objectstack/spec/kernel注册表里的那份在 dist 上永远不===(只有走 src 才成立)。这条约束已写进测试注释,并单独记为观察类 finding #5379,免得下一个人先写一遍 identity 断言再怀疑自己。未做 / 需维护者裁断
objectstack build/validate从不按 PageSchema 解析页面元数据:ADR-0089 D3a 早就该拒绝的键一路通过,#4001 的「三个示例应用 validate 全过」对 page 面是空证 #5000 应按「前提失效 + 证据补齐」关闭,而不是按「新门已实现」关闭 —— 方向 A/B/C 的取舍在当前代码上已无对象。测试
Generated by Claude Code