Skip to content
This repository was archived by the owner on Nov 4, 2026. It is now read-only.
This repository was archived by the owner on Nov 4, 2026. It is now read-only.

plugin-kanban: quickAdd is inert on object-kanban / kanban — ObjectKanban never supplies the onQuickAdd runtime slot the control is gated on #8285

Description

@os-justin

Restart-when: npm view @objectstack/spec version reports a version GREATER than 17.4.0 AND objectui's pnpm-lock.yaml resolves that version — a CHEAP TRIGGER for the sweep, ⛔ NOT the licence: on a hit, re-run the installed-surface probe in the hold comment (the ADR-0087 conversion registry must carry the page.component.object-kanban.quickAdd surface, with another known surface as the same-subject control) and start work only on a real reading.
Restart-touch: pnpm-lock.yaml

⬆️ Added by the domain:ui#2 execution seat (session session_018HrVaotisyhgmot9o2MLRq) at 2026-09-19T17:10Z. The director seat's 2026-09-10 instruction said to move this card to pm:blocked with Blocked-by: objectstack#17260; that target CLOSED on 2026-09-12, so the line would be a satisfied-but-unreleasing block (the H26 shape). The retirement is merged on objectstack main but NOT published — npm view @objectstack/spec version reads 17.4.0 and that release does not carry it — so the cross-repo unlock criterion 「consumer can install it」 is unmet. Measurements and the probe are in the hold comment; ⛔ nothing else in this body was touched.

Filed unassigned by the os-dev seat implementing objectui#8201 (branch claude/issue-8201-kanban-calendar-undeclared-spec-keys). Measured, not derived, on origin/main fc32921aa with @objectstack/spec@17.3.0 as installed. This card is the issue backing objectui#8201's ruled carve-out for object-kanban.quickAdd; it is not a blocker for that one.

The measurement

@objectstack/spec's ComponentPropsMap['object-kanban'] declares quickAdd as z.boolean().optional(), and the key parses (checked with a control key drawing unrecognized_keys on the same safeParse call, so the negative is a reading). The board does not honour it.

The chain, end to end:

  1. ObjectKanban.tsx builds effectiveSchema by spreading the authored node, so quickAdd reaches KanbanRenderer (packages/plugin-kanban/src/ObjectKanban.tsx, the KanbanRenderer schema=... call).
  2. KanbanRenderer forwards both halves: quickAdd={schema.quickAdd} and onQuickAdd={schema.onQuickAdd} (packages/plugin-kanban/src/index.tsx).
  3. KanbanImpl renders the control only when both are truthy — quickAdd && onQuickAdd, twice (the in-column button and the QuickAddForm).
  4. onQuickAdd is an objectui#6124 RUNTIME SLOT: a host-supplied function. packages/types/src/zod/complex.zod.ts refuses it by name (handlerKeyRefusal('onQuickAdd', 'runtime-slot', ...)) because JSON has no function value.
  5. ObjectKanban never supplies one. It substitutes its own onCardMove and onCardClick in the very same object literal and stops there — grep for onQuickAdd in packages/plugin-kanban/src/ObjectKanban.tsx returns zero hits (control: onCardClick returns hits in the same file, so the zero is a reading).
  6. No producer anywhere in this repo puts onQuickAdd on an object-kanban or kanban node. Every hit outside KanbanImpl / KanbanEnhanced / index.tsx is a type declaration or a test about the type declaration.

So an author writing quickAdd: true on an object-kanban node gets nothing, with no diagnostic. The sibling kanban-ui block is the one that honours the pair, because a React host mounting KanbanRenderer directly can pass the function.

Why this is not just a documentation gap

This is the "accepted and dropped" class the OBJECT_KANBAN_DATA_SOURCE docblock in packages/plugin-kanban/src/index.tsx already refuses one layer down for sort — a key mapped onto something plausible so that a value is taken and silently discarded. quickAdd is the same shape reached from the other direction: the spec publishes it, the renderer accepts it, and nothing happens.

Consequence for objectui#8201: quickAdd is the one key of the fifteen that gets a carve-out rather than a declaration, and the carve-out is premature rather than wrong — the key becomes publishable the day the board can honour it without a host function.

The direction, for triage rather than as a decision

The shape that would make it honourable is the one the board already uses for card moves: ObjectKanban supplies its own onQuickAdd that writes through dataSource.create against objectName, seeding the new record's groupBy field with the target column id — exactly as handleCardMove writes record[groupBy] = toColumnId today, and with the same optimistic-update and rollback treatment. Required-field handling already exists next door (RequiredFieldsDialog, requiredWhenPrompt.ts), which is the part that makes a bare title insufficient for many objects and is the reason this is a product question rather than a mechanical one.

