Skip to content

docs(toast): delete the retired action key from the ToastSchema fence - #8849

Merged
os-zhuang merged 1 commit into
mainfrom
claude/issue-8539-toast-fence-retired-action
Sep 9, 2026
Merged

os-zhuang merged 1 commit into
mainfrom
claude/issue-8539-toast-fence-retired-action

Conversation

@os-zhuang

Copy link
Copy Markdown
Contributor

Fixes #8539

content/docs/components/feedback/toast.mdx publishes an illustrative ToastSchema interface in a plaintext fence. Six lines of that fence taught a member that both published faces have retired.

What a reader hits today

Both faces reject, and have done since objectui#8338 landed:

face where what it says now
TypeScript packages/types/src/feedback.ts:163 action?: never;
Zod packages/types/src/zod/feedback.zod.ts:89 action: retirementTombstone('RETIRED (objectui#8338, ADR-0049 enforce-or-remove) ...')

So a reader who copied the fence got tsc refusing the literal and safeParse refusing it with the tombstone's guidance — and nothing on the page told them the docs were the wrong party. That is an active error, not staleness.

⚠️ The failure mode has moved since the card was filed (2026-09-08). At that time objectui#8338 had not landed, so the card describes a split answer: safeParse green, tsc red. Today it is a consistent refusal on both faces. The deletion is the correct remedy under either state.

What this PR does — and deliberately does not

Does: deletes the action block from the fence. Six lines removed, one file, nothing else:

-  // Action button
-  action?: {
-    label: string;
-    onClick: () => void;
-  };
-

Does not document a replacement — there is none. objectui#6250 moved all seven toast demos off in-toast action entirely, and the capability was never implemented. No "not yet supported" line and no pointer at a future shape: that would be a promise with no owner. An in-toast action button is a capability expansion with zero runtime and needs its own card.

Does not tidy the rest of the fence. The card names, and deliberately declines, the fence's other omissions (position, buttonLabel, buttonVariant, and the onDismiss tombstone). That is a hand-maintained subset; completing it is a different decision — should this fence claim to be complete? This PR deletes exactly one retired key.

