Skip to content

Commit 48203ff

Browse files
authored
spec(ui): retire ObjectKanbanProps.quickAdd from object-kanban — tombstone, D2 conversion and baselines (#17792)
Fixes #17260 Executes the objectui#8285 director-seat ruling (comment 5583979207, decision batch #91, 2026-09-08, standing maintainer delegation) — ruled **option B**: `quickAdd` is retired from the `object-kanban` board and stays only on the `kanban-ui` block, where a React host can supply the runtime function the control needs. This PR is the tombstone half that ruling assigns to this repo. A vs B is not re-opened here. - **Clause-②: yes** — this PR narrows a published accept set: `ObjectKanbanProps.quickAdd` is retired from `object-kanban`. ## The premise, re-measured rather than relayed The card's body said an author writing `quickAdd: true` got "nothing, with no diagnostic". The filer corrected that themselves, and the correction is what holds — re-measured here at the objectui sha this repo pins (`.objectui-sha` = `53ded82bf`), not at that checkout's HEAD: | probe at the pinned sha | reading | control (same instrument, same file) | |:--|--:|:--| | `onQuickAdd` in `plugin-kanban/src/ObjectKanban.tsx` | **0** | `onCardClick` — **6** | | `quickAdd` in the same file | **0** | `objectName` — **38** | | `object-kanban` registration `inputs` (`index.tsx:421-431`) | `objectName`, `columns` — `quickAdd` absent | `objectName` present | The board **forwards** the key — `ObjectKanban.tsx:931` spreads the authored bag into `KanbanRenderer`, which passes `quickAdd={schema.quickAdd}` alongside `onQuickAdd={schema.onQuickAdd}` (`index.tsx:196`) — but `KanbanImpl` gates the affordance on **both** (`:355`, `:368`), and `onQuickAdd` is a host-supplied function JSON cannot carry and no producer puts on an `object-kanban` node. So the gate was permanently false: accepted-and-dropped, exactly as the card classifies it. Two readings the card's numbers came from could **not** be reproduced at the pin, and are reported as such rather than passed on: `OBJECT_KANBAN_INPUTS` (the 13-key constant) and the `inert-quick-add` interim diagnostic do not exist at `53ded82bf` at all — both are later objectui work. `OBJECT_KANBAN_INPUTS` does resolve at that checkout's HEAD (control lit, 3 files), and the registry-spec ledger records the key verbatim there as `ESCALATED (object-kanban.quickAdd — measured NOT honoured)`. The pin's own equivalent reading is the `inputs` row in the table above, and it says the same thing. ## The retirement kit | carrier | what changed | |:--|:--| | `ObjectKanbanPropsSchema.quickAdd` | `retiredKey()` tombstone — `tsc` types it `never`, and a value reaching the parse raises the prescription instead of a bare unknown-key verdict | | the schema's docblock | it listed `quickAdd` among the keys reached "via the forwarded schema" — true about the FORWARD, false about the READ, which is how the key kept re-authorizing itself. Corrected in the same stroke | | `src/conversions/registry.ts` | D2 conversion `object-kanban-quick-add-removed` — a pure lossless delete (the key never had an effect to preserve), scoped by component `type` so the LIVE `kanban-ui` spelling stays out of its reach | | `migrations/entries/retired-keys/18.ui__ObjectKanbanProps__quickAdd.ts` | `RETIRED_KEYS_BY_MAJOR[18]` entry `ui/ObjectKanbanProps:quickAdd`, plus the D3 chain-step wiring and rationale | | `authorable-surface/ui.json` | the row becomes `ui/ObjectKanbanProps:quickAdd [RETIRED]` | | `content/docs/references/ui/component.mdx` | regenerated — the row now prints the prescription | | `src/ui/component.test.ts` | four pins (see the ablation below) | | `.changeset/17260-object-kanban-quick-add-retired.md` | `minor`, `adr-0087: registered object-kanban-quick-add-removed` | `packages/spec/src/ui/view.zod.ts` is untouched — it is another round's declared face this batch. The `kanban-ui` block's `quickAdd` is untouched by design: it is not a component type this spec declares at all, which is why the conversion is scoped by `type` rather than by key name. ## Liveness — measured, with a lit control Zero stored or example stacks in this repo carry `quickAdd`, because **no `object-kanban` component is authored anywhere under `examples/` or `apps/`**. The zero is a reading, not a dark probe: the same instrument over the same corpora returns `object-grid` 3 and `object-metric` 8. Repo-wide, `quickAdd` occurred in exactly four places before this PR — the schema key, the docblock sentence, the ratchet row and the generated docs row — i.e. only the carriers being retired here. Out-of-repo authors are unknown and unknowable from here, which is what the D2 conversion and the prescription exist for. ## Verification | run | result | |:--|:--| | `pnpm --filter @objectstack/spec build` | `VERDICT command-exit 0` | | `pnpm --filter @objectstack/spec test` | `VERDICT command-exit 0` — Test Files 473 passed (473), Tests 13443 passed (13443) | | `pnpm --filter @objectstack/spec typecheck` | exit 0 | | `pnpm --filter @objectstack/spec check:generated` | 15/15 artifacts current (one lap: `gen:migration-registry`, then the build's `gen:schema`, then `gen:docs`) | | `pnpm --filter @objectstack/spec check:migration-registry` | `✓ src/migrations/registry.ts is current (202 semantic, 168 retired-key, 178 retired-def)` | | `node scripts/check-adr-0087-registration.mjs --base origin/main` | `✓ 1 declared-breaking changeset(s), each carrying an ADR-0087 disposition` — `registered object-kanban-quick-add-removed (new here)` | | `node scripts/check-changeset-no-major.mjs --base origin/main` | `✓ This diff introduces no major bump` | | `pnpm check:nul-bytes` | OK — 8453 text files scanned | The registry was regenerated by the repo's own generator (`pnpm --filter @objectstack/spec gen:migration-registry` → `✓ wrote src/migrations/registry.ts`), never by hand; the first build before that run failed loudly with `1 key(s) were tombstoned with no registered retirement`, which is the gate doing its job. **Ablation — the pins can fail.** On `HEAD`: 4 passed. With the tombstone mutated back to a live `z.boolean().optional()` in source (mutation proven on disk: tombstone-call count 1 → 0, injected marker 1, blob hash `106299e7…` → `e657a7e3…`), the same run goes **2 failed / 2 passed**: the two refusal pins are the discriminating half. Restored from `HEAD` and proven byte-identical (blob back to `106299e7…`, `git diff HEAD` empty). Reported honestly: the `not.toHaveProperty` pin does **not** flip under that mutation — an optional key absent from the input is not materialized either way — so it guards the strip direction and not the refusal. ## Changeset — measured, not assumed Owed, at `minor`. - **Subject**: the tombstone's prescription text reaches the published `dist` — 2 hits, `dist/ui/index.js` and `dist/ui/index.mjs`, both inside `packages/spec`'s `files[]`. - **Positive control**: a pre-existing shipped describe from the same schema — 2 hits, same files. - **Negative control**: text that exists only in `component.test.ts` — **0** hits in `dist`. Level is `minor`, not `major`: `scripts/check-changeset-no-major.mjs` forbids `major` during the launch window (lockstep versioning would promote ~70 packages), and the sibling retirement one entry over (`ui/ObjectGridProps:defaultSort`, #11805) is registered under protocol 18 on the same reading. `api-surface/` is unchanged and correctly so — it ratchets export existence, and `ObjectKanbanProps` still exists, one key narrower. ## Not flipping this ready An at-tier contract-review verdict is owed on the head that lands; `needs:contract-review` rides this PR. Draft, not enqueued. Co-Authored-By: Claude <noreply@anthropic.com> 🤖 Generated with [Claude Code](https://claude.com/claude-code) --- _Generated by [Claude Code](https://claude.ai/code/session_01MkQhmuuJAVDjmeWNixwDDH)_ --- _Generated by [Claude Code](https://claude.ai/code)_
1 parent 2070a1d commit 48203ff

8 files changed

Lines changed: 439 additions & 6 deletions

File tree

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
---
2+
"@objectstack/spec": minor
3+
---
4+
5+
feat(spec)!: retire `ObjectKanbanProps.quickAdd` — the `object-kanban` board forwarded it and nothing ever read it (ADR-0049)
6+
7+
<!-- adr-0087: registered object-kanban-quick-add-removed -->
8+
9+
**BREAKING** — `quickAdd` is retired from the `object-kanban` component props. Executes the
10+
objectui#8285 director-seat ruling (decision batch #91, 2026-09-08, standing maintainer
11+
delegation), ruled **option B**: the key leaves the board and stays only on the `kanban-ui`
12+
block, where a React host can supply the runtime function the control needs.
13+
14+
| | before | after |
15+
|:--|:--|:--|
16+
| `object-kanban` | `quickAdd: true` parsed clean and did nothing | refused by the tombstone, with the prescription |
17+
| `kanban-ui` (objectui block) | the control works when the host passes `onQuickAdd` | **unchanged** |
18+
19+
**What was actually wrong.** Measured at the `.objectui-sha` pin this repo builds against
20+
(`53ded82bf`): the board FORWARDS the key — `ObjectKanban.tsx:931` spreads the authored bag
21+
into `KanbanRenderer`, which passes `quickAdd={schema.quickAdd}` alongside
22+
`onQuickAdd={schema.onQuickAdd}` (`plugin-kanban/src/index.tsx:196`) — but `KanbanImpl`
23+
gates the affordance on **both** (`:355`, `:368`), and `onQuickAdd` is a host-supplied
24+
FUNCTION that JSON cannot carry and that no producer puts on an `object-kanban` node.
25+
`ObjectKanban.tsx` names neither half of the pair (0 occurrences each, against 6 for the
26+
sibling `onCardClick` in the same file), so the gate was permanently false.
27+
28+
**And the drop was not silent, which is what made it worse than silence.** objectui's html
29+
tier reported the published key as `unknown-prop` — the same diagnostic a typo gets — and
30+
its registry↔spec ledger records it as `ESCALATED (object-kanban.quickAdd — measured NOT
31+
honoured)`. An author following the published contract met a tool that contradicted it, with
32+
nothing in either message to say which side was wrong. The tombstone collapses both halves
33+
onto one answer.
34+
35+
## What to write instead
36+
37+
Nothing, on this board: there is no per-column quick-add affordance on `object-kanban` and
38+
there never was one. Delete the key.
39+
40+
```ts
41+
// before — parsed clean, rendered nothing
42+
{ type: 'object-kanban', properties: { objectName: 'crm_task', groupBy: 'status', quickAdd: true } }
43+
// after
44+
{ type: 'object-kanban', properties: { objectName: 'crm_task', groupBy: 'status' } }
45+
```
46+
47+
The control itself is not withdrawn from the platform. It stays on the `kanban-ui` block,
48+
which a React host renders directly and can hand the `onQuickAdd` slot to — that is what the
49+
ruling preserved deliberately.
50+
51+
Existing sources: `os migrate meta --from 17` lists the mechanical edits; apply them by hand.
52+
53+
The retirement kit:
54+
55+
- a `retiredKey()` tombstone on `ObjectKanbanPropsSchema` — `tsc` types the key `never`, and
56+
a value reaching the parse raises the prescription rather than a bare unknown-key verdict
57+
- the D2 conversion `object-kanban-quick-add-removed` (`RETIRED_KEYS_BY_MAJOR[18]` entry
58+
`ui/ObjectKanbanProps:quickAdd`, wired into the protocol-18 chain step) — a **pure lossless
59+
delete**, since the key never had an effect to preserve, scoped by component `type` so the
60+
live `kanban-ui` spelling stays out of its reach
61+
- the `authorable-surface/ui.json` row becomes `ui/ObjectKanbanProps:quickAdd [RETIRED]`, and
62+
the generated reference page prints the prescription in place of the old describe
63+
- the schema docblock's read-point list is corrected in the same stroke: it named `quickAdd`
64+
among the keys reached "via the forwarded schema", a sentence true about the FORWARD and
65+
false about the READ — which is how the key kept re-authorizing itself
66+
- pin tests (`ui/component.test.ts`): the refusal carries the prescription; a clean parse does
67+
not materialize the key; and the control pair separating the tombstone's answer from the
68+
strict unknown-key arm's, so a shape that had merely DROPPED the key could not pass
69+
- no liveness-ledger row (component props are not an enrolled ledger type) and no form or
70+
i18n edit: zero `object-kanban` components are authored anywhere under `examples/` or
71+
`apps/` (control: `object-grid` 3, `object-metric` 8 in the same corpora, same instrument)
72+
- `api-surface/` is unchanged, correctly: it ratchets export existence, and no export leaves —
73+
`ObjectKanbanProps` still exists, one key narrower

