Skip to content

docs(api): stop teaching quickAdd and allowCollapse on the object-kanban table - #9353

Draft
os-sam wants to merge 1 commit into
mainfrom
claude/issue-9247-kanban-doc-table-rows
Draft

docs(api): stop teaching quickAdd and allowCollapse on the object-kanban table#9353
os-sam wants to merge 1 commit into
mainfrom
claude/issue-9247-kanban-doc-table-rows

Conversation

@os-sam

@os-sam os-sam commented Sep 13, 2026

Copy link
Copy Markdown
Collaborator

Fixes #9247

content/docs/api/schema-reference.md's object-kanban section listed two keys an object-bound board does not honour, and one of them sat inside the copy-paste JSON example. This is the face an AI generator copies from, so a wrong row produces wrong metadata at scale rather than one confused author.

One file changed, 3 insertions and 4 deletions.

What changed

  1. The copy-paste example"quickAdd": true deleted. ⚠️ Deleting the last member left a dangling comma on the cardFields line, which would have made the fenced block invalid JSON; that comma is dropped in the same edit. The snippet gate was run rather than assumed, and it compiles (below).
  2. The allowCollapse table row — deleted, not reworded.
  3. The quickAdd table row — deleted, not reworded. The wording was not free: the retirement ruling governs it, and no description was invented.
  4. One note added, in the shape the section already uses for groupField, recording why both keys are absent. Without it the next reader finds both keys still declared on @object-ui/types' mirror and restores the rows, which is the same defect coming back.

Zone 2 — the second-hand readings, re-measured here

Neither triage nor the PM could measure the spec side: @objectstack/spec is not installed in either container. It is installed in this worktree, so both claims were re-derived from the artifact rather than inherited. Both hold.

claim, as dispatched re-measured here verdict
ComponentPropsMap['object-kanban'] refuses allowCollapse by name not in .shape; safeParse returns unrecognized_keys whose keys array names allowCollapse, and the message names it in prose confirmed
quickAdd parses but is dropped parses green and is kept in the parse output — the strict map does declare it. The drop is at the renderer, not at the spec: the control is gated on an onQuickAdd runtime slot and nothing on the object-kanban path supplies one confirmed, with the mechanism stated precisely

⚠️ That second row is the one nuance worth reading: "parses but is dropped" is true, but the dropping half happens downstream of validation. The card's own body says the same thing; the one-line summaries compress it in a way that could be read as "the spec drops it", which it does not.

Line addresses were re-derived by content, never by line number, as instructed. They happened to still be :929, :942 and :944, but nothing in this change depends on that.

The ruling was verified on its own card rather than assumed: objectui#8285 is open, and the batch-91 ruling recorded on it stands — option B, the key retires from object-kanban and stays on the KanbanRenderer component where a React host can supply the function. Its spec half is filed cross-repo and has not landed, which is exactly why the key still parses today.

⭐ Every row re-measured, not just the two named

Two of eleven rows being wrong is not evidence the other nine are right, so all eleven were probed. Instruments: ComponentPropsMap['object-kanban'] from the installed artifact for the contract half; OBJECT_KANBAN_INPUTS in packages/plugin-kanban/src/index.tsx plus occurrence counts in that package's sources for the honoured half.

# row in the strict map's shape parses declared in OBJECT_KANBAN_INPUTS honoured by the board verdict
1 objectName yes yes yes yes correct
2 groupBy yes yes yes yes correct
3 columns yes yes (both arms) yes yes correct
4 titleField yes yes yes yes correct
5 cardFields yes yes yes yes correct
6 filter yes yes yes yes correct
7 limit yes yes yes yes correct
8 quickAdd yes yes NO NO wrong — removed
9 coverImageField yes yes yes yes correct
10 allowCollapse NO refused by name NO NO wrong — removed
11 conditionalFormatting yes yes (both dialects) yes yes correct

