Repository navigation
Commit 52aad5c
feat(types,plugin-kanban)!: retire ObjectKanbanSchema.onQuickAdd; the object-kanban path renders an internal board that takes the quick-add pair as props (objectui#11234) (#11269)
Fixes #11234
Clause-②: no (narrowing)
Retires `ObjectKanbanSchema.onQuickAdd` on `object-kanban` on both
faces, completing ruling B of the director seat's decision batch #91
(`5583979207`, recorded on objectui#8285): the object-bound board does
not grow an inline record-creation write path, and the Quick Add pair
stays with a React host. Direction is option A of the PR objectui#11231
dev, as adopted in the card; no inline creation path is added, and
`KanbanRenderer`'s host pair is unchanged.
## What changed
- **`@object-ui/types`**: `ObjectKanbanSchema.onQuickAdd` is `?: never`
on the TypeScript face (`objectql.ts`), and
`handlerKeyRefusal('onQuickAdd', 'retired', 'Quick Add handler')` on the
zod mirror (`zod/objectql.zod.ts`). The JSON face still refuses the key
by name with code `custom`; the guidance now says RETIRED instead of
RUNTIME SLOT.
- **`@object-ui/plugin-kanban`**:
- A new internal module `src/KanbanBoardCore.tsx` holds the board body
that used to live in `KanbanRenderer`: the bucketing memo, the lazy
`KanbanImpl`, and the Suspense fallback. It takes the Quick Add pair
ONLY as explicit props (`quickAdd`, `onQuickAdd`), and its `schema` type
is `KanbanRendererProps['schema']` with those two keys omitted, so a
`schema.onQuickAdd` read written into it fails type-check. It is not
re-exported from the `index.tsx` barrel.
- `KanbanRenderer` (public) now renders `KanbanBoardCore` and passes
`schema.quickAdd` / `schema.onQuickAdd`. Its props interface is
byte-identical, and so is what a host gets.
- `ObjectKanban` renders `KanbanBoardCore` and passes neither half. The
old `quickAdd: undefined` line on `effectiveSchema` is removed, because
nothing on this path reads `schema.quickAdd` any more; the comment in
its place says where the cut now is.
- Why the module move was needed: `check:handler-key-reads` refuses a
`retired` disposition while a renderer reachable from the registration
reads the key off the document. The `object-kanban` path reached
`KanbanRenderer`'s `schema.onQuickAdd` read. After this change, the
gate's census for `object-kanban` holds one row, `onCardClick
[runtime-slot]`, read in `KanbanBoardCore.tsx`.
- **Docs**: `content/docs/plugins/plugin-kanban.mdx` (the handler-key
paragraph and the "Quick Add is a React-host capability" section) and
`content/docs/api/schema-reference.md` (the `ObjectKanbanSchema`
handler-keys callout, and one clause of the `quickAdd` callout).
- **Changesets**:
`.changeset/11234-object-kanban-onquickadd-retired.md`, with `minor` on
`@object-ui/types` (a narrowing, breaking semantics stated in the body)
and `patch` on `@object-ui/plugin-kanban` (no public props moved). Three
pending entries that this release would otherwise ship with a false
sentence are amended, one sentence each, with every other byte and the
frontmatter unchanged: `8285-object-kanban-quick-add-retired.md` (its
closing note said `onQuickAdd` stays a runtime slot),
`7804-object-kanban-handler-keys-judged.md` (it said `onCardClick` and
`onQuickAdd` are both runtime slots) and
`8285-kanban-quickadd-html-diagnostic.md` (it said `onQuickAdd` is a
runtime slot).
## Pins
- **JSON face, by name, and TS face `never`**: new
`packages/types/src/__tests__/object-kanban-on-quick-add-retired-11234.test.ts`.
- Runtime legs: the key is refused as `custom` at path `onQuickAdd`, for
an action object and for a live function. The `.describe()` text is the
parse message. A near-miss key is kept. The CLI union refuses a whole
node carrying the key.
- The retired-disposition leg reads RETIRED for `onQuickAdd` against
`onCardClick` on the same arm and helper, which still reads RUNTIME
SLOT. That `onCardClick` reading is the lit control.
- Type-level pins: `Equal` to `undefined`, not `any`, not callable, and
an `@ts-expect-error` on a literal that writes the key. The sibling slot
`onCardClick` is still callable.
- **The host pair still draws and calls (control)**:
`quickAddRetiredNotForwarded-8285.test.tsx` row 2, unchanged.
`KanbanRenderer` with `quickAdd: true` plus a function draws one control
per lane, and a submitted title reaches the host.
- **An `object-kanban` node draws no Quick Add**: the same file's row 1,
unchanged, through the real registry and the real board. It was already
green before this change, because `quickAdd` was cut. The readings that
discriminate on `onQuickAdd` itself flip in two files, each with
`onCardClick` as the lit control on the same render:
- `handlerKeyDispositionsMeasured-7804.test.tsx` suite 2: the board
receives `onQuickAdd: undefined` and `quickAdd: undefined`, while the
authored `onCardClick` runs once.
- `kanban-handler-slots-7664.test.tsx` suite 1.
- **Ablation** (below): re-declaring the key as a runtime slot turns the
retired-disposition pin red on each face.
Ledger rows moved with it:
- the objectui#6124 ledger: the row moves from `RUNTIME_SLOT` to
`RETIRED`, 61 + 21 becomes 60 + 22 with the total unchanged at 82, and
the type blocks move the key from `KeepsFunction` to `RetiredIsNever`;
- `zod-mirror-parity`: `onQuickAdd` leaves the
`objectql.zod.ts#ObjectKanbanSchema` drift entry, and the header key
total goes 87 to 86 with its history sentence;
- the objectui#7340 docs census: 29 retired members, `objectql.ts` 2,
and `onQuickAdd` joins the unambiguously retired names;
- the objectui#7804 and objectui#7664 plugin-kanban readings: suite 3 of
7664 now derives the read sites from both bodies, and adds a barrel pin
that `KanbanBoardCore` is not published;
- `check-handler-key-read-sites.test.ts`: `onQuickAdd` leaves the
`object-kanban` census, the arm reads `retired`, and the `onCardClick`
row's file is `KanbanBoardCore.tsx`.
Three source-reading pins had to be re-pointed at the moved text:
- the objectui#9357 arity pin's `index.tsx` hop is now the hand-off to
`KanbanBoardCore`;
- the objectui#8932 firing control finds the live board's lazy import in
`KanbanBoardCore.tsx`;
- the objectui#8801 schema-channel end is now `KanbanBoardCore`'s
signature.
## Measured producers of `onQuickAdd` on `object-kanban`: 0 in both
repos
- **objectui** (this branch): tracked files naming `onQuickAdd`,
excluding tests and markdown, number 7 at the final head. They are
`KanbanImpl.tsx` (the board's props), `index.tsx` (the host face), the
two declarations, one comment in the gate script, `KanbanBoardCore.tsx`
(its internal prop pair), and one comment in `ObjectKanban.tsx`. None
writes the key onto an `object-kanban` node. Lit control on the same
instrument: 7 non-test files write a `type: 'object-kanban'` node, and 2
JSON files in `examples/schema-catalog` carry `object-kanban`. JSON/YAML
files naming `onQuickAdd`: 0.
- **objectstack** `origin/main` `4d0b9cd54` (read-only `git grep`):
`onQuickAdd` appears only in docs, CHANGELOGs, comments and diagnostic
message text (`component.mdx`, the sdui-parser interim diagnostic and
its test, the spec CHANGELOG, a `conversions/registry.ts` note).
`packages/spec/src/ui/component.zod.ts` has 0 hits for `onQuickAdd`. Lit
control on the same instrument: `quickAdd` hits 17 files,
`component.zod.ts` among them.
## Verification
All runs from the worktree root, through `os-verify-lock`, with
`NODE_OPTIONS=--max-old-space-size=4096`. Pass counts are read from the
vitest summary line, not from exit codes. Final head is `b1e88910f`. Its
two commits over `e2bf34b97` are changeset text only, so the test and
type-check runs below at `e2bf34b97` stand; the changeset gates were
re-run at `b1e88910f` (last table row).
| Run | Head | Result |
|---|---|---|
| `pnpm exec vitest run packages/plugin-kanban/src/` (verbose) |
`611112e0e` | 64 files passed, 421 tests passed |
| 8 named pins: the types 11234 / 6124 / zod-mirror-parity / 7340 / 8285
files, sdui-parser `kanban-quick-add-8285`, react 9357, scripts
`check-handler-key-read-sites` | `611112e0e` | 8 files passed, 487 tests
passed |
| `pnpm exec vitest run packages/types/` plus the 14 test files outside
types/scripts that import plugin-kanban (console, schema-catalog,
app-shell, cli, core, i18n, plugin-calendar, plugin-list, runner) |
`e2bf34b97` | 308 files passed, 8232 tests passed |
| `pnpm exec vitest run scripts/__tests__/` (whole root suite, owed
because docs were edited) | `e2bf34b97` | 177 passed, 2 skipped (179
files); 5371 passed, 2 skipped tests |
| `pnpm --filter @object-ui/types type-check` (3 tsc projects; the test
project lists 294 test files, the new pin among them) | `e2bf34b97` |
exit 0 |
| `pnpm --workspace-concurrency=2 --filter
'@object-ui/plugin-kanban^...' build` (13 packages), then `pnpm --filter
@object-ui/plugin-kanban type-check` | `e2bf34b97` | build exit 0;
type-check exit 0 with 0 `error TS`. The rebuilt
`packages/types/dist/objectql.d.ts` carries `onQuickAdd?: never`, so the
plugin read the new typings |
| `check:handler-key-reads` | `e2bf34b97` | exit 0, every judged read
declared, 2 exempted by ledger |
| `check-changeset-presence`, `check-changeset-no-major`,
`check:control-bytes`, `check:new-line-citations` | `e2bf34b97` | all
exit 0; 0 new cross-file line citations |
| `check-i18n-call-site-keys`, `check-i18n-en-drift`,
`check-i18n-dead-keys` (the `kanban.uncategorized` translation hook
moved modules) | `e2bf34b97` | all exit 0 |
| `node scripts/markdown-test-inputs.mjs --audit` | `e2bf34b97` | exit
0: 107 candidate files adjudicated, 78 entries present |
| `pnpm exec eslint --format json` over the 16 changed code files |
`e2bf34b97` | 0 errors, 96 warnings. Every pre-existing file has the
same message count as the base version linted through stdin; the 2 new
files have 0 |
| `check-governed-queue-guard --test` over the 19 paths | `e2bf34b97` |
NOT GOVERNED |
| `check-changeset-presence`, `changeset:check`,
`check:changeset-claims`, `check:pending-changeset-literals`,
`check-governed-queue-guard --test` over the 22 paths | `b1e88910f` |
all exit 0; NOT GOVERNED |
**Declared narrowing**: repo-wide `pnpm lint` and the full `pnpm test`
farm are left to CI. eslint's population is its own `files:
['**/*.{ts,tsx}']` block. The file count, 16, is read from the JSON
output. `eslint.config.js` configures no `projectService` and no
`parserOptions.project`, so linting is not type-aware and this diff
cannot move a verdict on an untouched file.
### Ablation: re-declare `onQuickAdd` as a runtime slot, one face at a
time
Run on the committed head `e2bf34b97` through objectstack's
`scripts/ablation-replace.mjs` in wrap mode, inside a script with its
own `trap` restore, under the lock. The predictions were written before
the run.
- **Zod leg**: `'retired'` becomes `'runtime-slot'` in
`objectql.zod.ts`. The anchor went x1 to x0 and the blob `c106c73cb1ec`
to `6b9fc742c9d5`. Vitest over the 11234 pin and the 6124 ledger read 2
failed, 341 passed. The two failures are exactly the predicted legs: the
11234 retired-disposition leg, and the 6124 "guidance wording
distinguishes a runtime slot from a retired key" leg.
- **TS leg**: `onQuickAdd?: never;` becomes the callable in
`objectql.ts`. The anchor went x1 to x0 and the blob `dde43cddfea1` to
`afedc0cab24b`. `tsc -p packages/types/tsconfig.test.json` exited 2 with
5 errors:
- the 11234 pin: TS2344 twice (tombstone, not-callable) and TS2578 (the
`@ts-expect-error` became unused);
- the 6124 `RetiredIsNever` row: TS2344;
- `zod-mirror-parity`'s type-map ledger: TS2322, because the drift entry
is owed again. This fifth error was not in the written prediction. It is
the right direction, since the ledger answers to the faces.
- **Restore proven**: `git diff HEAD` over both paths is 0 bytes, both
blob hashes equal HEAD's, and `git status --porcelain` has 0 lines.
## Acceptance notes (observations; nothing filed)
- Three pending changesets said `onQuickAdd` is, or stays, a runtime
slot on `object-kanban`, which would ship false in the same release:
`8285-object-kanban-quick-add-retired.md`,
`7804-object-kanban-handler-keys-judged.md` and
`8285-kanban-quickadd-html-diagnostic.md`. Each false sentence is
amended in this PR, and the rest of each file, frontmatter included, is
byte-identical. The seat added the three files to the claim's file
surface.
- The objectui#6124 ledger's `RetiredIsNever` type block has no
`ObjectKanbanSchema['onCardMove']` row. That key's `never` is pinned by
a source read in the 7804 suite 3 leg instead. Not added here.
- A few comments still say "`KanbanRenderer`'s lazy boundary", and
several tests' pre-warm comments say their `'../KanbanImpl'` specifier
matches `index`'s. The lazy import now lives in `KanbanBoardCore.tsx`.
It resolves to the same module, so the pre-warm imports still hit the
cache. The comments are not swept; per AGENTS.md they get repaired when
a change touches those files anyway. I fixed the ones on lines this
change touched.
- The retired guidance text is the shared `handlerKeyRefusal` wording
(the node-type remedy). The practical remedy for this key, mounting
`KanbanRenderer`, is carried by the TS docblock, the docs and the
changeset, the same as for `onCardMove`.
- The card body says `Clause-②: yes`; the PM claim says `no
(narrowing)`. This body copies the claim's line, as the dispatch order
directs.
Session: `https://claude.ai/code/session_011p7ikEivgXefNDaE5S5Uec` (a
dispatched `os-dev` run; branch
`claude/issue-11234-kanban-onquickadd-retire`).
---
_Generated by [Claude
Code](https://claude.ai/code/session_011p7ikEivgXefNDaE5S5Uec)_
---------
Co-authored-by: Claude <noreply@anthropic.com>1 parent 18d1a0a commit 52aad5c
22 files changed
Lines changed: 746 additions & 190 deletions
File tree
- .changeset
- content/docs
- api
- plugins
- packages
- plugin-kanban/src
- __tests__
- react/src/hooks/__tests__
- types/src
- __tests__
- zod
- scripts/__tests__
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
4 | 4 | | |
5 | 5 | | |
6 | 6 | | |
7 | | - | |
8 | | - | |
9 | | - | |
10 | | - | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
11 | 12 | | |
12 | 13 | | |
13 | 14 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
5 | 5 | | |
6 | 6 | | |
7 | 7 | | |
8 | | - | |
9 | | - | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
10 | 12 | | |
11 | 13 | | |
12 | 14 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
40 | 40 | | |
41 | 41 | | |
42 | 42 | | |
43 | | - | |
44 | | - | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
981 | 981 | | |
982 | 982 | | |
983 | 983 | | |
984 | | - | |
| 984 | + | |
985 | 985 | | |
986 | 986 | | |
987 | 987 | | |
988 | 988 | | |
989 | 989 | | |
990 | 990 | | |
991 | 991 | | |
992 | | - | |
| 992 | + | |
993 | 993 | | |
994 | 994 | | |
995 | 995 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
82 | 82 | | |
83 | 83 | | |
84 | 84 | | |
85 | | - | |
86 | | - | |
87 | | - | |
88 | | - | |
89 | | - | |
90 | | - | |
91 | | - | |
92 | | - | |
93 | | - | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
94 | 100 | | |
95 | 101 | | |
96 | 102 | | |
| |||
473 | 479 | | |
474 | 480 | | |
475 | 481 | | |
476 | | - | |
477 | | - | |
478 | | - | |
479 | | - | |
| 482 | + | |
| 483 | + | |
| 484 | + | |
| 485 | + | |
480 | 486 | | |
481 | 487 | | |
482 | 488 | | |
483 | 489 | | |
484 | 490 | | |
485 | 491 | | |
486 | 492 | | |
487 | | - | |
488 | | - | |
489 | | - | |
490 | | - | |
| 493 | + | |
| 494 | + | |
| 495 | + | |
| 496 | + | |
| 497 | + | |
| 498 | + | |
491 | 499 | | |
492 | | - | |
493 | | - | |
494 | | - | |
| 500 | + | |
| 501 | + | |
| 502 | + | |
495 | 503 | | |
496 | 504 | | |
497 | 505 | | |
| |||
0 commit comments