‎content/docs/references/ui/component.mdx‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -502,7 +502,7 @@ Sort field and direction pair
502502
| **cardFields** | `string[]` | optional | Fields rendered on each card |
503503
| **swimlaneField** | `string` | optional | Field for horizontal swimlanes (in addition to columns) |
504504
| **grouping** | `any` | optional | View grouping config; its first field is the swimlane fallback |
505-
| **quickAdd** | `boolean` | optional | Show the per-column quick-add affordance |
505+
| **quickAdd** | `never` | optional | [REMOVED] `object-kanban` property `quickAdd` was removed in @objectstack/spec 17 (ADR-0049) — the board forwarded it, but the per-column affordance is gated on both `quickAdd` and `onQuickAdd`, and `onQuickAdd` is a host-supplied function JSON cannot carry and no producer ever put on an `object-kanban` node, so authoring it was a parse-clean no-op. Delete the key. The quick-add control is unchanged on the `kanban-ui` block, where a React host supplies the `onQuickAdd` slot the control needs. Run `os migrate meta --from 17` to list the mechanical edits for existing sources; apply them by hand. |
506506
| **coverImageField** | `string` | optional | Image field rendered as the card cover |
507507
| **conditionalFormatting** | `any` | optional | Card conditional formatting rules |
508508