Controls, so the two zeroes are readings rather than broken probes. On the parse probe, ten of eleven rows returned green against the single refusal — a dead probe returns no greens. On the occurrence probe, allowCollapse has zero mentions anywhere under packages/plugin-kanban/src while every other row key has non-zero, and onQuickAdd has zero occurrences in ObjectKanban.tsx against six for onCardClick in the same file on the same query.

Two rows carried claims specific enough to be worth checking separately, and both survived:

  • columns promises a { id, title } array or a bare-string array. Both arms parse green, as does a lane carrying the full member set.
  • conditionalFormatting promises a native { field, operator, value } dialect or a spec { condition, style } one. Both parse green. ⚠️ Worth flagging because OBJECT_KANBAN_INPUTS spells the second dialect differently in its own description; the document's spelling is the one the mirror declares and the one the renderer's tests exercise, so the document is right here and no change is owed.

⇒ Nine rows correct, two wrong, and the two wrong ones are exactly the two the card named. Nothing outside that table was touched.

The other face, deliberately untouched

@object-ui/types still declares both keys on its mirror of this face (packages/types/src/objectql.ts, packages/types/src/zod/objectql.zod.ts). That half is objectui#8801 and is out of scope here by dispatch: its files collide with in-flight PR #9348, so it serialises behind that one. This change deliberately leaves the mirror alone, and the note added to the section points a reader at that card so the two faces stay visible to each other. Related history for the same key: objectui#7742 and objectui#8802.

⛔ The renderer is untouched. Both keys' runtime behaviour is correct and owned elsewhere.

Gates

Derived from the per-gate workflow files, not from package.json. ⚠️ Deviation worth recording: the dispatch said to derive the doc gates from .github/workflows/lint.yml's step list. They are not there — lint.yml runs pnpm lint, the entry-guard check, the upstream-port pin, the bash floor and pnpm check. The doc gates each own a separate workflow file, and that is where this list comes from. Exit codes were captured by redirect before any pipe.

gate instrument exit verdict line
Doc Snippet Types check-doc-snippet-types.mjs 0 805 covered blocks, 649 compiled, 0 failed — the gate that type-checks the edited JSON fence
Doc Example Types check-doc-example-types.mjs 0 124 blocks; every covered example compiles or fails exactly as its ledger row declares
Doc Component Types check-doc-component-types.mjs 0 188 docs, 1106 blocks, 897 type literals — every documented component type is registered
Doc Fence Languages check:doc-fences 0 227 documents, no unknown fence spelling hides a TypeScript block
Doc Example Id Check check-doc-example-ids.mjs 0 414 references all resolve in the catalog registry
Internal Docs Link Check check-doc-links.mjs 0 links valid across 17 scan roots
Docs Route Eager Closure check:docs-route-closure 0
Prompt component keys check-prompt-component-keys.mjs 0 every key taught as available is answered by a real renderer
Control Bytes check-control-bytes.mjs 0 7530 tracked text files scanned, clean
Line citation gate check-new-cross-file-line-citations.mjs 0 0 new citations
Changeset Presence check-changeset-presence.mjs 0 no changeset owed — 0 files are published source of a released package, 0 are a manifest whose published contract moved

⚠️ The two snippet gates first answered exit 2, PRECONDITION NOT MET — their own words: "I could not run", NOT "I ran and found errors", because the packages they resolve against were unbuilt. That is not a red gate and is not recorded as one. The scoped build the gate itself prescribes was run first (35 turbo tasks, all successful), and the numbers above are from the re-run after it.

Tests: every test in the tree that reads this document as its input was run — eleven files found by scanning for readers of the path, which is the same method scripts/markdown-test-inputs.mjs uses to decide whether markdown-only changes must run the shards. 11 files, 413 tests, all passing. All heavy runs went through the shared verify lock; its verdict line reads command-exit 0 with the parts joined by and-and, so the number covers every part.