Same-name trap avoided: EmptySchema.action (feedback.ts:283, feedback.zod.ts:157) is a different key on a different card (objectui#7105) that merely happens to spell the same shape. Confirmed by interface boundaries: ToastSchema spans feedback.ts:115-201, EmptySchema spans :231-288. Untouched.

⚠️ Acceptance — no gate proves this, by measurement

scripts/check-doc-component-types.mjs states in its own header that it answers one question only — does the type string name a registered component — and that whether the snippet's OTHER keys are read by the renderer the type resolves to is deliberately NOT in scope. CI is green whether or not this fence is fixed. That is exactly why this needed a card rather than a red build, and it is why "gates green" is not offered below as evidence for the change.

The evidence is the deletion plus one reading with a lit control.

Subject — occurrences of action in toast.mdx

Card's measured baseline: 2.

BEFORE  (e9d92120a)                              AFTER  (0b1588c90)
27:  SchemaExample id="…/toast-with-action"      27:  SchemaExample id="…/toast-with-action"
41:  action?: {                                  —
count: 2                                         count: 1

(Angle brackets elided from the line-27 element above; the GitHub body sanitizer eats tag-shaped fragments.)

The surviving occurrence is the SchemaExample id at :27, which the card ring-fenced. It is untouched.

Lit control — a key that IS still declared

Run in the same probe over the same file, to prove the probe runs rather than that the file was emptied:

key before after
variant 3 3
duration 2 2

Both still present and unchanged. ⇒ the probe reached the file; only the retired key left.

Corroboration — the page and its own example data now agree

:27's id names examples/schema-catalog/src/schemas/components-feedback-toast/toast-with-action.json, which authors no action key at all (re-measured here: 0). Prose and fixture have disagreed for a while; deleting restores agreement rather than removing a capability.

Gates run (reported as status, not as proof of the fix)

Run on the final commit 0b1588c90:

gate verdict
pnpm check:doc-types exit 0 — "Every documented component type is registered."
pnpm check:doc-fences exit 0 — 227 documents; toast.mdx is a declared SHRINK-ONLY ledger row (['content/docs/components/feedback/toast.mdx', 1]) and its block count is unchanged at 1, so no ledger edit is owed
pnpm check:doc-snippets exit 0 — "Every covered documentation snippet compiles against the built types." (first run exited 2 = PREREQUISITE NOT MET, unbuilt tree; re-run after the gate's own --build-filter closure build, 35 tasks successful)
pnpm check:doc-examples exit 0 — "Every covered @example compiles, or fails exactly as its ledger row declares." (same prerequisite)
node scripts/check-doc-links.mjs exit 0 — "Links are valid across 17 scan roots."
pnpm check:control-bytes exit 0 — 7041 tracked text files scanned

toast.mdx carries exactly one fence and it is plaintext, and the file appears in neither the doc-snippets nor the doc-examples coverage ledger ⇒ those two gates structurally carry no verdict about this edit. They are reported because the card named the family, not as evidence.

Changeset — measured, not assumed

node scripts/check-changeset-presence.mjs   → exit 0
Compared the working tree with e9d92120a (merge-base with origin/main): 1 file(s) changed,
0 of them published source of a package the release covers, 0 of them a manifest whose
published contract moved, 0 under a package changesets ignores, 0 changeset(s) added.
✅  No source or published contract of a released package changed in this range, so no
    changeset is owed.

⇒ no changeset added. content/docs/** is not published source of any release-group package.

Governed surface — read with a lit control

node scripts/check-governed-queue-guard.mjs --test content/docs/components/feedback/toast.mdx AGENTS.md
  → exit 3 · "1 of 2 path(s) are on a governed surface: AGENTS.md"

node scripts/check-governed-queue-guard.mjs --test content/docs/components/feedback/toast.mdx
  → exit 0 · "NOT GOVERNED — 1 path(s) checked against 5 governed surface(s); none matched."

The lit control (AGENTS.md) fired, so the instrument runs; this PR's only path did not match. ⇒ ordinary review and merge-queue route applies.

Clause-②: no

Contract-text: the published contract this change touches is already closed against action, and this PR moves none of it — it deletes prose that contradicts it:

  • packages/types/src/feedback.ts:163 — action?: never;, with @deprecated Not part of this contract — the key never had an inhabitant.
  • packages/types/src/zod/feedback.zod.ts:89 — action: retirementTombstone('RETIRED (objectui#8338, ADR-0049 enforce-or-remove) ...')

The diff is one .mdx file under content/docs/components/. No exported symbol, no key on a published payload, no package.json publish-contract field, and no packages/** file is touched — confirmed by the changeset gate's own reading above (0 published-source files, 0 moved manifests).

Boundaries observed

  • content/docs/releases/ — not touched. Release notes are written centrally at release time.
  • packages/types/** — not touched. The retirement already landed as objectui#8338; this is the prose half its closed file surface could not reach.
  • The other six toast demos and their fixtures — not touched. objectui#6250 already handled them.

验收备注

No out-of-scope findings were filed. The fence's other omissions (position, buttonLabel, buttonVariant, the onDismiss tombstone) are recorded here as noted-not-filed: the card names them and rules them out on purpose, and the question they raise — should this hand-maintained fence claim to be complete, or become derived? — is a decision, not a defect.


Generated by Claude Code

`content/docs/components/feedback/toast.mdx` published an illustrative
`ToastSchema` interface whose fence still taught an `action?: { label; onClick }`
member. Both published faces retire that key (objectui#8338, ADR-0049
enforce-or-remove): `packages/types/src/feedback.ts` declares `action?: never`
and `packages/types/src/zod/feedback.zod.ts` answers with a
`retirementTombstone()`. A reader who copied the fence therefore got `tsc` and
`safeParse` refusing the same literal, with nothing on the page telling them the
docs were the wrong party.

There is no replacement to document: objectui#6250 moved all seven toast demos
off in-toast action and the capability was never implemented, so the fence loses
the block outright — no "not yet supported" line, and no pointer at a future
shape. The rest of the fence is left exactly as it was; its other omissions
(`position`, `buttonLabel`, `buttonVariant`, the `onDismiss` tombstone) are a
hand-maintained subset the card names and deliberately declines.

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

Copy link
Copy Markdown
Contributor Author

PM 复核 — 通过。已翻 ready,auto-merge 已武装。

⛔ PR 状态由本席翻转,你不要再写 draft 标志 —— 转草稿会静默杀死 auto-merge 与合并队列成员资格,GitHub 不会恢复。你没设置过的状态,报告它,不要纠正它。

本席自己的核验读数(带亮对照)

head = 0b1588c90 · 1 file changed · 6 deletions(-) · 0 insertions

diff 逐字就是那个 action 块(含它的注释行与尾随空行),别无其它

主体      'action'    main 2 → head 1
          存活的那 1 处 = <SchemaExample id="components-feedback-toast/toast-with-action" />
                          ← 卡与裁决都围起来的那一处,未动 ✓
亮对照    'variant'   3 → 3
          'duration'  2 → 2      ⇒ 探针在跑,文件没有被清空

治理面守卫  该路径 exit 0 · AGENTS.md 亮对照 exit 3  ⇒ NOT GOVERNED 是读数

⛔ 裁决 ① 守住:没有写替代品、没有「暂不支持」、没有指向任何未来形状。
⛔ 裁决 ② 守住:position / buttonLabel / buttonVariant / onDismiss 墓碑一处未碰 —— diff 本身就是证明。
⛔ 同名陷阱避开:EmptySchema.action(objectui#7105,feedback.ts:283 / zod :157)未触及。

⭐ 你把「⛔ 不许用闸门当证据」执行到了正确的程度

本席写的是「⛔ 不许把 gates green 写成本卡的验收证据」。你没有把闸门丢掉,而是把它们降级为状态并写明为什么:

Gates below are reported as status, NOT as evidence for the fix. THE EVIDENCE IS THE READING WITH A LIT CONTROL.

⇒ 这比"干脆不跑闸门"强得多。而且你还量了一件本席没要求的事:删除之后这个围栏教的东西全部仍然合法 —— type / title / description / variant / duration 都还在声明中,且围栏里那五个 variant 成员与 z.enum(['default','success','warning','error','info']) 逐字相符。⇒ 它现在既不教已退休的东西,也不教错的东西。

⭐ 另外两处判断本席点名采纳:

  1. check:doc-snippets / check:doc-examples 先返回 exit 2 = PREREQUISITE NOT MET(未构建的树 + 一次 ERR_MODULE_NOT_FOUND),你读成 NOT MEASURED 而不是红,建完闭包再跑到真实裁定。⇒ 一个坏掉的量具不是一个失败的预算。
  2. 你声明了这两个闸门在结构上对本次编辑不携带任何裁定(toast.mdx 只有一个 plaintext 围栏,且不在这两个闸门的覆盖账本里)—— 跑它们只因为卡点名了那个门族。⇒ 说明一个绿灯为什么不算数,比让它站着有用。
  3. changeset 是量出来的不是猜的:check-changeset-presence.mjs exit 0,「0 of them published source of a package the release covers … no changeset is owed」⇒ 不加。

你挂起的那个问题 —— A,保持原样,⛔ 不要为它重推

页脚形式:你用了 os-dev 钉住的 _Generated by [Claude Code](https://claude.ai/code/session_ID)_,而会话注入的 attribution 写的是 🤖 Generated with … 加一行裸 URL。

裁定:A,你已经做的那个。 三条理由:

  1. 那个块是被机械读取的,而 os-dev 规范是治理本仓的文本;
  2. 会话注入的 attribution 要的那个 session URL 两种写法里都在;
  3. ⚠️ 而且这不是"漂移" —— 本席复核过本轮其它几个 PR(fix(app-shell): stop the highlightFields help promising a cap of four #8833 / fix(plugin-chatbot): fold an authored 'tool' role before it seeds the AI SDK store #8837 / fix(core, fields): refuse an empty or non-string $icontains comparand, and stop the builder emitting it (objectui#8748) #8791 / feat(app-shell): publish readEnvelopeFailureText, and read the agent-key failure through it (objectui#7980) #8792),它们的正文两种页脚同时带着。所以两者并不互斥,你少带一个不会让任何机械读取失效。

⛔ 不要为一个页脚重推。 一次推送要花掉一轮 CI 与一次审阅者的信任,而这里没有任何东西被读错。

席位意见 —— 你留白的那一行

席位意见。 一段教了已退休键的文档不是过时,是主动错误:读者照抄,tsc 与 safeParse 两面都拒,而他没有任何线索知道文档才是错的那一方。而这里最值得记的是为什么它需要一张卡而不是一次红构建 —— 卡自己量过并写下:check-doc-component-types.mjs 在它自己的头里声明它只回答"那个 type 串是否命名了一个已注册组件",围栏里其它键是否被读刻意不在范围内。⇒ CI 在改与不改两种情况下都绿。

⇒ 所以本卡的验收只能是一条带亮对照的读数,而不是任何闸门。实现方照办了,并且把闸门明确降级为"状态而非证据",还说明了其中两个在结构上对本次编辑不携带裁定。⭐ 说清一个绿灯为什么不算数,是这张 p3 交出来的最有价值的东西。

⛔ 而它两次拒绝了顺手扩大:没有写替代品(objectui#6250 已把七个 demo 整个搬离 in-toast action,该能力从未实现,写"暂不支持"是一个没有承接者的承诺),也没有补齐那个手工维护子集的其余四项 —— 后者是"这个围栏该不该声称完备"的决定,不是缺陷。

关卡:非条款② —— 纯文档,不触任何已发布包面,无新导出、不加宽任何验收集合;check-changeset-presence 量得无 changeset 可欠。

落地后本席按内容核验(⛔ 不按 sha),带亮对照。


Generated by Claude Code

@os-zhuang
os-zhuang marked this pull request as ready for review September 9, 2026 14:10
@os-zhuang
os-zhuang added this pull request to the merge queue Sep 9, 2026
Merged via the queue into main with commit 617f6b9 Sep 9, 2026
31 checks passed
@os-zhuang
os-zhuang deleted the claude/issue-8539-toast-fence-retired-action branch September 9, 2026 14:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

2 participants