‎packages/spec/authorable-surface/ui.json‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -780,7 +780,7 @@
780780
"ui/ObjectKanbanProps:grouping",
781781
"ui/ObjectKanbanProps:limit",
782782
"ui/ObjectKanbanProps:objectName",
783-
"ui/ObjectKanbanProps:quickAdd",
783+
"ui/ObjectKanbanProps:quickAdd [RETIRED]",
784784
"ui/ObjectKanbanProps:swimlaneField",
785785
"ui/ObjectKanbanProps:titleField",
786786
"ui/ObjectListView:addRecord",

‎packages/spec/src/conversions/registry.ts‎

Lines changed: 184 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8010,6 +8010,189 @@ const objectGridDefaultSortRemoved: MetadataConversion = {
80108010
},
80118011
};
80128012

8013+
/**
8014+
* `object-kanban`'s per-column quick-add switch leaves the contract (protocol
8015+
* 18, #17260, ADR-0049 enforce-or-remove; the spec half of the objectui#8285
8016+
* director-seat ruling, decision batch #91, 2026-09-08 — ruled option B,
8017+
* `quickAdd` is retired from the board and stays only on the `kanban-ui`
8018+
* block, where a React host can supply the runtime function the control
8019+
* needs).
8020+
*
8021+
* **A pure lossless delete.** The key never had an effect to preserve.
8022+
* Measured at the `.objectui-sha` pin (`53ded82bf`): the board FORWARDS it —
8023+
* `ObjectKanban.tsx:931` spreads the authored bag into `KanbanRenderer`,
8024+
* which passes `quickAdd={schema.quickAdd}` alongside
8025+
* `onQuickAdd={schema.onQuickAdd}` (`plugin-kanban/src/index.tsx:196`) — but
8026+
* `KanbanImpl` gates the affordance on BOTH (`:355`, `:368`), and
8027+
* `onQuickAdd` is a host-supplied FUNCTION that JSON cannot carry and that no
8028+
* producer puts on an `object-kanban` node (`ObjectKanban.tsx` names neither
8029+
* half of the pair: 0 occurrences each, against 6 for the sibling
8030+
* `onCardClick` in the same file). So the gate was permanently false and
8031+
* deleting the key preserves observed behaviour exactly.
8032+
*
8033+
* ⚠️ Scoped by component `type`, never by key name. `quickAdd` is LIVE on the
8034+
* `kanban-ui` block — the same renderer chain, reached by a React host that
8035+
* hands in `onQuickAdd` — and the ruling keeps it there deliberately. That
8036+
* block is objectui-side and is not a component type this spec declares, so no
8037+
* stack this walk reaches can carry it; the type scoping is what keeps the
8038+
* strip from generalising into a name-keyed one if it ever is declared. The
8039+
* fixture's non-carrier control is an `object-grid` authoring the same key
8040+
* name.
8041+
*
8042+
* The neighbouring forwarded keys `coverImageField` and `conditionalFormatting`
8043+
* are LIVE and survive untouched (both are read on this very path, by
8044+
* `KanbanRenderer` / `bucketCardsIntoColumns`).
8045+
*
8046+
* Zero authored occurrences in this repo's corpora — no `object-kanban`
8047+
* component is authored anywhere under `examples/` or `apps/` at all (control:
8048+
* `object-grid` 3, `object-metric` 8 in the same corpora, same instrument) —
8049+
* so this entry exists for stored `sys_metadata` rows and for authors outside
8050+
* the repo, which the filing seat explicitly could not measure.
8051+
*/
8052+
const objectKanbanQuickAddRemoved: MetadataConversion = {
8053+
id: 'object-kanban-quick-add-removed',
8054+
toMajor: 18,
8055+
retiredFromLoadPath: true,
8056+
surface: 'page.component.object-kanban.quickAdd',
8057+
summary:
8058+
"object-kanban component prop 'quickAdd' removed (#17260 — the affordance is gated on a "
8059+
+ "host-supplied 'onQuickAdd' function no producer puts on an object-kanban node, so the key "
8060+
+ "was accepted and dropped; the quick-add control stays on the React-host 'kanban-ui' block)",
8061+
apply(stack, emit) {
8062+
return mapPageComponents(stack, (component, path) => {
8063+
if (component.type !== 'object-kanban') return component;
8064+
const properties = component.properties;
8065+
if (!isDict(properties) || !('quickAdd' in properties)) return component;
8066+
const stripped = stripKeys(properties, ['quickAdd'], emit, `${path}.properties`);
8067+
return { ...component, properties: stripped };
8068+
});
8069+
},
8070+
fixture: {
8071+
before: {
8072+
pages: [
8073+
{
8074+
name: 'delivery_board',
8075+
regions: [
8076+
{
8077+
name: 'main',
8078+
components: [
8079+
// The carrier: an `object-kanban` authoring the retired key.
8080+
{
8081+
type: 'object-kanban',
8082+
id: 'k1',
8083+
properties: { objectName: 'crm_task', groupBy: 'status', quickAdd: true },
8084+
},
8085+
// ⚠️ The same key name on a component that is NOT an
8086+
// `object-kanban` — not this entry's key. Untouched: the strip
8087+
// is scoped by component type, never by key name, which is what
8088+
// keeps the LIVE `kanban-ui` spelling out of its reach.
8089+
{
8090+
type: 'object-grid',
8091+
id: 'g1',
8092+
properties: { objectName: 'crm_task', quickAdd: true },
8093+
},
8094+
// A board WITHOUT the key rides through untouched — the strip
8095+
// dispatches on key presence and the copy-on-write contract
8096+
// keeps the reference.
8097+
{
8098+
type: 'object-kanban',
8099+
id: 'k3',
8100+
properties: { objectName: 'crm_task', cardFields: ['title'] },
8101+
},
8102+
// The nested position (#6775's lesson): a board inside a
8103+
// card's `children` is still a component.
8104+
{
8105+
type: 'page:card',
8106+
id: 'c1',
8107+
properties: {
8108+
children: [
8109+
{
8110+
type: 'object-kanban',
8111+
id: 'k4',
8112+
properties: { objectName: 'crm_lead', groupBy: 'stage', quickAdd: false },
8113+
},
8114+
],
8115+
},
8116+
},
8117+
],
8118+
},
8119+
],
8120+
},
8121+
// The named-slot shape (#6776): a board authored into a slotted page.
8122+
{
8123+
name: 'delivery_board_detail',
8124+
kind: 'slotted',
8125+
regions: [],
8126+
slots: {
8127+
details: {
8128+
type: 'object-kanban',
8129+
id: 'k5',
8130+
properties: { objectName: 'crm_task', groupBy: 'status', quickAdd: true },
8131+
},
8132+
},
8133+
},
8134+
],
8135+
},
8136+
after: {
8137+
pages: [
8138+
{
8139+
name: 'delivery_board',
8140+
regions: [
8141+
{
8142+
name: 'main',
8143+
components: [
8144+
{
8145+
type: 'object-kanban',
8146+
id: 'k1',
8147+
properties: { objectName: 'crm_task', groupBy: 'status' },
8148+
},
8149+
{
8150+
type: 'object-grid',
8151+
id: 'g1',
8152+
properties: { objectName: 'crm_task', quickAdd: true },
8153+
},
8154+
{
8155+
type: 'object-kanban',
8156+
id: 'k3',
8157+
properties: { objectName: 'crm_task', cardFields: ['title'] },
8158+
},
8159+
{
8160+
type: 'page:card',
8161+
id: 'c1',
8162+
properties: {
8163+
children: [
8164+
{
8165+
type: 'object-kanban',
8166+
id: 'k4',
8167+
properties: { objectName: 'crm_lead', groupBy: 'stage' },
8168+
},
8169+
],
8170+
},
8171+
},
8172+
],
8173+
},
8174+
],
8175+
},
8176+
{
8177+
name: 'delivery_board_detail',
8178+
kind: 'slotted',
8179+
regions: [],
8180+
slots: {
8181+
details: {
8182+
type: 'object-kanban',
8183+
id: 'k5',
8184+
properties: { objectName: 'crm_task', groupBy: 'status' },
8185+
},
8186+
},
8187+
},
8188+
],
8189+
},
8190+
// Three notices: the region-level board, the nested one and the slotted
8191+
// one. The `object-grid` sibling and the board without the key emit none.
8192+
expectedNotices: 3,
8193+
},
8194+
};
8195+
80138196
/**
80148197
* Object-permission lifecycle bits `allowRestore` / `allowPurge` removed
80158198
* (protocol 18, #12497 — ADR-0049 enforce-or-remove, maintainer ruling
@@ -9170,6 +9353,7 @@ export const CONVERSIONS_BY_MAJOR: Readonly<Record<number, readonly MetadataConv
91709353
translationComponentSubmitLabelRemoved,
91719354
pageComponentResponsiveRemoved,
91729355
objectGridDefaultSortRemoved,
9356+
objectKanbanQuickAddRemoved,
91739357
permissionAllowRestorePurgeRemoved,
91749358
formViewOptionDefaultRemoved,
91759359
fieldReferenceToAlias,
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
// Copyright (c) 2026 ObjectStack. Licensed under the Apache-2.0 license.
2+
3+
// #17260 — ADR-0049 enforce-or-remove, executing the objectui#8285
4+
// director-seat ruling (comment 5583979207, decision batch #91, 2026-09-08,
5+
// standing maintainer delegation): ruled option B — `quickAdd` is retired from
6+
// the `object-kanban` board and stays only on the `kanban-ui` block, where a
7+
// React host can supply the runtime function the control needs.
8+
// The board FORWARDED the key but never honoured it: measured at the
9+
// `.objectui-sha` pin `53ded82bf`, `ObjectKanban.tsx:931` spreads the authored
10+
// bag into `KanbanRenderer` (`plugin-kanban/src/index.tsx:196` passes both
11+
// `quickAdd` and `onQuickAdd`), and `KanbanImpl` gates the affordance on BOTH
12+
// (`:355`, `:368`) — while `onQuickAdd` is a host-supplied FUNCTION that JSON
13+
// cannot carry and no producer puts on an `object-kanban` node
14+
// (`ObjectKanban.tsx` names neither half: 0 each, against 6 for the sibling
15+
// `onCardClick` in the same file). The drop was not silent, which is the sharp
16+
// edge: objectui's html tier reported the published key as `unknown-prop` —
17+
// the SAME diagnostic a typo gets — and its registry-spec ledger records it as
18+
// `ESCALATED (object-kanban.quickAdd — measured NOT honoured)`, so the author
19+
// met a tool contradicting the contract with no way to tell which side was
20+
// wrong. Tombstoned with `retiredKey()` in `ObjectKanbanPropsSchema` (the
21+
// surface baseline line carries `[RETIRED]`); sources are stripped by the D2
22+
// conversion `object-kanban-quick-add-removed`, a pure lossless delete scoped
23+
// by component `type` so the LIVE `kanban-ui` spelling is untouched.
24+
//
25+
// Registered under 18, not 17: v17.0.0 was cut before this landed, so the
26+
// removal ships on the 17.x line (launch-window convention: accept-set
27+
// narrowings ride minor releases) and the prescription lives at the major
28+
// boundary where `migrate meta` users look — the `ui/ObjectGridProps:defaultSort`
29+
// precedent one entry over.
30+
export const entry = 'ui/ObjectKanbanProps:quickAdd';

0 commit comments

Comments
 (0)