Acceptance notes

  • No pin protects the two deleted rows from coming back. Noted, not filed. The natural taker exists: whoever lands objectui#8801 reads this same table. Adding a pin would mean a new test file plus a new row in the markdown-input ledger, which is outside the one-file surface this dispatch fenced, so it was deliberately not done.
  • The table documents nine of the thirteen keys the board declares. cardTitle, swimlaneField, grouping and data are read by the board but absent from the table. That is an omission, not a wrong row — nothing here teaches a key the runtime refuses — so it is out of this card's defect class. Noted, not filed.
  • titleField is documented as the card title field; the registry ledger calls it the legacy spelling of cardTitle, which wins when both are authored. The row is true as far as it goes and the key is honoured, so it is not in the defect class either. Noted, not filed.

Delivery posture

Draft, and it stays draft from this seat. Nothing here is flipped ready, enqueued, armed for auto-merge or merged. No needs:contract-review carrier: this change has no contract increment — @objectstack/spec untouched, the mirrors untouched, the renderers untouched.

Session, as a code span so it survives a body rewrite: session_01L5xpA5q533BgTTNADibEFt.


🤖 Generated with Claude Code

https://claude.ai/code/session_01L5xpA5q533BgTTNADibEFt


Generated by Claude Code

…ban table

`content/docs/api/schema-reference.md`'s `object-kanban` section listed two
keys an object-bound board does not honour, and one of them sat inside the
copy-paste JSON example.

Re-measured against the installed `@objectstack/spec` artifact, not inherited:

- `allowCollapse` is not in `ComponentPropsMap['object-kanban'].shape`, and
  `safeParse({ allowCollapse: true })` fails with `unrecognized_keys` naming
  the key. The strict map refuses it BY NAME, so a document written from that
  row does not merely go unread, it fails validation. Control: the other ten
  rows all parse green on the same probe, so the refusal is a reading.
  `@object-ui/plugin-kanban/src` has zero occurrences of the key, against
  non-zero for every other row key.
- `quickAdd` parses -- the strict map does declare it -- but the board never
  honours it: the Quick Add control is gated on an `onQuickAdd` runtime slot,
  `ObjectKanban.tsx` has zero occurrences of it against six for the control
  `onCardClick`, and it is absent from `OBJECT_KANBAN_INPUTS`. The wording is
  aligned with the retirement ruling rather than invented.

Deleting the example's line required dropping the now-dangling comma on the
`cardFields` line; the fenced block still compiles under the snippet gate.

A note in the shape the section already uses records why both keys are absent,
so the rows are not restored from the mirror, which still declares them.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01L5xpA5q533BgTTNADibEFt

os-sam commented Sep 13, 2026

Copy link
Copy Markdown
Collaborator Author

CI red — established as NOT this PR's, and ⛔ not ported. Standing down with reasons.

Two checks are red on head 541323fa. Neither names a file this PR touches, and this PR's diff is one file: content/docs/api/schema-reference.md.

The failures, and what they actually name

Doc Snippet Type Check — 649 blocks judged, 3 failed, all one signature (TS2740, a plain object literal missing find/findOne/create/update/… from DataSource<any>):

content/docs/guide/schema-rendering.md:99:29
content/docs/guide/schema-rendering.md:434:29
packages/react/README.md:73:29

Skill Example Check — 14 marked fences, 1 failed:

skills/objectui/guides/data-integration.md:304:26  TS18049: 'dataSource' is possibly 'null' or 'undefined'

Why it is not this PR's — measured, ⛔ not asserted

I checked the content on main's tip (7cbc7241) rather than reasoning from run timing:

main:content/docs/guide/schema-rendering.md   const dataSource = { user: {…}, stats: {…} }
                                              <SchemaRendererProvider dataSource={dataSource}>
main:packages/react/README.md                 const dataSource = { user: { name: 'John Doe' } }
                                              <SchemaRendererProvider dataSource={dataSource}>

⇒ the offending fences are already on main, untouched by this branch. The root cause is the renderer-seam narrowing (dataSourceDataSource | null | undefined) that landed with #9310 at 04:37Z; this PR is simply the first whose CI built types that can see it.

⚠️ A control complicated the picture and is recorded rather than smoothed over: PR #9351, which ran at 04:49Z — after #9310 merged — is green on both checks. So "the base branch is red" is ⛔ not cleanly established by run comparison; what is established is the content reading above, plus the two cards below. I am not claiming more than I measured.

