从 #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 的形状 —— 一条被当作闸门引用的命令,在这个类型上并不闸。
建议方向(未定,需维护者判)
无论选哪条,#4001 后续批次(ui/component.zod.ts 还有 29 个站点,view.zod.ts 还有 20 个)在写「三个示例应用 validate 全过」之前应该知道这条,否则会重复地把空证当成实证。
相关
按 AGENTS.md Prime Directive #10 归档,未指派。
从 #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的一个页面组件上加一个键:结果:
而同一份组件走元数据类型注册表这条门是拒绝的:
也就是说
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 的形状 —— 一条被当作闸门引用的命令,在这个类型上并不闸。
建议方向(未定,需维护者判)
objectstack build/validate对每个已注册的元数据类型都走getMetadataTypeSchema(type),与写路径同门。要先测量现有示例应用会不会因此变红(很可能会 —— 那正是这条 issue 的价值)。validate走(build 保持宽松,便于迭代),把它做成发布前闸门。无论选哪条,#4001 后续批次(
ui/component.zod.ts还有 29 个站点,view.zod.ts还有 20 个)在写「三个示例应用 validate 全过」之前应该知道这条,否则会重复地把空证当成实证。相关
packages/spec/src/kernel/metadata-type-schemas.ts、packages/cli按 AGENTS.md Prime Directive #10 归档,未指派。