refactor(spec)!: 补完 2026-06 字段剪除 — 删除两个孤儿 value schema (#3726, #3733) - #3732
Conversation
…ataQualityRulesSchema (#3726) The `dataQuality` field key was pruned in 2026-06 along with `encryptionConfig`, `maskingRule`, `auditTrail` and `cached` — "dead in both layers, aspirational governance with no runtime consumer" (docs/audits/2026-06-dead-surface-disposition-plan.md, P0/P2 field prune). Four of the five took their value schemas with them. `dataQuality` did not: the key vanished from `FieldSchema` while `DataQualityRulesSchema` stayed on the published API surface and in the generated reference docs, with zero consumers anywhere in the tree. Removed, matching the other four: - DataQualityRulesSchema (const) - DataQualityRules (type) - DataQualityRulesInput (type) - the published data/DataQualityRules.json schema Of the three coherent states — key + schema + consumer, none of them, or schema only — the surviving one was the worst, and it failed quietly rather than loudly. `FieldSchema` is NOT `.strict()` (verified by parse: an unknown key succeeds and is dropped), so an author who found `DataQualityRules` in the reference docs and wrote `dataQuality: { uniqueness: true }` got no error at all — the field parsed clean and the key was silently stripped. Declared in source, absent from the contract, enforced by nothing: the ADR-0104 failure class that the `accept` / `maxSize` declarations were added to close. `uniqueness` was the sharpest edge. Described as "Enforce unique values across all records", it reads exactly like the platform-wide scope that `unique: 'global'` actually provides (#3696), making it the option an author was most likely to reach for by mistake. The json-schema ratchet (#2978) caught the retirement as designed; its manifest key is removed here as the deliberate-retirement step. api-surface.json loses exactly the three entries #3726 predicted, and the generated field reference drops the DataQualityRules section. A tombstone in field.zod.ts records why, so the schema is not restored on its own again. Full build (71 tasks) and test suite (132 tasks) green. Closes #3726 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MwkLYCx8NL3sqSvqcoBt5p
|
The latest updates on your projects. Learn more about Vercel for GitHub. 1 Skipped Deployment
|
📓 Docs Drift CheckThis PR changes 1 package(s): 104 hand-written doc(s) reference the affected code and may need an implementation-accuracy re-verification:
|
|
附带发现已按 Prime Directive #10 单独开:#3733 —
没有在本 PR 里一并删掉:那是 issue 作者明确评估过、并判定为已完成的一项,再动一次公开 API 值得单独决策。#3733 里写了照搬本 PR 的处置步骤。 顺带确认两条 bot 评论无需处理:
Generated by Claude Code |
…heSchema (#3733) The 2026-06 prune left TWO orphaned value schemas, not one. #3726 caught `dataQuality`'s and its core table recorded `cached` as already cleaned — it was not. `ComputedFieldCacheSchema` + the `ComputedFieldCache` type were still on the published API surface (api-surface.json:195-196), still shipping `data/ComputedFieldCache.json`, and still occupying a section in the generated field reference, while the `cached` key itself had been gone from `FieldSchema` since the prune. Consumers in-tree: zero. Removed, matching the other four keys of that prune: - ComputedFieldCacheSchema (const) - ComputedFieldCache (type) - the published data/ComputedFieldCache.json schema Same failure mode as `dataQuality`, verified the same way — `FieldSchema` is not `.strict()`, so authoring the discoverable shape succeeds and the key is dropped: FieldSchema.safeParse({ name: 'total', type: 'formula', cached: { enabled: true, ttl: 3600 } }) → parse success: true → cached key survived? false This one is the quieter of the two and so the harder to notice: an author writing `ttl: 3600` on a formula field would believe results were cached for an hour, get no error, and never see a signal that nothing had happened. Declared in source, absent from the contract, enforced by nothing — the ADR-0104 failure class. The tombstone in field.zod.ts is generalized to cover both orphans and to record that all five keys are now dead in both layers, as it always claimed. The changeset is rewritten to cover both removals and renamed accordingly. The json-schema ratchet (#2978) caught this retirement too; its manifest key is removed as the deliberate-retirement step. api-surface.json goes 4383 → 4381 exports, exactly the two entries #3733 predicted. Full build (71 tasks), test suite (132 tasks), all six spec drift checks and check:liveness green. Closes #3733 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MwkLYCx8NL3sqSvqcoBt5p
DataQualityRulesSchema (#3726)…esschema-orphan-cleanup-tgwyfw
Closes #3726。Closes #3733。两个 issue 是同一批剪除留下的同一种残留,处置完全同构,合并在本 PR 一起走。
改了什么
从
@objectstack/spec公开面上移除:DataQualityRulesSchema(const) /DataQualityRules(type) /DataQualityRulesInput(type)ComputedFieldCacheSchema(const) /ComputedFieldCache(type)以及随之停发的
data/DataQualityRules.json和data/ComputedFieldCache.json。api-surface.json4383 → 4381,恰好是两个 issue 各自预言的 3 + 2 条。那批剪除留下的是两个孤儿,不是一个
2026-06 剪掉五个字段键(
encryptionConfig/maskingRule/auditTrail/cached/dataQuality),tombstone 声明它们 "dead in both layers"。实际三个带走了自己的 value schema,两个没有:encryptionConfigmaskingRuleauditTrailcacheddataQualitycached那一行是 #3726 核对表里唯一记错的。两者形态完全一致:键早已从FieldSchema删除,schema 仍在公开面 + 生成的参考文档里,全仓消费者为零。一处事实更正:
FieldSchema并不是.strict()#3726 的第 1 条理由说,作者若误写会因
.strict()直接 parse 报错。实测不是这样 ——FieldSchema是普通z.object({...}),没有.strict()。两个键都实测过:解析成功,键被静默丢弃。这比报错更糟:报错至少给作者信号,静默剥离让「source 里写了 / 契约里没有 / 没人执行」同时成立且零反馈 —— 正是
field.zod.ts里accept/maxSize注释点名的 ADR-0104 失败类。结论不变,剪除的理由反而更强。commit message、changeset、代码 tombstone 均按实测事实措辞。两者各有一处尖角:
DataQualityRules.uniqueness描述为 "Enforce unique values across all records",读起来恰好像unique: 'global'真正提供的全平台唯一(多租户缺陷:unique 物化为全局唯一索引、无视 tenancy,与按租户分裂的 autonumber 序列自相矛盾(跨租户必然撞号 + 存在性探测泄露) #3696),是最容易被误选的那个。ComputedFieldCache更安静因而更难察觉:作者在公式字段上写ttl: 3600,会以为结果缓存了一小时,没有报错,也永远看不到「什么都没发生」的信号。验证
pnpm build(全仓)pnpm test(全仓)check:api-surfacecheck:docscheck:livenesscheck:spec-changes/check:upgrade-guide/check:skill-refs/check:skill-docs第一个 commit 推上去后的 CI 也是全绿(含 Spec property liveness、Check Changeset、Check Generated Artifacts、Build Docs、ESLint)。
json-schema ratchet(#2978)两次都如设计般拦下了停发,manifest 键的移除是它要求的 deliberate-retirement 步骤。生成物(
api-surface.json、json-schema.manifest.json、content/docs/references/data/field.mdx)均由脚本重新生成,未手改。破坏性 & 迁移
已配 changeset(
@objectstack/spec: minor+!标记,随 v17 major 发车,沿用apimethod-enum-shrink的先例),覆盖两次移除。无运行时行为可迁移 —— 两个 schema 都从未被
FieldSchema引用,都没有消费者。字段级唯一性用unique(true= 租户内、'global'= 全平台,#3696);completeness/accuracy/ 计算字段缓存(enabled/ttl/invalidateOn)无替代,本就从未实现。field.zod.ts的 tombstone 已改写为覆盖两个孤儿,并写明:若将来真做数据质量治理或计算字段缓存,键与 schema 必须连同消费者一起加回(ADR-0049 enforce 侧),不要单独恢复 schema —— 那个中间态正是这两个 issue 的由来。五个键至此在两层都真的死了,与 tombstone 一直以来的声明相符。