Both halves are already carded — dedupe first, and it hit

half card state
the three doc fences objectui#9346"three fences that stopped compiling under the objectui#7912 narrowing" domain:ui · priority:p2 · pm:blocked
the skills guide fence objectui#9311PR #9352 (fix(skills): guard the DataSource read in the marked data-integration example) in flight

⇒ ⛔ No new card filed. Filing a third would be the duplicate this lane keeps carding.

⛔ Why I am NOT porting a fix into this PR

The standing rule is to port an existing fix rather than wait. I am declining here, deliberately, for two reasons that the rule does not cover:

  1. The docs half has no fix to port. objectui#9346 is pm:blocked with no PR — there is no change to carry.
  2. The skills half's fix lands on skills/**, a GOVERNED surface. Porting PR fix(skills): guard the DataSource read in the marked data-integration example #9352 into this PR would convert a one-file documentation change into a governed-surface PR, moving it off the merge queue and onto the terminal maintainer-merge path — ⛔ a materially worse outcome for this change, and it would also take another lane's in-flight work.

⇒ this PR waits for main to be repaired, then merges main and re-runs. It stays draft; ⛔ not flipped ready, ⛔ not enqueued.

⛔ What was NOT done, and will not be

⛔ No re-run (this is not a flake — it is a reproducible type error with a named cause). ⛔ No test skipped, disabled or quarantined. ⛔ No gate weakened. ⛔ No empty commit.

This PR's own gates are green

Type Check, Lint, Build Docs, Doc Component Type Check, Doc Example Id Check, Doc Fence Language Check, Internal Docs Link Check, Governed Surface Queue Guard, all three changeset gates — all success. check-clause2-carriers --pair 9353 reads exit 0. The four test shards were still in progress at this reading.

⚠️ A blocked p2 is holding a gate that every docs-touching PR must pass. That makes objectui#9346's pm:blocked state worth a second look by the domain:ui seat — raised here, ⛔ not re-graded by this seat, and ⛔ not this lane's card to move.

Seat: domain:spec @ objectui, os-sam, session session_01L5xpA5q533BgTTNADibEFt, 2026-09-13T05:2xZ.


Generated by Claude Code

os-sam commented Sep 13, 2026

Copy link
Copy Markdown
Collaborator Author

Chain update: objectui#9369 now fixes both halves of the main-side doc blocker

Recording this here because this PR sits behind the same chain, and because its own gate readings predate it.

objectui#9369 (domain:ui seat) carries Fixes #9308 and Fixes #9346, on the maintainer's 2026-09-13 ruling (verbatim 「同意」, option B), and is not draft. It moves the three DataSource fences that turned Doc Snippet Type Check red on main.

⚠️ Two readings that bear on this PR, stated with their limits:

  1. This PR's base is 7cbc7241; main is now 69aa9c01. The gate table in the body — including Doc Snippet Types exit 0, 0 failed — was measured on this branch's tree at that older base, before objectui#9310's narrowing met the fences. A pull_request run resolves the merge ref, so a fresh run picks up main's current content regardless of this branch.
  2. NOT MEASURED by this seat: this PR's current check conclusions. I have not read them, so I am ⛔ not asserting it is red — only that its recorded green predates the cause and cannot be carried forward as live.

⇒ No action owed here and ⛔ nothing ported: the fence fix depends on objectui#9369's code half (the fences move to PredicateScopeProvider, which does not exist in this tree), and this PR's one file is content/docs/api/schema-reference.md — a different file from all three fences.

⭐ Also worth crediting: this PR's body is where the gate-derivation error was first caught — «the dispatch said to derive the doc gates from .github/workflows/lint.yml's step list. They are not there». That correction has since been adopted by the seat and propagated to every later dispatch order in this lane.

⛔ Still draft, ⛔ not enqueued. No needs:contract-review — correctly, this change carries no contract increment.


Generated by Claude Code

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

Labels

None yet

Projects

None yet

2 participants