feat(spec)!: 退役 NotificationActionSchema / EmbedConfigSchema —— 两个没有授权门的 ui 词汇表形状 (#5015) - #5300
Merged
Merged
Conversation
…权门的 ui 词汇表形状 (#5015) ADR-0049 enforce-or-remove,裁决 REMOVE(2026-08-04 分诊)。两个形状都是 published `./ui` 词汇表,但**从来没有键可以写进去** —— 比「声明了但没人读」 还低一级的一档。 #4001 批 14 在 2026-08-03 做的三条测量,本次在 origin/main 上全部重跑,每条 都带同一次运行内通过的阳性对照: 1. 承载键 —— 没有任何 schema 声明这两个类型的键。按 specifier 解析而非子串 比对(仓里有两个 sharing.zod,子串法会误记 stack.zod.ts)。 2. 图可达性 —— 从 24 个 metadata-type root + ObjectStackSchema 做 BFS(含 derived-clone 桥接)两个都走不到;Page / Action / DashboardWidget / Webhook / SharingConfig 在同一次运行里全部 root-graph,注入合成承载键后 两个都翻成 root-graph。 3. 调用点 —— 三个仓里除各自单测外零 .parse()。 批 14 故意没有用 .strict() 收紧:strict 是一次 parse 的属性,对没人 parse 的 形状收紧只会留下「一个被精确校验的死槽位」(#4583)。⚠️ 按 SCHEMA 退役,不是按文件。两个模块都存活: - ui/sharing.zod 保留 SharingConfigSchema —— 活门,FormViewSchema.sharing 承载,rest-server.ts 读它挂匿名表单路由。公开表单分享不受影响。 - ui/notification.zod 保留三个呈现枚举。 生成物基线的删除是有意的(整 def 删除路线的预期读数):manifest −2 key, authorable-surface −10 行,api-surface −4 导出。#2978 ratchet 先开火,删完 重跑后 per-key ratchet 自行判定为 #4650 路径 3。 批 14 留下的 JSDoc + pin + 台账三处留痕一并改写:no-door pin 换成 notification-embed-retirement.test.ts 的缺席+存活双向 pin(缺席按 resolved symbol identity;存活侧同样承重 —— 连文件删掉的「退役」能满足全部缺席断言 却会摧毁工作面),台账两行按反向 pin 删除并记录去向。 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01ErbEDVAg1No9gdg1pgDAGB
|
The latest updates on your projects. Learn more about Vercel for GitHub. 1 Skipped Deployment
|
Contributor
📓 Docs Drift CheckThis PR changes 1 package(s): 107 hand-written doc(s) reference the affected code and may need an implementation-accuracy re-verification:
|
This was referenced Aug 4, 2026
os-zhuang
marked this pull request as ready for review
August 4, 2026 17:14
同步 #5289(theme token 退役)、#5293(HttpServerConfig 退役)、#5296 等。 冲突 1 处:`packages/spec/src/migrations/registry.ts` —— step17 `rationale` 的纯追加碰撞(#5021 与 #5015 各追加一段)。按「双方事实都保留」解决: main 已落地的 theme 段落原样保留,本单段落改写开头衔接语跟在其后。 生成物一律按 os-regen 四步处理:先 `git checkout origin/main --` 取回 main 侧全部 os-regen 路径,再整体重新生成(gen:schema / gen:api-surface / gen:spec-changes / gen:upgrade-guide / gen:docs / gen:skill-refs / gen:skill-docs / gen:strictness-ledger),零文本合并、零手改数字。 merge-base gate 现在一次性为三个兄弟单的 5 处整 def 删除背书: system/HttpServerConfig(9 行)、ui/Animation(2)、ui/EmbedConfig(7)、 ui/NotificationAction(3)、ui/ZIndex(8),全部走 #4650 路径 3。 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01ErbEDVAg1No9gdg1pgDAGB
os-zhuang
enabled auto-merge
August 4, 2026 19:21
os-zhuang
pushed a commit
that referenced
this pull request
Aug 4, 2026
…aseline (#5235) `git merge origin/main` brought #5289 / #5293 / #5296 / #5300, three of which change the authorable surface (theme token tombstones, the HttpServerConfig removal, the NotificationAction / EmbedConfig removals). The anchor is written from the merge base, so it moves with it: baseRev 88b9b2d → 26e1029, 8045 → 8016 keys, regenerated by `gen:schema` rather than text-merged — this file is on the os-regen list precisely because a textual merge of it means nothing. Verified line-for-line against `git show 26e1029:packages/spec/authorable-surface.json`, and the siblings' entries survived in it: `ui/Theme:animation [RETIRED]` / `ui/Theme:zIndex [RETIRED]` are carried, HttpServerConfig / NotificationAction / EmbedConfig are gone from every generated witness at once. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01ErbEDVAg1No9gdg1pgDAGB
This was referenced Aug 4, 2026
os-zhuang
pushed a commit
that referenced
this pull request
Aug 4, 2026
) Serial-landing sync for PR #5306. `git merge origin/main`, then all NINE os-regen paths reset to origin/main and regenerated wholesale from the merged sources (the path list read from the merged tree's `.gitattributes`, not from memory — #5304 added `authorable-surface.base.json` as the ninth). The merge driver had deferred `api-surface.json` and `json-schema.manifest.json`, and git's textual result RESURRECTED symbols three sibling PRs had retired — this branch's pre-merge copies still listed them. Wholesale regeneration removes them again: - #5293: HttpServerConfig / HttpServerConfigInput / HttpServerConfigSchema - #5289: Animation / AnimationSchema / ZIndex / ZIndexSchema - #5300: EmbedConfig / EmbedConfigSchema / NotificationAction / NotificationActionSchema Verified after regeneration: this PR's 7 exports and `data/FilterArray` still present, the FilterArray docs section still carries its describe text, all three siblings' retirements absent from every witness, the #5304 anchor authentic (baseRev an ancestor of origin/main, keys identical line-for-line to that commit's surface), and `check:merge-driver` reconciling 9 paths both ways. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01ErbEDVAg1No9gdg1pgDAGB
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #5015
ADR-0049 enforce-or-remove,按 2026-08-04 分诊裁决 REMOVE 执行(T2 档,否决窗口已过)。走
spec-property-retirement套件的整 def 删除路线。先复核前提(rule 6)——三条测量在
origin/main上全部重跑批 14 的证据是 2026-08-03 的,不能直接拿来当施工依据。三条独立测量重跑,每条都带同一次运行内通过的阳性对照:
ui/notification.zod非测试 importer =['ui/index.ts'];ui/sharing.zod=['ui/index.ts','ui/view.zod.ts'],而view.zod.ts:1531点名的是兄弟SharingConfigSchemasecurity/sharing.zod有 5 个 importer(含stack.zod.ts)—— 证明匹配器在工作,且两个同名模块被分开了Page/Action/DashboardWidget/Webhook/SharingConfig全部root-graph;注入合成承载键后两个都翻成root-graph.parse()测量 1 的子串陷阱是真的:仓里有两个
sharing.zod(ui/与security/),子串法会把stack.zod.ts/security/index.ts误记为 UI 那个的 importer。全程按 specifier 解析。第一版 BFS 探针四个阳性对照全部 UNREACHABLE。零命中不可信,于是改查仪器,连查出两个缺陷:
getMetadataTypeSchema('page') !== PageSchema—— metadata-type root 是派生克隆,这正是build-schemas.ts里derived-clone那条腿存在的原因。补上后仍有两个对照红。.mts入口造成双模块实例。探针写成.mts时,view.zod.ts走 CJS 而探针的 import 走 ESM,sharing.zod被求值两次 ——sharing.innerType === SharingConfigSchema为false,每一层属性实例都不同。换成.ts入口后true。改完两处,五个对照全绿、两个 subject UNREACHABLE、合成承载键翻转 —— 这才是可信的读数。如果当初信了第一版的零命中,结论恰好也是「不可达」,但理由是假的。
改了什么
NotificationActionSchema/NotificationAction—— 移除。I18nLabelSchemaimport 随之移除(该文件仅此一处用)。EmbedConfigSchema/EmbedConfig—— 移除。ui/index.tsbarrel 加指向注释。ui/sharing.zod保留SharingConfigSchema,它是活门:FormViewSchema.sharing承载,rest-server.ts读allowAnonymous/publicLink挂匿名表单路由,两个示例应用都在写。公开表单分享不受影响,批 14 给它的strictObject也原样保留。ui/notification.zod保留三个呈现枚举(objectui toaster 的词汇表)。派单提到
notification.zod整文件退役「on the table」——核实后否决:文件里还有三个z.enum活导出。它现在的对象站点是 0(枚举不是 object site),所以台账行必须删,但文件不能删。两个形状为什么会成为孤儿(各自是上一层退役的遗留)
NotificationAction在 spec 双源清账 C3:通知语汇 Notification(Schema)(./api ≠ ./ui)+ NotificationConfig(Schema)(./system ≠ ./ui)—— 4 条,单 PR #4610 失去两个 wrapper(NotificationSchema/NotificationConfigSchema,零消费者被删);EmbedConfig在 17.0.0 失去它的键 —— 2026-06 liveness audit 退役了App.embed,该键至今作为retiredKey()墓碑立在app.zod.ts。写了那个键的作者早就撞得到处方;本次删的是比键活得更久的值形状。路线与 ratchet 读数(整 def 删除,不是枚举值收窄)
套件明写这两种形态的 ratchet 可见性相反,拿错对照就会判错。本次是整 def 删除,所以四张 ratchet 必须变化,本单实测:
json-schema.manifest.json−2 keyauthorable-surface.json−10 行api-surface.json−4 导出而且这串输出本身就是路线的自证,原样留档:
有意删掉 manifest key 后重跑,merge-base gate(对
origin/main,本 PR 改不动它)自行判为 #4650 路径 3。同步后这段输出更完整 —— 它一次性为三个兄弟单的 5 处整 def 删除背书,是「兄弟条目没被吞」最直接的证据:未注册 D2 conversion,注册的是 D3
SemanticMigration(ui-notification-action-embed-config-retired):两个形状都没有承载键,没有任何sys_metadata行装得下,也没有源码可改写 —— 这正是EnhancedApiError.fieldErrors/ #4834 那一档。step17 的rationale同步扩写。批 14 三处留痕的一并改写(pin 不能半死不活)
strictness-batch14.test.ts的 no-door pinno-door pin 那个 describe 块没有整体保留也没有整体删除:
namesEmbed).toEqual([])—— 整体替换。schema 删掉后它依然绿,但绿的原因是「什么都没产出」而不是逻辑成立(PR fix(lint): 收敛 validate-expressions / validate-security-posture 的 spec 不声明键??别名读法 (#5017) #5046 记录的那个陷阱)。缺席断言搬到新 pin 文件,在那里它能真红。both stay strip—— 删除(断言的是已删符号)。SharingConfig承载键 —— 保留,这半边讲的还是活形状,跟着一起删会把幸存判定的证据也删掉。SharingConfigSchema仍拒绝未声明键的行为断言(带阳性对照),防止「删兄弟顺手带走严格性」。新 pin:缺席与存活双向,两边都承重
packages/spec/src/ui/notification-embed-retirement.test.ts,照 #4834 的编译器 API 形制(#4642:本包 tsconfig 排除*.test.ts,类型级断言是装饰品):按 resolved symbol identity 遍历package.jsonexports map 的每个 public entry。存活侧和缺席侧一样承重 —— 一次连文件删掉的「退役」能满足全部缺席断言,却会摧毁
SharingConfigSchema这样的工作面。反向验证:方向先预判后运行,两次都如预期红
EmbedConfigSchema加回去EmbedConfigSchema must have zero holders: expected [ './ui' ] to deeply equal []notification.zod(摘掉三个枚举)NotificationTypeSchema must SURVIVE this retirement: expected [] to include './ui'—— 失败全部落在 SURVIVE 断言上第二条正是派单点名的范围性错误,pin 抓得住。
一个自打脸的记录
新 pin 第一版在
.(根 barrel)上同时断言了存活,跑出来是红的:根 barrel 是精选面,只从./uire-exportdefineX工厂,不导出 schema 词汇表 —— 四个幸存者从来就不在.上。这也意味着根 barrel 上的缺席断言本身是弱证据(那两个名字本来也不在)。已改成:缺席两个 entry 都查(防止将来有人在根上「顺手」采纳),存活只在./ui断言,并把这段经过写进注释。台账(#5220 格式)
数字一律
gen:strictness-ledger整体重算,零手改。本单自身的位移:sites −2、strip −2、
no door−2;strict列不动(没碰活门)。同步 #5289 后的绝对值以生成文件为准 —— 合并前后都重算过,写在这里的是重算结果而不是任何一方的减法:总 sites 474、strip 219、
no door36;ui/190 sites / 112 strict / 73 strip。(strict从 120 落到 112 是 #5289 的 8 个 theme 退役,不是本单;本单对strict列的贡献恒为 0。两个退役单叠加时,正是「各自减法都对、合并后小计错」的经典场景 —— 所以全部重算。)反向 pin 要求已闭合的行必须删,三行按 gate 报错逐条处置:
notification.zod.ts的 triage 行 —— 删(0 对象站点),去向记在表下;sharing.zod.ts的 triage 行 —— 保留并改写(文件还有 1 个 strict 站点);另外改掉两处现在读起来是假的现在时:分类规则里把
ui/sharing.zod.ts当作「一行两判」活例子的段落,和ui/小结里把这两个列为no door未决项的清单。顺带记一笔反讽:
sharing.zod.ts那行原话写着*「shrinks without disappearing —— the firstno doorfloor」*,而这次它就是消失了。反向 pin 对零命中一视同仁,分不出「有意的地板」和「被退役掉的地板」,所以在表下写清了。⛔ 不在本 PR 范围
packages/react/src/hooks/__tests__/animation-notification-spec-parity.test.tsx(读.shape.variant当词汇表,不是 parse)、packages/types/src/__tests__/spec-ui-schema-reexports.test.ts、packages/types/src/__tests__/p2-spec-exports.test.ts。objectui 刷新本依赖时会红,适配由 PM 另行立案。content/docs/releases/未改动。同步记录(2026-08-05,入队前)
合入
origin/main@175d789(#5289 theme 退役、#5293 HttpServerConfig 退役、#5296 等)。无 rebase、无 force-push。冲突 1 处:
packages/spec/src/migrations/registry.ts—— step17rationale的纯追加碰撞(#5021 与本单各追加一段)。按「双方事实都保留」解决:main 已落地的 theme 段落原样保留,本单段落改写开头衔接语跟在其后。ui/index.ts与strictness-batch14.test.ts均无冲突。rationale属性,我的续行+ '…'成了语法错误(Expected identifier but found "+")。第一次跑构建时我用 grep 过滤输出、把管道状态当成了退出码,报告成「BUILD done」—— 正是套件 §6 那条| tail掩盖退出码的陷阱。改成显式捕获EXIT=$?后立刻暴露,已修(接成\n\n续行)。生成物按 os-regen 四步:
git checkout origin/main --取回.gitattributes当前清单的全部 8 条 os-regen 路径(authorable-surface.base.json不在树上,按指示跳过),再整体重生成gen:schema/gen:api-surface/gen:spec-changes/gen:upgrade-guide/gen:docs/gen:skill-refs/gen:skill-docs/gen:strictness-ledger—— 全部 OK,零文本合并、零手改数字。pre-commit 的 os-regen 钩子独立复核:all deferred artifacts are current — marker cleared。兄弟条目断言(全部在):
[RETIRED]标记ui/Theme:animation、ui/Theme:zIndex、ui/Typography:fontSize/fontWeight/letterSpacing/lineHeighttheme-inert-token-scales-removed条目retired in v17处方stack-server.zod.ts6 处ui-notification-action-embed-config-retired台账散文亦双方并存(#5021 的
theme.zod.ts行含其 14 → 6 说明,本单三段去向记录俱在),全树无遗留冲突标记。验证(同步后重跑)
同步前在
3905c00基线上另跑过:check:i18nPASS、lint57 files / 1198 tests、cli69 files / 626 tests。(packages/lint首轮红过一次,是全新 worktree 未构建依赖的老陷阱,按pnpm --filter "PKGNAME^..." build构建依赖后全绿 —— 与本次改动无关。)顺带发现(已另立,未在本 PR 修)
#5280 ——
app元数据表单仍在提供三个已retiredKey()退役的键(sharing/embed/mobileNavigation),填了必然存盘失败;而 #3786 的对账门用key ∈ shape判定,retiredKey()按设计把键留在 shape 里,所以门永远绿。带阳性对照实测。与本单无因果关系(即使什么都不做它也是错的),但正是App.embed这条线索让本 PR 说清了EmbedConfig成为孤儿的原因。🤖 Generated with Claude Code
https://claude.ai/code/session_01ErbEDVAg1No9gdg1pgDAGB