You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Commit 7538f27
Browse filesBrowse the repository at this point in the historyBrowse files
fix(spec): the 18.x action-block variant migration entry says element:button spells it danger, not destructive (#27652)
domain:spec#3 · os-support-ai · session_01WGufzjAFu9q3UWTLiMSuk9
<!-- claude-projects-attribution: {"github_login":"os-support-ai"} -->
_Requested by **Yibo Wang** · [project
thread](https://claude.ai/code/project/chan_01BVUyyPie8gHwoPM18iABwB?thread=cmsg_01BVUyyPie8gHwoPM18iABwBKUxGsrA3itzdun1PSZn7o5)_Fixes#27589
Clause-②: no
Metadata-protocol: none
## 维护者速读
- 改了什么:18.x 升级指南里 `destructive` → `danger` 那一条迁移说明,原来说「`element:button`
之类直接画 Button 原件的组件保留 `destructive`」,现在改成:`element:button` 本来就写
`danger`、拒收 `destructive`;只有把 variant 原样转给 Button 原件的
`record:quick_actions` 和 `record:alert` 的 action 还收 `destructive`。
- 为什么改:这句话会在下一个 18.x 发版时固化进升级指南。作者照着它在 `element:button` 上写
`destructive`,保存时就被拒;人和读指南的 AI 都会被教错。
- 风险与回滚:只改文字(迁移条目 `reason`、D2 转换的注释、一个测试的用例名),没有任何
schema、取值或转换行为变化;回滚即还原本 PR。
-
先看:`packages/spec/src/migrations/entries/semantic/18.ui-page-action-block-variant-destructive-refused.ts`(改的那句)、`packages/spec/src/conversions/page-action-block-variant-destructive-to-danger.test.ts`(新
pin,句子与三处 schema
实测绑定)、`.changeset/27589-action-block-variant-entry-element-button.md`(同版本
changelog 的更正段)。
- 两分钟验证:`pnpm --filter @objectstack/spec exec vitest run
src/conversions/page-action-block-variant-destructive-to-danger.test.ts`,应见
41 个用例全绿;把条目文件换回 `origin/main` 的版本再跑,新增的 3 个用例转红。
- 需要你做的:无,席位落地。
## What changes
**Before** (`origin/main` `178b5238`), the D3 entry
`ui-page-action-block-variant-destructive-refused`, `reason`, L19–L20:
> The blocks now take `danger` and refuse `destructive` with the rename.
Other components that draw the Button primitive directly
(`element:button` and the like) keep `destructive`, the primitive's own
word, and are not touched.
**After:**
> The blocks now take `danger` and refuse `destructive` with the rename.
`element:button` already spells it `danger`
(`ElementButtonPropsSchema.variant`) and refuses `destructive`, so it is
not touched. `destructive` is the React Button primitive's own word; the
two record blocks that forward a variant to that primitive unchanged,
`record:quick_actions` and a `record:alert` action, still take it and
are not touched either.
Measured on `origin/main`:
- `ElementButtonPropsSchema.variant` (`ui/component.zod.ts`) is
`z.enum(['primary', 'secondary', 'danger', 'ghost', 'link'])` on a
strict object: `danger` parses, `destructive` is refused.
- **The card's wanted wording "no metadata block accepts it" does not
hold**, so this PR does not say it. Two record rows still take the
primitive's vocabulary on purpose: `RecordQuickActionsProps.variant` and
`RecordAlertActionSchema.variant` are both `z.enum(['default',
'destructive', 'outline', 'secondary', 'ghost', 'link'])`, described as
"the Button primitive's own vocabulary". The D2 conversion does not
visit either type. The corrected sentence names them instead, and the
pin asserts both accept `destructive`.
The upgrade guide is generated, not committed
(`content/docs/protocol-upgrade/` is git-ignored; the docs build and the
release lane run `build-upgrade-guide.ts`). Regenerated locally from
this head with `--out` and `--docs`: the protocol 18 page prints the new
sentence, and `` `element:button` and the like `` has 0 hits in either
output (1 hit each on `origin/main`).
Copies of the same claim, searched in `packages/spec`, `content/docs/**`
and `skills/**`:
| Where | Governed | Change |
|:---|:---|:---|
| `packages/spec/src/conversions/registry.ts`, the D2 conversion's
docblock ("`destructive` stays the Button primitive's word on
`element:button` and the other primitive-backed components") | no |
corrected to the same facts |
| `packages/spec/src/conversions/registry.ts`, fixture comment "The
Button primitive's own word on another component" | no | reworded to
"Another component type: not this entry's, whatever it holds (its own
row refuses `destructive`)"; the fixture value is unchanged (prose only)
|
|
`packages/spec/src/conversions/page-action-block-variant-destructive-to-danger.test.ts`,
header bullet and one control label | no | reworded; the control case is
unchanged |
| `.changeset/26779-action-block-variant-danger.md` ("`element:button`,
toasts, alerts, badges and the like keep `destructive`") | yes
(`check-empty-changeset` refuses edits to a changeset the base carries)
| not edited; this PR's changeset carries a "Supersedes, in the same
release" paragraph |
| `content/docs/**`, `skills/**` | | 0 hits |
The card body of #27243, which quotes the sentence, is the seat's to
correct and is not touched here.
## Tests
`page-action-block-variant-destructive-to-danger.test.ts` gains `the D3
entry says what the untouched components accept (#27589)`, which reads
the entry from `MIGRATIONS_BY_MAJOR[18]` (the generated chain
`build-upgrade-guide.ts` prints) and pins:
- `element:button` accepts `danger` and refuses `destructive`, and the
`reason` carries the corrected `element:button` sentence;
- `record:quick_actions` and a `record:alert` action accept
`destructive`, and the `reason` carries the sentence naming them;
- none of `reason`, `replacement`, `acceptanceCriteria` matches
``/keeps? `destructive`/`` or contains "`element:button` and the like".
One-shot negative run: with the entry file checked out from
`origin/main` and the registry regenerated, the three new cases go red
(`Tests 3 failed | 38 passed (41)`, lock VERDICT command-exit 1);
restored with `git checkout HEAD --`, blob hash matched HEAD.
All on head `00bd2dad`, under `os-verify-lock`:
<details><summary>spec local suite + typecheck, spec repo
suite</summary>
- `pnpm --filter @objectstack/spec test && pnpm --filter
@objectstack/spec typecheck`: `Test Files 751 passed | 1 skipped (752)`,
`Tests 22345 passed | 1 skipped | 1 todo (22347)`;
`check:test-typecheck: OK`; VERDICT command-exit 0.
- `pnpm --filter @objectstack/spec test:repo`: `Test Files 86 passed
(86)`, `Tests 1433 passed (1433)`; VERDICT command-exit 0.
</details>
No dogfood run: no `!` in the title and no `(narrowing)` arm.
## Acceptance notes
- The conversion's fixture keeps an `element:button` with `variant:
'destructive'` as its "another component type" control. That value is
one `element:button`'s own row refuses; it stays because the binding is
prose only and the control is still true (the conversion never visits
the type). Noted, not changed.
- The 26779 changeset's list also names "toasts, alerts, badges"; those
were not measured here and are left as stated.
## Verification
`node scripts/pm/dispatch-gates.mjs --commands --repo
objectstack-ai/objectstack` derived 81 families on `00bd2dad` (4 paths
vs merge base `178b5238`).
<details><summary>81 derived gates: 81 exit 0</summary>
- First serial pass: 70 exit 0, 11 exit 3 (built-output prerequisites:
the spec `dist`, and the pinned fixture commit for
`check-plugin-teardown-shape --self-test` on the shallow clone).
- After `turbo run build --concurrency=2
--filter='@objectstack/lint...'` (VERDICT command-exit 0) and `git fetch
origin 621a487`, the 11 were rerun: all exit 0 (`check:api-surface`,
`check:browser-reachable-entries`, `check:dual-source-exports`,
`check:entry-nameability`, `check:exported-any`, `check:dts-closure`,
`check:dual-build-cjs-loads`, `check:lean-entry-closure`,
`check:sourcemap-no-sources-content`, lint
`check:doc-formula-expressions`, `check-plugin-teardown-shape
--self-test`).
- `dispatch-gates --ran`: "81 derived famil(ies) accounted for — 81 run,
0 NOT-MEASURED".
</details>
`check-changeset-no-major` with this body as the event: exit 0, "✓ LEVEL
AXIS: this PR declares clause-② `no` and metadata-protocol `none`, and
it introduces no changeset entry graded `minor` or above".
CI families are read from this PR's check-runs.
---
_Generated by [Claude
Code](https://claude.ai/code/session_01WGufzjAFu9q3UWTLiMSuk9)_
🤖 Generated with [Claude Code](https://claude.com/claude-code)
https://claude.ai/code/session_01WGufzjAFu9q3UWTLiMSuk9
Co-authored-by: Claude <noreply@anthropic.com>
fix(spec): the 18.x migration entry for the action-block `destructive` → `danger` rename no longer says `element:button` keeps `destructive` (#27589)
6
+
7
+
Clause-②: no
8
+
Metadata-protocol: none
9
+
10
+
The D3 entry `ui-page-action-block-variant-destructive-refused` said that components drawing the Button primitive directly, "`element:button` and the like", keep `destructive`. That is false for `element:button`: `ElementButtonPropsSchema.variant` is `primary | secondary | danger | ghost | link`, so it already spells the arm `danger` and refuses `destructive` at the metadata save door and in `os validate`. An author who followed the sentence wrote a page the save door rejects. The entry's `reason`, which the upgrade guide prints, now says so, and names the two record blocks that do still take the React Button primitive's `destructive` because they forward a variant to it unchanged: `record:quick_actions` (`variant`) and a `record:alert` action (`action.variant`). The same correction is made to the docblock of the D2 conversion `page-action-block-variant-destructive-to-danger`. No schema, value or conversion behaviour changes.
11
+
12
+
**Supersedes, in the same release.** The `@objectstack/spec` 18 note for the rename says "Other components that draw the Button primitive directly (`element:button`, toasts, alerts, badges and the like) keep `destructive`". Read `element:button` out of that list: it spells the arm `danger`, as the action blocks now do.
0 commit comments