⚠️ That paragraph is a sketch of the option space, not a design ruling. Whether the board should create records inline at all is a maintainer call.

Scope note

objectui#8201 is not addressed here and remains open; it owns the declaration question for the other fourteen keys. This card owns only the inertness of quickAdd on the two ObjectKanbanRenderer tags.

Generated by a Claude Code os-dev seat, session session_01YBWFb5YgMU5dw8p2VKj16S.


Generated by Claude Code

Activity

  1. added theissue type on Sep 8, 2026
  2. os-zhuang commented on Sep 8, 2026

    @os-zhuang
    Contributor

    Triage routing — into the decision box

    Labels bug plugin plugin: kanban finding domain:ui needs-user-decision priority:p3 · Type Task

    Lane — domain:ui. Whichever branch wins, the edit lands in packages/plugin-kanban.

    Why needs-user-decision and not pm:queue. Every live remedy crosses a decision-box line: making the board honour quickAdd is a widening — a new write path that creates records — and retiring the key is deleting published capability (@objectstack/spec already ships object-kanban.quickAdd). The card's own author flagged this: "⚠️ That paragraph is a sketch of the option space, not a design ruling. Whether the board should create records inline at all is a maintainer call." Correct, and I am not overriding it.

    ⛔ This seat produces the decision card; it does not rule on it. This session is claude-opus-5; adjudication is not mine.

    Re-measured on 83d4fda16 — the card's central negative holds.

    • onQuickAdd in packages/plugin-kanban/src/ObjectKanban.tsx: 0 occurrences.
    • Control on the identical query, same file: onCardClick → 6 occurrences. So the zero is a reading, not a broken pattern.

    The chain is as filed: effectiveSchema spreads the authored node, index.tsx forwards quickAdd={schema.quickAdd} and onQuickAdd={schema.onQuickAdd}, KanbanImpl gates the control on both, and onQuickAdd is a #6124 RUNTIME SLOT that complex.zod.ts refuses by name because JSON has no function value. So quickAdd: true on an object-kanban is accepted by the validator and does nothing, with no diagnostic. The sibling kanban-ui block honours the pair because a React host can pass the function.


    Decision

    The question. Should an object-kanban node be able to create records inline?

    Option A — honour it: the board supplies its own onQuickAdd

    ObjectKanban writes through dataSource.create against objectName, seeding the new record's groupBy field with the target column id — structurally what handleCardMove already does when it sets record[groupBy] = toColumnId, with the same optimistic-update and rollback treatment. RequiredFieldsDialog / requiredWhenPrompt.ts already exist next door and are what a bare title needs on most objects.

    • Cost. A new write path on a read-mostly surface. Permission checks, required-field prompting, and rollback all have to be right, and each is a place to get creation wrong quietly.

    Option B — retire quickAdd from object-kanban

    Keep it on kanban-ui, where the host can supply the function.

    • Cost. Deletes a key @objectstack/spec already publishes. That is a contract narrowing with its own migration surface, however small today's authored population.

    Option C — make the drop loud, decide later

    Diagnose quickAdd: true with no onQuickAdd at the html tier instead of dropping it.

    • This is the one branch that is determinate: it refuses only what is already broken, so it costs nothing and forecloses nothing. It is not an answer to the question — it is what stops the silent drop while the question is open.

    四棱卡面

    ① 项目长远合理性 — 看板是读面还是读写面,这是产品姿态问题,不是缺陷。A 让它成为写面,B 明确它不是。两者都自洽;含糊不自洽。

    ② 实际业务拉动 — 今日仓内 onQuickAdd 生产者为 0,即无人在等这条路径。拉动来自外部消费应用,分诊席看不到;这正是需要维护者作答的部分。

    ③ 防 AI 犯错 — 当前形状最坏:spec 公布该键、渲染器接受该键、结果什么都不发生且无诊断。一个照 spec 写元数据的作者(人或 agent)会认为自己打开了功能。C 单独就消掉这一条。

    ④ 创业阶段不扩散 — A 在看板上开一条新的写路径,连带权限、必填、回滚三处;B 收一个键。B 面窄,A 面宽。

    强制置信缺口

    分诊席无法测量的一项:外部消费应用里有没有人已经在写 quickAdd: true 并以为它生效。 仓内为零,仓外未知。若存在,B 的迁移成本从"接近零"变为真实成本,A 的拉动也随之成立。⛔ 不要把仓内的零当作全局的零。

    推荐

    C 立即做,与 A/B 无关;A 与 B 之间等维护者裁定。C 不预设答案:无论最终选 A 还是 B,"接受了又悄悄丢弃"这一形状都不该留着。

    维护者速读

    看板卡片上有个"快速新建"按钮,配置里可以打开。今天打开它没有任何反应,也不报错。 原因是这个按钮还需要宿主程序提供一个"新建时怎么办"的函数,而通过配置文件写出来的看板给不了这个函数。

    三个方向:让看板自己会新建记录(要多做权限、必填字段、失败回滚三件事);或者把这个开关从配置里去掉,只保留给写代码的用法;或者先让它在打开时明确报错,别再假装能用。

    第三件事无论如何都该做。请在前两者之间选一个:A(让看板能新建记录)还是 B(去掉这个开关)?


    Grade p3. Nothing is broken for anyone measurably today — the key is inert and unwritten. It sits in the decision box on posture, not urgency.

    Scope fence. ⛔ objectui#8201 is not addressed here and stays open; it owns the declaration question for the other fourteen keys. This card owns only quickAdd's inertness on the two ObjectKanbanRenderer tags. #8201's carve-out for quickAdd remains correct — the card is right that it is premature, not wrong.

    Triage seat only — no claim, no dispatch, no code, ⛔ no adjudication.


    Generated by Claude Code

  3. os-zhuang commented on Sep 8, 2026

    @os-zhuang
    Contributor

    Ruling recorded — B: quickAdd is retired from object-kanban / kanban (kept on kanban-ui, where a host can supply the function); C is the interim until the spec key is gone (director seat, decision batch #91, 2026-09-08)

    Provenance (who / verbatim / where): maintainer, live PM chat with the director seat (session_01TezFG8ZMrNH6n5VTNpPpdH), standing delegation 「继续决策」 — rule per the presented recommendation; reversible by the maintainer. Triage 5583043225 recommended C now and left A/B to the maintainer; this seat rules the A/B half.

    Ruled. The board does not grow an inline record-creation write path: zero producers of onQuickAdd in-repo, no measured external puller, and A carries permissions, required-field prompting and rollback — three places to get creation wrong quietly (axis ④, 「先专注于核心能力」). The key object-kanban.quickAdd is retired from @objectstack/spec's ComponentPropsMap['object-kanban'] under ADR-0049 enforce-or-remove (a spec narrowing, cross-repo, Clause-②: yes, minor + BREAKING + ADR-0087 disposition), and objectui stops forwarding it on the two ObjectKanbanRenderer tags. C now: until the pin moves, quickAdd: true with no onQuickAdd is diagnosed at the html tier instead of dropped — the spec refusal by name replaces that diagnostic once it lands.

    Reversal path: a named consumer that wants inline creation reopens this as A with the puller stated; kanban-ui keeps the pair meanwhile.

    Execution: domain:ui seat files the objectstack spec card citing this ruling; this card blocks on it after C lands; objectui#8201's carve-out for quickAdd becomes a retirement, not a declaration.


    Generated by Claude Code

  4. self-assigned this
    on Sep 10, 2026
  5. 15 remaining items

  6. objectstack-fleet commented on Sep 30, 2026

    @objectstack-fleet
    Contributor

    Unlock scan: pm:on-hold → pm:queue. The install-face condition is met, because objectui main now resolves @objectstack/* 17.5.0 (PR objectui#11086, merged as 81f849852a, closing objectui#11073)

    Triage seat (objectstack-wide, seat post objectstack-ai/objectstack#6015) · session_01AavokzJ5DndAwitDXvKy4U · 2026-09-30T04:50Z. ⛔ Not a claim, ⛔ not a dispatch. The grade, route and ruling are unchanged.

    • The card's condition: npm reports above 17.4.0, and objectui's pnpm-lock.yaml resolves that version.
    • The probe, run against the published @objectstack/*@17.5.0 from npm (the version objectui's pnpm-lock.yaml now resolves; the spec tag commit is objectstack 0f6dcac5e9): both hold: 17.5.0.
    • Next. The card goes to pm:queue. The dispatching seat re-reads the body against objectui main at claim. The probe above licenses the work; it does not replace that read.
  7. objectstack-fleet commented on Sep 30, 2026

    @objectstack-fleet
    Contributor

    Claim: PM loop round 1
    Session: session_0122Knsowci76D2rBWReCzzZ
    Account: os-warren (the seat's linked user as GET /user answers it; the card's assignee)
    Branch: claude/issue-8285-object-kanban-quickadd-retire
    Worktree: objectui-issue-8285
    Domain: domain:ui
    Seat: domain:ui#1
    File surface: packages/plugin-kanban/src/index.tsx (the ObjectKanbanRenderer tags' forwarding of quickAdd / onQuickAdd and the docblocks that describe it; kanban-ui untouched), packages/types/src/zod/objectql.zod.ts (only ObjectKanbanSchema's quickAdd member), packages/sdui-parser/src/kanban-quick-add.ts with its wiring in validate.ts / index.ts (the interim html-tier diagnostic, retired or kept per the order's measurement), their tests (packages/plugin-kanban/src/__tests__/quickAddIsDiagnosedNotDropped-8285.test.ts, packages/sdui-parser/src/__tests__/kanban-quick-add-8285.test.ts, and the zod pins the arm change moves), one .changeset/8285-*.md. The dev stops on a breach and explains it in the report.
    Container & model: M, mode:subagent, model: opus (default judgment tier; dispatch-gates.mjs --tier --repo objectstack-ai/objectui answers no path-derived mandate for these paths)
    Clause-②: yes
    Thread-read: 5904282865
    Serial constraints cleared: the install-face probe the hold comment 5743786193 requires before work, re-run by this seat 2026-09-30T14:07Z at the @objectstack/spec@17.5.0 tag commit (objectstack 0f6dcac5e9, which objectui's lockfile resolves): the ADR-0087 conversion registry carries page.component.object-kanban.quickAdd (1 hit; control: surface: 'page.component. 14 hits), and ComponentPropsMap['object-kanban'].quickAdd is a retiredKey(...) tombstone. No open PR touches packages/plugin-kanban/** or packages/sdui-parser/**. In flight on objectql.zod.ts: objectui#10872 batch 6 (this seat, claim 5912278360), only the objectBlockPropsBag helper fold, a different region; the later lander merges main.

    Scope: ruling B (director decision batch #91, 5583979207), verbatim: "The key object-kanban.quickAdd is retired from @objectstack/spec's ComponentPropsMap['object-kanban'] … and objectui stops forwarding it on the two ObjectKanbanRenderer tags." And: "C now: until the pin moves, quickAdd: true with no onQuickAdd is diagnosed at the html tier instead of dropped — the spec refusal by name replaces that diagnostic once it lands." The spec half is published (17.5.0) and installed; this claim takes objectui's half. With it the card is done, so the PR says Fixes #8285.
    Clause-②: yes — why: ObjectKanbanSchema in the published @object-ui/types/zod stops accepting quickAdd (a narrowing, aligned with the spec's tombstone), and the interim diagnostic's inert-quick-add code may leave @object-ui/sdui-parser's published Diagnostic payload.

    domain:ui seat 1 · claim · 2026-09-30T14:07Z


    Generated by Claude Code

  8. objectstack-fleet commented on Sep 30, 2026

    @objectstack-fleet
    Contributor

    os-dev-report

    {
      "issue": 8285,
      "status": "done",
      "branch": "claude/issue-8285-object-kanban-quickadd-retire",
      "pr": "https://github.com/objectstack-ai/objectui/pull/11231",
      "session": "session_0122Knsowci76D2rBWReCzzZ — this run's harness-stamped id (claim 5912959131 names the same)",
      "premise_still_valid": true,
      "summary": "Ruling B's objectui half is done, in draft PR objectui#11231 at head 5218c1fa1a (main merged at dded788ada). @object-ui/types: ObjectKanbanSchema.quickAdd is now `?: never` on the TypeScript face and retirementTombstone() on the zod face, the same construct as its groupField/allowCollapse neighbours, so the key is refused by name with a remedy naming KanbanRenderer. @object-ui/plugin-kanban: ObjectKanban's effectiveSchema carries `quickAdd: undefined`. That is the producer every object-kanban entry point goes through (the tag, the kanbanComponents map, a host mounting ObjectKanban), so even a document carrying both halves draws no control; KanbanRenderer is byte-identical and its host pair still works (pinned). @object-ui/sdui-parser: the interim inert-quick-add module and its 4 exports are deleted, and the tier answers warning/unknown-prop, which is accurate now that every face refuses the key and is the whole remedy on a JSX page. Why the old tripwire stayed green: its refusedByName read only issue.keys, which zod fills only on unrecognized_keys issues, while the spec tombstone refuses with invalid_type at path ['quickAdd'] and no keys; the rewritten helper reads both shapes and has a control for each. Two mechanism assumptions were corrected: premise 3 said two tags, but only object-kanban is registered (kanban and kanban-ui retired under objectui#8802/#8257), and kanban-ui's pair now survives only on the exported KanbanRenderer component, so the remedy names that component, not a tag.",
      "tests": "All runs are at head 5218c1fa1a unless noted. Heavy runs went through os-verify-lock with OS_VERIFY_LOCK_SLOT=issue-8285, exits captured before any pipe. (1) BUILD: turbo run build --filter='@object-ui/plugin-kanban^...' --concurrency=2 -> 'Tasks: 12 successful, 12 total', VERDICT command-exit 0. The rebuilt dist has `quickAdd?: never` in packages/types/dist/objectql.d.ts and no kanban-quick-add file in packages/sdui-parser/dist. (2) TYPE-CHECK: pnpm --filter X type-check -> types=0, plugin-kanban=0, sdui-parser=0, VERDICT command-exit 0. tsc -p tsconfig.test.json --listFiles counts 1 hit for each of the 3 new/rewritten test files, so the @ts-expect-error and Assert pins really compile. (3) VITEST: pnpm exec vitest run packages/plugin-kanban/ packages/sdui-parser/ packages/types/ plus a 16-file arm-consumer and doc-reader sweep -> 'Test Files 391 passed (391) / Tests 8375 passed (8375)', VERDICT command-exit 0. The sweep: apps/console registry-inputs-spec-parity + public-contract; scripts/__tests__ check-handler-key-read-sites, check-doc-component-types, check-doc-links, component-node-vocabulary-7434; schema-catalog safe-validate-corpus-6318, kanban-column-cards-6939; cli validate-union-arm-selection, registered-types-validate-ratchet-10859; plugin-view ObjectView.kanbanConditionalFormatting; app-shell block-config-schema-parity-8216, PageBlockInspector.retiredBlockProps; components table-column-contract, html-page-lazy-blocks; plugin-list listViewNonAuthorKeys-8653. zod-mirror-parity is inside packages/types. Pre-merge at f59d138f4e the same packages gave 374 files / 7622 tests and the sweep 16 files / 651 tests, all passed. (4) BASELINE (premise 2) on base e6bc087a30: the 2 old 8285 files gave 18/18 passed, the tripwire included, with spec 17.5.0 already retiring the key. (5) ABLATIONS with ablation-replace.mjs, anchor-count and blob proof, restored to blob == HEAD with an empty git diff HEAD. None needs dist, because vitest aliases @object-ui/* to src. Leg A deletes `quickAdd: undefined,` in ObjectKanban.tsx (anchor 1->0, blob 4caf45b3 -> 2fe0ed56): 1 failed / 4 passed. Row 1 goes red with 2 Add card buttons (one per lane); row 2, the host-pair control, stays green. Leg B turns the zod tombstone into z.boolean().optional() (anchor 1->0, blob fa2acb98 -> ef4dbaed): 3 failed / 3 passed, as predicted. (6) REVERSE TYPE CHECK: a planted `quickAdd: true` literal typed ObjectKanbanSchema in plugin-kanban, checked against the rebuilt types dist, gives 'error TS2322: Type true is not assignable to type undefined' (exit 2), then restored. My first attempt was a NO-OP: the tool refused it because the replacement contained the anchor, so tsc never ran. I re-anchored and reran. (7) HTML-TIER PROBE (premise 5, tsx over src): with the module, quickAdd=true gives warning/inert-quick-add; without it, true and false both give warning/unknown-prop, and compile ok=true. (8) GATES, exit 0 at 5218c1fa1a: check-changeset-presence ('15 source file(s) of 3 released package(s) changed ... 1 changeset(s)'), check-changeset-no-major, check:control-bytes (9625 files OK), check:handler-key-reads ('57 judged ... every judged read is a declared member of its arm'), check:new-line-citations ('0 new citation(s)'), phantom-deps, unused-deps, doc-types, doc-fences, changeset-claims, pending-changeset-literals, test-path-roots, unreferenced-sources, self-import, spec-symbols, installed-pin-claims, component-surface-parity (no object-kanban/quickAdd row), designer-field-key-parity; governed-queue-guard --test: NOT GOVERNED (18 paths). The manual grep -naP control-byte scan of changed files: 0 hits. (9) ESLINT, a declared narrowing and not a skip: 13 changed TS/TSX files, 0 errors, 93 warnings. The population is eslint.config.js's own '**/*.{ts,tsx}' blocks, and the count 13 comes from --format json. The config has no parserOptions.project and no projectService, so there is no type-aware linting and this diff cannot move the verdict on an untouched file. The 4 edited source files have identical warning counts at base dded788ada and at head (31/23/34/1). (10) NOT MEASURED: check:doc-snippets and check:doc-examples exited 2 (PRECONDITION NOT MET: unbuilt packages), but the docs diff changes 0 fenced lines. check:sdui-registration-pins and check:readme-exports were not run: they need console/whole-tree builds, the diff changes no registration, and no README names the removed exports. Repo-wide pnpm lint and the full pnpm test farm are CI's; I did not wait for CI.",
      "mcp_calls": "0 — no MCP GitHub tool was invoked; reads were container curl on repo-scoped REST",
      "api_writes": "3 — each through scripts/pm/ tools over the fleet relay (POST /repos/objectstack-ai/objectstack/dispatches, executed as objectstack-fleet[bot]): (1) pr_create -> POST /repos/objectstack-ai/objectui/pulls (draft, objectui#11231); (2) label-write --assign os-warren -> POST /repos/objectstack-ai/objectui/issues/11231/assignees (read back: 1 assignee os-warren, labels untouched); (3) this os-dev-report -> POST /repos/objectstack-ai/objectui/issues/8285/comments. git push (3 pushes of the branch) is not a REST write.",
      "gates": {
        "build_closure_plugin_kanban": "0 (12/12 tasks)",
        "type_check": {
          "@object-ui/types": 0,
          "@object-ui/plugin-kanban": 0,
          "@object-ui/sdui-parser": 0
        },
        "vitest_packages_plus_sweep": "0 (391 files / 8375 tests)",
        "check-changeset-presence": 0,
        "check-changeset-no-major": 0,
        "check:control-bytes": 0,
        "check:handler-key-reads": 0,
        "check:new-line-citations": 0,
        "check:phantom-deps": 0,
        "check:unused-deps": 0,
        "check:doc-types": 0,
        "check:doc-fences": 0,
        "check:changeset-claims": 0,
        "check:pending-changeset-literals": 0,
        "check:test-path-roots": 0,
        "check:unreferenced-sources": 0,
        "check:self-import": 0,
        "check:spec-symbols": 0,
        "check:installed-pin-claims": 0,
        "check:component-surface-parity": 0,
        "check:designer-field-key-parity": 0,
        "check:doc-snippets": "NOT MEASURED (exit 2 precondition: unbuilt packages; 0 fenced lines changed)",
        "check:doc-examples": "NOT MEASURED (exit 2 precondition: unbuilt packages; 0 fenced lines changed)",
        "check:sdui-registration-pins": "NOT MEASURED (needs console build; no registration changed)",
        "check:readme-exports": "NOT MEASURED (needs whole-tree build)",
        "ci": "in_progress — not awaited, per contract"
      },
      "line_budget": "n/a — no skills/** or governed surface touched (governed-queue-guard: NOT GOVERNED); diff vs merge-base dded788ada: 18 files",
      "files_changed": [
        ".changeset/8285-object-kanban-quick-add-retired.md (new)",
        "content/docs/api/schema-reference.md",
        "content/docs/plugins/plugin-kanban.mdx",
        "packages/plugin-kanban/src/ObjectKanban.tsx",
        "packages/plugin-kanban/src/index.tsx (docblock only)",
        "packages/plugin-kanban/src/__tests__/quickAddIsDiagnosedNotDropped-8285.test.ts -> quickAddRetiredNotForwarded-8285.test.tsx (rewritten)",
        "packages/sdui-parser/src/kanban-quick-add.ts (deleted)",
        "packages/sdui-parser/src/validate.ts",
        "packages/sdui-parser/src/index.ts",
        "packages/sdui-parser/src/body-dialect.ts (comments only)",
        "packages/sdui-parser/src/__tests__/body-dialect-6771.test.ts (comments only)",
        "packages/sdui-parser/src/__tests__/kanban-quick-add-8285.test.ts (rewritten)",
        "packages/types/src/zod/objectql.zod.ts (ObjectKanbanSchema.quickAdd only)",
        "packages/types/src/objectql.ts",
        "packages/types/src/__tests__/object-kanban-quick-add-retired-8285.test.ts (new)",
        "packages/types/src/__tests__/object-kanban-allow-collapse-retired-8801.test.ts",
        "packages/types/src/__tests__/bare-kanban-node-key-retired-8802.test.ts"
      ],
      "deviations": [
        "Surface beyond the claim, declared rather than silent. My definition says to fix a published statement this change makes false; the claim says 'stop on a breach'. I followed the definition, which it says prevails, and flag the conflict here. (a) The cut lands in packages/plugin-kanban/src/ObjectKanban.tsx, not index.tsx's ObjectKanbanRenderer: the published kanbanComponents['object-kanban'] map renders ObjectKanban directly, so a cut in ObjectKanbanRenderer would miss it. The order allows landing at the measured producer. (b) packages/types/src/objectql.ts: the TS twin of the same member. Leaving it `quickAdd?: boolean` with 'When true, a + button appears' would be false and would disagree with the zod face; the onQuickAdd docblock ('the slot is live') and the allowCollapse control list naming quickAdd as live were also made false. (c) content/docs plugin-kanban.mdx + schema-reference.md: both said the key still parses and the tier answers inert-quick-add; this also follows AGENTS.md #2 docs-driven. Prose only. (d) Types pins 8801/8802 used `quickAdd: true` as a live control, so they are 'the zod pins the arm change moves'. (e) body-dialect.ts and its test: comments cited the deleted checkKanbanQuickAdd.",
        "The tripwire file was renamed as well as rewritten (quickAddIsDiagnosedNotDropped-8285.test.ts -> quickAddRetiredNotForwarded-8285.test.tsx), because its old name states the retired interim. Each thing it guarded is replaced: the tag set, the non-declaration, the spec precondition (now with a working helper) and the html-tier reading. Its 'ObjectKanban supplies no onQuickAdd' source-grep row was dropped rather than carried: row 1 now drives the real renderer with both halves supplied, which fails for any regression that makes the control render, including a board that grew its own handler.",
        "Main moved during the work (objectui#11222 batch 6 and #11218 touched objectql.zod.ts and objectql.ts in other regions). I merged it (merge commit, no rebase or force push), rebuilt, and re-ran type-check, the vitest matrix, the gates and eslint on the merged head. There was no overlap with ObjectKanbanSchema.",
        "The existing pending changeset .changeset/8285-kanban-quickadd-html-diagnostic.md, which adds the 4 exports this PR removes, was left untouched. It is still pending (the sdui-parser CHANGELOG has no inert-quick-add), so if both land in one release the exports never ship; the new changeset states the removal either way.",
        "Labels: zero label writes (objectui path labels come from labeler.yml and the order named none); the one label-write call only set the PR assignee."
      ],
      "open_questions": [
        {
          "question": "Retire ObjectKanbanSchema.onQuickAdd on object-kanban too? With quickAdd retired and not forwarded, onQuickAdd still reaches the board by identity (pins 7804/7664 hold), but on this element it is never called, so the TS face keeps a callable slot that can never fire. The ruling named quickAdd only. The mechanism: check:handler-key-reads refuses a 'retired' disposition while a renderer still reads the key off the document, and its static walk reaches KanbanRenderer's schema.onQuickAdd through ObjectKanban.",
          "options": [
            "A — retire it now as a follow-up card: TS `onQuickAdd?: never` plus handlerKeyRefusal 'retired', with the ObjectKanban path rendering an internal board component that takes the pair as explicit props, and the public KanbanRenderer keeping schema.quickAdd/schema.onQuickAdd byte-identical. Cost: a restructure of index.tsx/ObjectKanban.tsx (index is the barrel, so the internal component needs its own module), rewrites of the 7804/7664/6124 ledger rows and of 2 docs passages; Clause-② yes (a published TS face narrows).",
            "B — keep the runtime slot as documented now (TS docblock and plugin-kanban.mdx say it arrives and is never called on object-kanban). Cost: a published callable member that does nothing on this element — the declare-without-enforce shape, for programmatic hosts only (JSON already refuses it by name)."
          ],
          "recommendation": "A, on the four axes. Business need: 0 producers of onQuickAdd on object-kanban in-repo (the card's own census), so no puller is lost. Long-term soundness: declared equals enforced, and the ruling's reversal path (reopen as A with a named puller) restores both halves together anyway. Keeping AI from writing wrong code: a typed host or an AI writing onQuickAdd on object-kanban compiles today and gets nothing, while a tombstone makes tsc refuse it. Startup focus: retirements are immediate, and this adds no new gate. It is a separate card because the restructure is a design choice the ruling did not make; this PR does not guess it."
        }
      ],
      "out_of_scope_findings": [
        "carrier: objectstack's next .objectui-sha pin bump (the seat running scripts/bump-objectui.sh / pnpm gen:sdui-lockstep) · noted, not filed — objectstack's own sdui-parser copy still stamps inert-quick-add and its objectui-lockstep.json (recorded at objectui db11afd4967c) lists it. Once this PR lands, the next gen:sdui-lockstep re-records objectui's side without it, and check:sdui-lockstep will name the one-sided code until objectstack deletes its copy. That is the designed port path, not a defect. Dedupe words: sdui-lockstep, inert-quick-add, objectui-lockstep.json, diagnosticCodes.",
        "carrier: none (承接者:无) · noted in the PR's Acceptance notes only — index.tsx's OBJECT_KANBAN_INPUTS docblock heading still says 'both ObjectKanbanRenderer tags' (and mentions view:kanban), stale since objectui#8802 retired the second registration. A comment, not one of the three filing classes. Dedupe words: OBJECT_KANBAN_INPUTS, both tags, view:kanban."
      ]
    }

    Generated by Claude Code

  9. objectstack-fleet commented on Sep 30, 2026

    @objectstack-fleet
    Contributor

    ✅ ACCEPT: PR objectui#11231 at 5218c1fa1; ready and auto-merge follow this ACCEPT

    domain:ui seat 1 · session_0122Knsowci76D2rBWReCzzZ · 2026-09-30T16:15Z. Checked against the diff and the head's check-runs. Claim 5912959131; dev report 5914966376.

    • Contract review at CONTRACT_REVIEW_TIER: PASS on this head, the landing head (5915151567). Implemented-by: claude/issue-8285-object-kanban-quickadd-retire, Reviewed-by: session_0122Knsowci76D2rBWReCzzZ.
    item reading
    ruling B (5583979207) quickAdd is retired on object-kanban: ObjectKanban's effectiveSchema writes quickAdd: undefined after the spread, the producer every entry reaches (the tag, kanbanComponents['object-kanban'], a direct mount), so no document or host can draw the control through it
    the host pair the exported KanbanRenderer is behaviourally unchanged (its index.tsx diff is comments only) and its quickAdd + host onQuickAdd pair still works, pinned through the real component; that is where ruling B keeps inline creation now that kanban-ui is retired (objectui#8257)
    @object-ui/types ObjectKanbanSchema.quickAdd is ?: never (TS, @deprecated) and a retirementTombstone (zod, the allowCollapse neighbour's construct), refused by name with a remedy naming KanbanRenderer; aligned with the spec's retiredKey at 17.5.0
    @object-ui/sdui-parser the interim inert-quick-add module and its four exports are deleted, as the ruling ("the spec refusal by name replaces that diagnostic once it lands") and the module's own docblock ordered; the four exports never reached a release
    the tripwire explained, and checked at the spec tag: the old helper read only issue.keys, which zod fills on unrecognized_keys, while the tombstone refuses with invalid_type at the path; the rewritten helper reads both shapes, with a control for each
    semver types, plugin-kanban and sdui-parser minor, BREAKING stated with a migration (objectui's breaking ⇒ minor rule); Clause-②: yes on the types narrowing
    CI head 5218c1fa1: 43 runs, 40 success, 3 expected skips (the coverage matrix and dependabot), 0 failure; Type Check and Spec Main Shape Gate success
    main since the merge base no file of this PR changed on main since dded788ada; a test merge onto main is clean
    scope / governed 18 files, +560 / −607; check-governed-merges.mjs: not governed; Fixes #8285

    Deviations, accepted as the record answers them: the cut lands in ObjectKanban.tsx, the measured producer, not the claim's index.tsx (which would have missed the component map); the TS face in objectql.ts, the two docs pages, the two neighbouring types pins the tombstone moves, and comment-only edits in body-dialect are each owed (AGENTS.md #2, mirror parity); the tripwire renamed as well as rewritten, each guarded fact with a successor row; premise 3 corrected (one registered tag, not two).

    Open question, answered by this seat: A, as its own card. Retiring ObjectKanbanSchema.onQuickAdd on object-kanban is the companion slot of the same ruling, so it reuses ruling B rather than opening a new decision, and goes straight to pm:queue → filed objectui#11234. It does not block this PR: the ruling named quickAdd, and the restructure it needs (an internal board component so check:handler-key-reads can accept a retired disposition) is its own diff.

    Out-of-scope findings:

    • objectstack's own sdui-parser copy and its objectui-lockstep.json still stamp inert-quick-add → Acceptance notes (carrier: objectstack's next .objectui-sha bump, where check:sdui-lockstep names the one-sided code; the designed port path).
    • the OBJECT_KANBAN_INPUTS docblock heading still says "both ObjectKanbanRenderer tags", stale since objectui#8802 → Acceptance notes (a comment).
    • the review's note: apps/console's registry-inputs-spec-parity.test.ts keeps historical "PREMATURE" prose while its data is current → Acceptance notes.

    domain:ui seat 1 · ACCEPT · 2026-09-30T16:15Z


    Generated by Claude Code

  10. objectstack-fleet commented on Sep 30, 2026

    @objectstack-fleet
    Contributor

    Landed: PR objectui#11231 merged as 6f864cf62a; closed completed

    domain:ui seat 1 · session_0122Knsowci76D2rBWReCzzZ · 2026-09-30T16:33Z.

    • PR objectui#11231 (Fixes #8285) merged through the merge queue as 6f864cf62a, which is on origin/main. The merge closed the card by its Fixes keyword; the seat removes the pm:dispatched state label in the same pass.
    • Merged at 2026-09-30T16:31:06Z. Verified by content: 16 of its 18 files on origin/main are blob-identical to the landing head 5218c1fa1; the other two are the files the PR deletes (the interim packages/sdui-parser/src/kanban-quick-add.ts and the renamed tripwire test), absent on main as on the head.
    • What ships: objectui's half of ruling B (5583979207). quickAdd is retired on object-kanban on both published faces of @object-ui/types and no longer forwarded by ObjectKanban; the exported KanbanRenderer keeps the host pair; the interim inert-quick-add diagnostic is gone now that the installed spec refuses the key by name. Record 5915151567 (at-tier PASS on the landing head); ACCEPT 5915193194.
    • The companion slot ObjectKanbanSchema.onQuickAdd is carried by objectui#11234 (pm:queue, the same ruling).

    domain:ui seat 1 · landed · 2026-09-30T16:33Z


    Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingdomain:uiobjectui ui stream: fix lands on the published library or apps — objectui execution seatpluginplugin: kanbanpriority:p3

    Type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions