Skip to content

refactor(spec): 三个手写 unrecognized_keys 错误映射折叠进 strictObject 的按集合取键 guidance(#6619) - #6804

Draft
os-project-manager wants to merge 3 commits into
mainfrom
claude/issue-6619-fold-error-maps
Draft

refactor(spec): 三个手写 unrecognized_keys 错误映射折叠进 strictObject 的按集合取键 guidance(#6619)#6804
os-project-manager wants to merge 3 commits into
mainfrom
claude/issue-6619-fold-error-maps

Conversation

@os-project-manager

Copy link
Copy Markdown
Collaborator

Fixes #6619#6416 方向 2)

做了什么

packages/spec 里仅存的三个手写 $ZodErrorMap 折叠进共享 strictObject / strictUnknownKeyError 模板,删除手工维护的模板副本,并让它们的别名指针与处方进入 alias-integrity.test.ts 的审计视野(#6416 命名的盲区,就此闭合):

手写映射 所在文件(实测锚点,252f71bd6 折叠后的形态
strictVisibilityError shared/visibility.ts:113 VISIBILITY_STRICT_OPTIONS —— 模式取键的 guidance 集合(VISIBILITY_KEY_PATTERN
strictWidgetAnalyticsError ui/dashboard.zod.ts:163 WIDGET_GUIDANCE_SETS —— 三个枚举集合,按声明顺序
strictTenancyError data/object.zod.ts:442 精确 guidance(两块墓碑)+ history 槽位承载常驻解释句

核心决策:guidance 的按集合取键形态

dashboard.zod.ts 的分支按集合成员资格取键(11 个退役 analytics 键共享一条迁移处方),精确键形态无法表达,visibility 的家族甚至不可枚举(模式匹配 visibleWhenn / visibleIf / hiddenWhen / conceal…)。因此共享模板新增 KeySetGuidance / guidanceSets

  • keys: 枚举列表 RegExp(模式必须携带 examples,审计据此判定模式没写错、没被 shape 遮蔽);
  • name: 具名(LEGACY_WIDGET_ANALYTICS_KEYS 等)——刻意渲染进消息:面向作者的拒绝应点名,不点名装键的数组;每条处方在文案里自己把家族拼出来,这才是可读性所在。名字供声明处与审计失败文本使用。

优先级规则(strict-object.test.ts 逐条钉住)

  1. 精确 guidance 条目永远胜过集合——更具体者裁决,新增集合永远偷不走已有手写答案的键;
  2. 集合之间按声明顺序,第一个认领的集合作答(对应手写映射原本的 if 链自上而下);
  3. 集合命中即抑制改名建议(处方与 "did you mean" 是同一问题的两个答案);
  4. 每条消息每个集合至多一条 bullet,位置在第一个命中键处(11 个 legacy 键 = 1 段处方,不是 11 段)。

keySetMatchesString#search 而非 RegExp#test/g 模式下 test 有状态,同一键会交替命中/不命中;已有测试钉住)。

盲区闭合的实测证据

同一探针矩阵在折叠前后各跑一次(strictObjectDeclarations() 全量强制遍历后计数):

折叠前(252f71bd6 折叠后
注册表可见声明 65 70
this view/page schema 不可见 可见(×3 shape)
this dashboard widget 不可见 可见
`tenancy` 不可见 可见

alias-integrity.test.ts 新增三项:集合成员死条目检查(成员是已声明键 / 与精确 guidance 重复 / 两集合争抢一键均报错)、模式 examples 检查(必须命中自身模式且不是已声明键)、以及折叠闭合钉——把任何一个映射还原成手写 $ZodErrorMap 会直接红在门上。反向验证已实测:注释掉 widget 的 guidanceSets → 8 个测试红(含闭合钉),方向与预测一致(红),恢复后全绿。

13 个顺序钉的处置(#6453 遗产)

零删除,全部随代码迁移view.test.ts 4 个、dashboard.test.ts 7 个、object.test.ts 3 个(其中 1 个"无修复分支全消息钉"换了夹具键并新增同类钉,净增不减)。发射顺序契约(前言 → 修复通道 → 解释句最后)在模板里天然成立,钉子原样验证它。

消息字节的刻意变化(顺序契约不变,逐处说明)

  1. 处方渲染为 \n • bullet(原为内联空格拼接)——与包内所有已折叠面的处方通道一致;单行渲染器(os validate、CI 日志)本就把换行拍平,前言→修复→解释的顺序不动。
  2. 无处方的键获得编辑距离改名——手写映射没有这条通道:tenantfield 原答"is not a tenancy key."(说了问题、没给修复),现答"Did you mean tenantfieldtenantField?";titeltitlecolourVariantcolorVariantlabelllabel 同理。对读者严格变好。
  3. widget 多键族时各族处方全部给出(原 if/else 链只给第一个命中分支,categoryField+component 会静默丢弃隔离判词)——本折叠唯一的行为向变化,按声明顺序各一条 bullet,dashboard.test.ts 有专钉。
  4. tenancy 无修复键不再有兜底 bullet——"zzzz is not a tenancy key." 的信息量已由前言"Unrecognized key(s) on tenancy"承载,解释句照常收尾(全消息钉)。

七个 #6453 全消息变体中,处方文本本身逐字节保留;变的只是装配(bullet 化)与新增的修复通道。

objectUnknownKeyErrorImpl 惰性构建的处置

#5593 已经在 object.zod.ts 里用声明顺序替代了 TDZ 惰性构建(UNKNOWN_KEY_GUIDANCE 上移到 ObjectSchemaBase 之前)。本折叠照搬同一解法:TENANCY_MODES_EXPLAINER / TENANCY_RETIRED_KEY_GUIDANCE 均在 TenancyConfigSchema 之前声明,无新增惰性表;OS_EAGER_SCHEMAS=1 全量构建(check:generatedgen:schema)绿。

一处刻意机械折叠:FormFieldBaseSchema

它是 module-private base,唯一消费者 FormFieldSchema = base.extend({fields}).strict() 在门口关门——#4001 批 18 刻意不关 base(关了就是接受面变化,超出本卡)。因此从 strictObject 拆出 strictObjectError(options, shape)构建错误映射并注册进审计,不 .strict()。该点位保持字面 z.object( 拼写,strictness ledger 的 AST 读数器继续看得见它(ui/view.zod.ts 的 strip 计数 3 不动,counts 工件零再生);extraKeys: ['fields'] 补上扩展层声明的键,feildsfields 的建议因此可用。

接受面

逐字节不变——所有 schema 接受/拒绝的输入集合与折叠前完全一致(探针矩阵 32 个用例逐一比对;变的只有消息文本)。strictObject 的公共行为由既有测试全量回归。

公开导出面(./sharedgen:api-surface 已再生)

  • 移除:strictVisibilityError (const)(手写映射,本卡的删除对象)
  • 新增:VISIBILITY_STRICT_OPTIONS (const)KeySetGuidance (interface)keySetMatches (function)strictObjectError(经 strict-object.ts,不在 ./shared barrel)

验证

消费半径清扫

#5046 的教训沿规则消费半径清扫:spec 之外(packages/、apps/、examples/)对三个旧符号名与全部旧消息字节的引用为(唯一命中是 spec 自身注释与 ledger 证据行,均已更新)。changeset:.changeset/fold-unrecognized-key-error-maps.md(patch)。

🤖 Generated with Claude Code

https://claude.ai/code/session_018ffcE95NaMJcL9XJ9VDYgk


Generated by Claude Code

claude added 3 commits August 8, 2026 17:53
…bject guidance (#6619)

- strictUnknownKeyError grows a set-keyed guidance form (KeySetGuidance +
  guidanceSets): one prescription per named key family, exact entry wins,
  declaration order among sets, one bullet per message, rename suppressed.
- strictVisibilityError -> VISIBILITY_STRICT_OPTIONS (pattern-keyed set);
  strictWidgetAnalyticsError -> WIDGET_GUIDANCE_SETS (three sets);
  strictTenancyError -> exact guidance + history-slot explainer.
- strictObjectError split out of strictObject so FormFieldBaseSchema
  registers with the audit WITHOUT closing the base (acceptance unchanged);
  spelled as a literal z.object so the strictness ledger keeps its site.
- alias-integrity gains set-member/dead-entry, pattern-example and
  fold-closure checks (#6416 blind spot closed).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018ffcE95NaMJcL9XJ9VDYgk
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018ffcE95NaMJcL9XJ9VDYgk
@vercel

vercel Bot commented Aug 8, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
objectstack Ignored Ignored Aug 8, 2026 6:26pm

Request Review

@github-actions

github-actions Bot commented Aug 8, 2026

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

This PR changes 1 package(s): @objectstack/spec.

112 hand-written doc(s) reference the affected code and may need an implementation-accuracy re-verification:

  • content/docs/ai/agents.mdx (via @objectstack/spec)
  • content/docs/ai/skills-reference.mdx (via @objectstack/spec)
  • content/docs/ai/skills.mdx (via @objectstack/spec)
  • content/docs/api/client-sdk.mdx (via @objectstack/spec)
  • content/docs/api/environment-routing.mdx (via @objectstack/spec)
  • content/docs/api/error-catalog.mdx (via @objectstack/spec)
  • content/docs/api/error-handling-client.mdx (via @objectstack/spec)
  • content/docs/api/error-handling-server.mdx (via @objectstack/spec)
  • content/docs/api/index.mdx (via @objectstack/spec)
  • content/docs/automation/approvals.mdx (via @objectstack/spec)
  • content/docs/automation/connectors.mdx (via @objectstack/spec)
  • content/docs/automation/flows.mdx (via @objectstack/spec)
  • content/docs/automation/hook-bodies.mdx (via packages/spec)
  • content/docs/automation/hooks.mdx (via @objectstack/spec)
  • content/docs/automation/index.mdx (via @objectstack/spec)
  • content/docs/automation/webhooks.mdx (via @objectstack/spec)
  • content/docs/automation/workflows.mdx (via @objectstack/spec)
  • content/docs/concepts/architecture.mdx (via @objectstack/spec)
  • content/docs/concepts/design-principles.mdx (via packages/spec)
  • content/docs/concepts/index.mdx (via @objectstack/spec)
  • content/docs/concepts/metadata-driven.mdx (via @objectstack/spec)
  • content/docs/concepts/metadata-lifecycle.mdx (via packages/spec)
  • content/docs/concepts/north-star.mdx (via @objectstack/spec)
  • content/docs/data-modeling/analytics.mdx (via @objectstack/spec)
  • content/docs/data-modeling/drivers.mdx (via @objectstack/spec)
  • content/docs/data-modeling/external-datasources.mdx (via @objectstack/spec)
  • content/docs/data-modeling/field-types.mdx (via @objectstack/spec)
  • content/docs/data-modeling/fields.mdx (via @objectstack/spec)
  • content/docs/data-modeling/formulas.mdx (via @objectstack/spec)
  • content/docs/data-modeling/index.mdx (via @objectstack/spec)
  • content/docs/data-modeling/objects.mdx (via @objectstack/spec)
  • content/docs/data-modeling/queries.mdx (via @objectstack/spec)
  • content/docs/data-modeling/schema-design.mdx (via @objectstack/spec)
  • content/docs/data-modeling/seed-data.mdx (via @objectstack/spec)
  • content/docs/data-modeling/validation-rules.mdx (via @objectstack/spec)
  • content/docs/data-modeling/validation.mdx (via @objectstack/spec)
  • content/docs/deployment/cli.mdx (via @objectstack/spec)
  • content/docs/deployment/tenancy-modes.mdx (via @objectstack/spec)
  • content/docs/deployment/troubleshooting.mdx (via @objectstack/spec)
  • content/docs/deployment/validating-metadata.mdx (via @objectstack/spec)
  • content/docs/getting-started/build-with-claude-code.mdx (via @objectstack/spec)
  • content/docs/getting-started/common-patterns.mdx (via @objectstack/spec)
  • content/docs/getting-started/examples.mdx (via @objectstack/spec)
  • content/docs/getting-started/quick-reference.mdx (via @objectstack/spec)
  • content/docs/getting-started/quick-start.mdx (via @objectstack/spec)
  • content/docs/getting-started/your-first-project.mdx (via @objectstack/spec)
  • content/docs/kernel/cluster.mdx (via @objectstack/spec)
  • content/docs/kernel/contracts/auth-service.mdx (via packages/spec)
  • content/docs/kernel/contracts/cache-service.mdx (via packages/spec)
  • content/docs/kernel/contracts/data-engine.mdx (via @objectstack/spec)
  • content/docs/kernel/contracts/index.mdx (via @objectstack/spec)
  • content/docs/kernel/contracts/metadata-service.mdx (via packages/spec)
  • content/docs/kernel/contracts/storage-service.mdx (via @objectstack/spec)
  • content/docs/kernel/index.mdx (via packages/spec)
  • content/docs/kernel/runtime-services/data-service.mdx (via @objectstack/spec)
  • content/docs/kernel/runtime-services/email-service.mdx (via packages/spec)
  • content/docs/kernel/runtime-services/examples.mdx (via @objectstack/spec)
  • content/docs/kernel/runtime-services/index.mdx (via packages/spec)
  • content/docs/kernel/runtime-services/queue-service.mdx (via packages/spec)
  • content/docs/kernel/runtime-services/sharing-service.mdx (via @objectstack/spec)
  • content/docs/kernel/runtime-services/sms-service.mdx (via packages/spec)
  • content/docs/kernel/runtime-services/storage-service.mdx (via @objectstack/spec)
  • content/docs/kernel/services-checklist.mdx (via @objectstack/spec)
  • content/docs/kernel/services.mdx (via @objectstack/spec)
  • content/docs/permissions/authorization.mdx (via @objectstack/spec)
  • content/docs/permissions/permission-sets.mdx (via @objectstack/spec)
  • content/docs/permissions/permissions-matrix.mdx (via @objectstack/spec)
  • content/docs/permissions/positions.mdx (via @objectstack/spec)
  • content/docs/permissions/rls.mdx (via @objectstack/spec)
  • content/docs/permissions/sharing-rules.mdx (via @objectstack/spec)
  • content/docs/plugins/adding-a-metadata-type.mdx (via @objectstack/spec)
  • content/docs/plugins/development.mdx (via @objectstack/spec)
  • content/docs/plugins/index.mdx (via @objectstack/spec)
  • content/docs/plugins/packages.mdx (via @objectstack/spec)
  • content/docs/protocol/backward-compatibility.mdx (via @objectstack/spec)
  • content/docs/protocol/diagram.mdx (via packages/spec)
  • content/docs/protocol/kernel/config-resolution.mdx (via @objectstack/spec)
  • content/docs/protocol/kernel/http-protocol.mdx (via @objectstack/spec)
  • content/docs/protocol/kernel/i18n-standard.mdx (via @objectstack/spec)
  • content/docs/protocol/kernel/index.mdx (via @objectstack/spec)
  • content/docs/protocol/kernel/lifecycle.mdx (via @objectstack/spec)
  • content/docs/protocol/kernel/plugin-spec.mdx (via @objectstack/spec)
  • content/docs/protocol/knowledge.mdx (via @objectstack/spec)
  • content/docs/protocol/objectql/index.mdx (via @objectstack/spec)
  • content/docs/protocol/objectql/query-syntax.mdx (via @objectstack/spec)
  • content/docs/protocol/objectql/schema.mdx (via @objectstack/spec)
  • content/docs/protocol/objectql/security.mdx (via packages/spec)
  • content/docs/protocol/objectql/state-machine.mdx (via @objectstack/spec)
  • content/docs/protocol/objectui/actions.mdx (via @objectstack/spec)
  • content/docs/protocol/objectui/concept.mdx (via @objectstack/spec)
  • content/docs/protocol/objectui/index.mdx (via @objectstack/spec)
  • content/docs/protocol/objectui/layout-dsl.mdx (via @objectstack/spec)
  • content/docs/protocol/objectui/record-alert.mdx (via @objectstack/spec)
  • content/docs/protocol/objectui/widget-contract.mdx (via @objectstack/spec)
  • content/docs/releases/implementation-status.mdx (via @objectstack/spec)
  • content/docs/releases/index.mdx (via @objectstack/spec)
  • content/docs/releases/v12.mdx (via @objectstack/spec)
  • content/docs/releases/v13.mdx (via @objectstack/spec)
  • content/docs/releases/v16.mdx (via @objectstack/spec)
  • content/docs/releases/v17.mdx (via @objectstack/spec)
  • content/docs/releases/v9.mdx (via @objectstack/spec)
  • content/docs/ui/actions.mdx (via @objectstack/spec)
  • content/docs/ui/apps.mdx (via @objectstack/spec)
  • content/docs/ui/create-vs-edit-form.mdx (via @objectstack/spec)
  • content/docs/ui/dashboards.mdx (via @objectstack/spec)
  • content/docs/ui/field-grouping-and-order.mdx (via @objectstack/spec)
  • content/docs/ui/forms.mdx (via @objectstack/spec)
  • content/docs/ui/index.mdx (via @objectstack/spec)
  • content/docs/ui/public-data-collection.mdx (via @objectstack/spec)
  • content/docs/ui/setup-app.mdx (via @objectstack/spec)
  • content/docs/ui/translations.mdx (via @objectstack/spec)
  • content/docs/ui/views.mdx (via @objectstack/spec)

Advisory only. To re-verify, run the docs-accuracy-audit workflow scoped to these files:
node scripts/docs-audit/affected-docs.mjs origin/main → pass the list as args.docs.

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

Projects

None yet

2 participants