Repository navigation
Description
从 #4001 批 13 的 ADR-0087 示例应用验证步骤拆出(发现)。做阴性对照时撞到的:对照本身没能变红。
问题
objectstack build 与 objectstack validate 不会把 page 元数据按 PageSchema 解析。一个 PageComponentSchema 自 ADR-0089 D3a 起就是 .strict() 拒绝的键,原样通过两条命令,并被写进产物。
复现(origin/main + #4001 批 13 分支,2026-08-03)
往 examples/app-showcase/src/ui/pages/styling-gallery.page.ts 的一个页面组件上加一个键:
{
id: 'styling_root', type: 'flex',
responsiveStyles: { large: { display: 'flex' } },
aKeyPageComponentHasRejectedSinceADR0089: 1, // 加这一行
...
}结果:
pnpm -s build → exit 0(无任何相关报错)
pnpm -s validate → exit 0(无任何相关报错)
而同一份组件走元数据类型注册表这条门是拒绝的:
getMetadataTypeSchema('page')!.safeParse(page)
// REJECTED — Unrecognized key(s) on this view/page schema:
// `aKeyPageComponentHasRejectedSinceADR0089`也就是说 PageSchema 的严格性在 MetadataManager.validate / GET /api/v1/meta / Studio 表单那条路上是生效的,唯独 CLI 的 build/validate 不走它。
为什么这条值得单独记
-
它让 未知键静默剥离仍是全仓默认:把 #3405 的 strict 收紧从一个 schema 推广到整个可授权面(ADR-0078 完整性闸门) #4001 的零破坏证据在 page 面上是空的。 这场战役每一批的验收里都有一条「app-showcase / app-crm / app-todo 三个示例应用
validate全过」(feat(spec): reject unknown keys on an action param instead of stripping them (#3405) #3746 起就是这么写的)。对object/flow/field那些类型这条证据是实的;对page它恒为真,因为那条路根本不解析。批 13 收紧ResponsiveConfigSchema/ResponsiveStylesSchema时,阴性对照(把responsiveStyles.large改成.lg)在validate上没变红 —— 只有在按槽位溯源解析产物的探针上、以及在getMetadataTypeSchema('page')这条真门上才变红。后两者是批 13 实际采用的证据。 -
产物会把坏值带下去。 上面那次注入之后
dist/objectstack.json里确实带着未声明的键(587.8 KB 的 showcase 产物,build打印 41 条 author-time warning,没有一条与之相关)。 -
这是 Prime Directive chore: version packages #10 的形状 —— 一条被当作闸门引用的命令,在这个类型上并不闸。
建议方向(未定,需维护者判)
- A. 让
objectstack build/validate对每个已注册的元数据类型都走getMetadataTypeSchema(type),与写路径同门。要先测量现有示例应用会不会因此变红(很可能会 —— 那正是这条 issue 的价值)。 - B. 只让
validate走(build 保持宽松,便于迭代),把它做成发布前闸门。 - C. 明确记录 build/validate 不是 schema 闸门,并把 未知键静默剥离仍是全仓默认:把 #3405 的 strict 收紧从一个 schema 推广到整个可授权面(ADR-0078 完整性闸门) #4001 各批验收里那条证据的措辞按类型限定,免得后续批次继续引用一条对 page 面为空的证据。
无论选哪条,#4001 后续批次(ui/component.zod.ts 还有 29 个站点,view.zod.ts 还有 20 个)在写「三个示例应用 validate 全过」之前应该知道这条,否则会重复地把空证当成实证。
相关
- 未知键静默剥离仍是全仓默认:把 #3405 的 strict 收紧从一个 schema 推广到整个可授权面(ADR-0078 完整性闸门) #4001(批 13 的 PR 描述里记了同一组测量)、feat(spec): reject unknown keys on an action param instead of stripping them (#3405) #3746(这条证据措辞的出处)
- ADR-0089 D3a(view/page strict)、ADR-0087
packages/spec/src/kernel/metadata-type-schemas.ts、packages/cli
按 AGENTS.md Prime Directive #10 归档,未指派。
Activity
docs(spec): record the measured binding door for the responsive stric…
feat(spec)!: 收紧 responsive/SDUI 样式形状的未知键,并把另外五个文件按实测改判(objectstack-ai…
baozhoutao commentedon Aug 5, 2026
🔒 认领:PM 循环第 1 轮(cli 车道,v17 优先)
会话:
session_01VkPSGsX9o17MsGv3Lbxu2w分支:
claude/issue-5000-cli-validate-page-schemaWorktree:
objectstack-issue-5000域:
domain:cli文件面:
packages/cli/src/**(validate / build 命令及其共享元数据装载·校验路径)+ 对应测试 + changeset。只读消费packages/spec的getMetadataTypeSchema,⛔ 不改 spec(spec 面归 spec 车道)。与同批 #5155(runtime dispatcher)、#5359(serve.ts)文件面不相交。PM 裁定(两轴分析,留否决窗口 —— 维护者可否决,不等批准):
os validate本单接真门(方向 A 的 validate 半边,v17 breaking 窗口件):对每个已注册元数据类型走getMetadataTypeSchema(type)整体解析,拒绝带处方 —— 与写路径(MetadataManager.validate/ Studio)同门。理由:①长远轴 —— 被 未知键静默剥离仍是全仓默认:把 #3405 的 strict 收紧从一个 schema 推广到整个可授权面(ADR-0078 完整性闸门) #4001 各批验收当作闸门引用的命令必须真闸(declared = enforced),否则「三个示例应用 validate 全过」对 page 面恒为空证;②防 AI 轴 —— AI 批量写元数据时,静默通过 + 产物带坏键正是错误被掩盖的温床,publish 时响亮拒绝优于消费端宽容。build侧按测量定:先测三个示例应用的红量;能在本单内修干净则 build 同样接门;若存在本单内修不完的存量违规,build 降为响亮 warning 并立后续单跟踪硬化,⛔ 不许静默通过。同日 churn:
packages/cli昨日被 #5314(ADR-0120 收尾)、更早被 #5065(apis:硬拒)触及 —— dev 基于合并后代码工作,issue 引用片段以origin/main为准先核对。Generated by Claude Code
test(cli): classify the newly registered `api` type in the metadata g…
baozhoutao commentedon Aug 5, 2026
✅ 验收通过 —— 前提证伪 + 证据补齐,PR #5380 转 ready 入队;本单随其合并关闭
对 GitHub 实况复核(cli 车道 PM,session_01VkPSGsX9o17MsGv3Lbxu2w):
前提裁定:本单描述的缺口在当前 main 上不存在。 dev 用纯对象字面量配置(绕开
definePage即时 parse)复现本单注入键:os validateexit=1 带 ADR-0089 D3a 处方,os buildexit=1 且不写产物;本单自己的阴性对照(.lg)同样红且带Did you mean lg -> large?。逐类型测量 24 个注册类型:21 个由同一 schema 实例承载,3 个结构性差异(field/translation/view)未声明键同样被拒。三个示例应用 validate 全绿 → build 侧无存量违规,无需降级或硬化后续单。方向 A/B/C 在当前代码上已无对象 —— 按「前提失效 + 证据补齐」关闭(dev 建议 A,PM 采纳):PR #5380 的 8 条 pin 测试把「门存在」变成 CI 会红的断言,比限定 #4001 验收措辞更难被悄悄推翻;「三个示例应用 validate 全过」对 page 面自此是实证。PM 公开认账一处:我在认领评论里写的裁定依据「
apis:已随 #5065 从 stack schema 退役」与合并后代码不符 ——stack.zod.ts:329仍声明apis:,#4936 的整面拒绝已被执行器工程(#5040 E7)的逐端点门取代。dev 以 file:line 更正并按实测分类,正确;后续读者以 dev 的 PR 评论为准。对账用例首战立功:PR 首次 CI 即抓到 #5312 中途注册的
api类型(设计目标场景),并顺藤发现ApiEndpointSchema仍是开放 z.object —— 已立 #5384(挂 #4001 子单,spec 车道),测试内给它一条诚实账本行(schema 关上时该行会红,届时是刻意的棘轮推进)。#5379(跨 entry 实例同一性)已立为 finding。CI 23 项零失败(changeset 按
skip-changeset标签豁免 —— 纯测试零发布物)。PR 转 ready 挂合并队列,跟到 MERGED。Generated by Claude Code
test(cli): objectstack-ai#5000 前提被证伪 —— build/validate 一直按注册表 schema …
feat(spec): close the 31 SDUI component-props shapes against unknown …
fix(pm): the merge-queue guard refuses an oversized PR and the post-m…