Repository navigation
fix(spec): the 18.x action-block variant migration entry says element:button spells it danger, not destructive - #27652
Conversation
…:button keeps destructive element:button spells the destructive arm `danger` and refuses `destructive`; only the record blocks that forward a variant to the Button primitive unchanged (record:quick_actions, a record:alert action) still take the primitive's `destructive`. Corrects the D3 entry's reason (printed by the upgrade guide), the D2 conversion's docblock and the conversion test's wording, and pins the corrected sentence against the rows it describes. Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WGufzjAFu9q3UWTLiMSuk9
📓 Docs Drift CheckNothing in this diff resolved to a documentable surface (no symbol, route or SDK anchor derived from 1 changed package(s)), so this run has no opinion about the docs. What this run could not see
Coarse fallback — 167 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): |
|
triage#1 · os-sales · session_01L6bhgV4fMGJHSdSdx3u9mK Contract-review-claim: session_01L6bhgV4fMGJHSdSdx3u9mK · head 00bd2da · 2026-10-29T17:02Z Generated by Claude Code |
|
triage#1 · os-sales · session_01L6bhgV4fMGJHSdSdx3u9mK Contract reviewServed-tier: Inputs read: card #27589 (body, triage 6500456009, claim 6500945752, seat-4 note 6501262533, os-dev-report 6502290069), PR #27652 (body, 4-file list, net diff vs merge base ① Derived judgments
② Semver level
③ Boundary flags
④ Design judgment
Gate for the rule (read, not reviewed): Check-runs on the head: 54 runs, every completed conclusion Findings: 0 must-fix, 1 should-fix (the unpinned count "two", non-blocking). Implemented-by: VERDICT: PASS Generated by Claude Code |
|
domain:spec#3 · os-support-ai · session_01WGufzgbJhFoXYsLSe5WSPP 维护者速读 (席位终稿)
席位意见:接受。分诊契约复核 PASS(6503382064,就在当前 head 上),没有 must-fix。唯一的 should-fix(「两个」是数量断言,pin 没绑定)不阻塞,记为偏差。 席位核对 · ACCEPT ·
|
domain:spec#3 · os-support-ai · session_01WGufzjAFu9q3UWTLiMSuk9
Requested by Yibo Wang · project thread
Fixes #27589
Clause-②: no
Metadata-protocol: none
维护者速读
destructive→danger那一条迁移说明,原来说「element:button之类直接画 Button 原件的组件保留destructive」,现在改成:element:button本来就写danger、拒收destructive;只有把 variant 原样转给 Button 原件的record:quick_actions和record:alert的 action 还收destructive。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/main178b5238), the D3 entryui-page-action-block-variant-destructive-refused,reason, L19–L20:After:
Measured on
origin/main:ElementButtonPropsSchema.variant(ui/component.zod.ts) isz.enum(['primary', 'secondary', 'danger', 'ghost', 'link'])on a strict object:dangerparses,destructiveis refused.RecordQuickActionsProps.variantandRecordAlertActionSchema.variantare bothz.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 acceptdestructive.The upgrade guide is generated, not committed (
content/docs/protocol-upgrade/is git-ignored; the docs build and the release lane runbuild-upgrade-guide.ts). Regenerated locally from this head with--outand--docs: the protocol 18 page prints the new sentence, and`element:button` and the likehas 0 hits in either output (1 hit each onorigin/main).Copies of the same claim, searched in
packages/spec,content/docs/**andskills/**:packages/spec/src/conversions/registry.ts, the D2 conversion's docblock ("destructivestays the Button primitive's word onelement:buttonand the other primitive-backed components")packages/spec/src/conversions/registry.ts, fixture comment "The Button primitive's own word on another component"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.changeset/26779-action-block-variant-danger.md("element:button, toasts, alerts, badges and the like keepdestructive")check-empty-changesetrefuses edits to a changeset the base carries)content/docs/**,skills/**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.tsgainsthe D3 entry says what the untouched components accept (#27589), which reads the entry fromMIGRATIONS_BY_MAJOR[18](the generated chainbuild-upgrade-guide.tsprints) and pins:element:buttonacceptsdangerand refusesdestructive, and thereasoncarries the correctedelement:buttonsentence;record:quick_actionsand arecord:alertaction acceptdestructive, and thereasoncarries the sentence naming them;reason,replacement,acceptanceCriteriamatches/keeps? `destructive`/or contains "element:buttonand the like".One-shot negative run: with the entry file checked out from
origin/mainand the registry regenerated, the three new cases go red (Tests 3 failed | 38 passed (41), lock VERDICT command-exit 1); restored withgit checkout HEAD --, blob hash matched HEAD.All on head
00bd2dad, underos-verify-lock:spec local suite + typecheck, spec repo suite
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.No dogfood run: no
!in the title and no(narrowing)arm.Acceptance notes
element:buttonwithvariant: 'destructive'as its "another component type" control. That value is oneelement: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.Verification
node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstackderived 81 families on00bd2dad(4 paths vs merge base178b5238).81 derived gates: 81 exit 0
dist, and the pinned fixture commit forcheck-plugin-teardown-shape --self-teston the shallow clone).turbo run build --concurrency=2 --filter='@objectstack/lint...'(VERDICT command-exit 0) andgit fetch origin 621a4876, 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, lintcheck:doc-formula-expressions,check-plugin-teardown-shape --self-test).dispatch-gates --ran: "81 derived famil(ies) accounted for — 81 run, 0 NOT-MEASURED".check-changeset-no-majorwith this body as the event: exit 0, "✓ LEVEL AXIS: this PR declares clause-②noand metadata-protocolnone, and it introduces no changeset entry gradedminoror above".CI families are read from this PR's check-runs.
Generated by Claude Code
🤖 Generated with Claude Code
https://claude.ai/code/session_01WGufzjAFu9q3UWTLiMSuk9