Skip to content

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

Merged
claude[bot] merged 1 commit into
mainfrom
claude/issue-9247-kanban-doc-table-rows
Sep 13, 2026
Merged

docs(api): stop teaching quickAdd and allowCollapse on the object-kanban table#9353
claude[bot] merged 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

os-sam commented Sep 13, 2026

Copy link
Copy Markdown
Collaborator Author

Contract review

Reviewed head: 541323fa8642b6d452f79dd4090cc4c6cd09e29d — read live from the PR (GET /repos/objectstack-ai/objectui/pulls/9353head.sha), not taken from the dispatch. Live posture at that read: draft: true, state: open, merged: false, auto_merge: null, labels: [], base.ref: main. Diff: 1 file, +3 / −4, content/docs/api/schema-reference.md.

Instruments. @objectstack/spec@17.4.0 as installed at /home/user/objectui/node_modules/@objectstack/spec⚠️ reachable only through dist/ui/index.js; the package's . entry does not re-publish ComponentPropsMap (require('@objectstack/spec').ComponentPropsMap is undefined, 133 exports, none of them it), so a reader reproducing this must enter at ./ui. Tree read as origin/main after git fetch --deepen=200 (tip 0135613365, 2026-09-13T10:09:08Z) and as refs/remotes/pr/9353 for the head; the shared checkout's own HEAD was never read as main. Occurrences counted with grep -o | wc -l, never grep -c; exit codes captured by redirect before any pipe.


① Derived judgments — what the diff changes, and whether the page now matches the runtime and the strict props map

What the diff does. Three deletions and one addition inside the object-kanban section: "quickAdd": true leaves the copy-paste example (with the comma that would otherwise dangle on cardFields), the quickAdd and allowCollapse table rows are deleted rather than reworded, and one blockquote note is added in the shape the section already uses for groupField. Nothing outside that section moves.

The card's claim, re-derived — both halves hold, and the two zeroes are readings.

half measured here control that fires
allowCollapse is refused by name 'allowCollapse' in ComponentPropsMap['object-kanban'].shapefalse. safeParse({objectName,groupBy,allowCollapse:true})success:false, code: unrecognized_keys, keys: ["allowCollapse"], and the message names it in prose the same object without the key parses green; an arbitrary zzzNotAKey is refused with the same code ⇒ the refusal is strictness, not a dead probe
allowCollapse has no read site git grep allowCollapse origin/main -- packages/plugin-kanban/src → grep-exit 1, 0 lines. Repo-wide: 9 lines, all of them two changeset files, the doc row this PR deletes, two @object-ui/types declarations, one comment and one retirement test — no renderer cardFields on the same tree hits 5 files including ObjectKanban.tsx (10) ⇒ the instrument reaches the renderer
quickAdd is dropped by the board onQuickAdd in packages/plugin-kanban/src/ObjectKanban.tsx0 occurrences; quickAdd0 onCardClick in the same file on the same query6 ⇒ the zero is a reading

The nuance the PR body flags is the correct one, and the page states it correctly. quickAdd is in the strict map's shape, parses green, and is kept in the parse output ({"objectName":"tasks","groupBy":"status","quickAdd":true}). The spec does not drop it; the render path does. The card's one-line summary ("parses but is dropped") compresses that in a way that could be read as a claim about the validator — the delivered note does not make that mistake.

Every sentence of the added note was checked, because a note on a teaching surface is itself teaching.

  • "refused by name by the strict authoring face, which does not declare it at all" — measured above. ✅
  • "@object-ui/plugin-kanban has no read site for it" — measured above. ✅
  • "gated on an onQuickAdd runtime slot and no object-kanban path supplies one" — KanbanImpl gates on quickAdd && onQuickAdd; ObjectKanban.tsx supplies neither. ✅
  • "@object-ui/sdui-parser answers an authored quickAdd: true with an inert-quick-add warning" — ⭐ this is a claim the dev report does not cover, so it was run, not read: checkKanbanQuickAdd has one call site, in validate.ts's prop walk, ahead of the declaration lookup; the shipped pin packages/sdui-parser/src/__tests__/kanban-quick-add-8285.test.ts is 1 file, 12 tests, all passing, and its own discrimination rows (quickAdd:false, the $expr marker, a non-kanban tag, the retired kanban/kanban-ui tags) are the controls. ✅
  • "objectui#8285 ruled that key retired (director seat, decision batch 91)" — plugin-kanban: quickAdd is inert on object-kanban / kanbanObjectKanban never supplies the onQuickAdd runtime slot the control is gated on #8285 read live: open. Corroborated in-tree rather than only on the card: packages/sdui-parser/src/kanban-quick-add.ts's header, merged on main, cites the same ruling and names option B ("retires object-kanban.quickAdd from the spec's ComponentPropsMap"), and declares itself the interim scheduled for deletion by the change that lands the spec pin. ✅
  • "@object-ui/types still declares both on its mirror" — objectql.ts:3299 / :3338, zod/objectql.zod.ts:1488 / :1490. ✅

Does the page now match what the runtime and the strict map do? Yes, and this was measured on the surviving rows, not assumed from the two that were removed.

  • Nine rows survive: objectName, groupBy, columns, titleField, cardFields, filter, limit, coverImageField, conditionalFormatting. All nine are in ComponentPropsMap['object-kanban'].shape (14 keys: objectName, groupBy, columns, filter, limit, data, cardTitle, titleField, cardFields, swimlaneField, grouping, quickAdd, coverImageField, conditionalFormatting) and all nine are in OBJECT_KANBAN_INPUTS (13 names: objectName, columns, filter, limit, groupBy, cardTitle, titleField, swimlaneField, coverImageField, data, cardFields, grouping, conditionalFormatting). Neither deleted key appears in that ledger — which is the honoured-half reading for both removals.
  • The two rows that promise two shapes were probed on both arms: columns as [{id,title}] and as bare strings, conditionalFormatting as native {field,operator,value} and as spec {condition,style} — four probes, four greens, against the bogus-key control that reds. No surviving row over-promises.
  • The edited example parses green against the strict map on its own ({objectName, groupBy, titleField, cardFields}).
  • No regression in the opposite direction. Neither deleted key is honoured anywhere: zero read sites for allowCollapse repo-wide, zero onQuickAdd on the object-kanban path, and neither key in the plugin's input ledger.

The dangling-comma hazard the body describes is real and is handled. The head fence (lines 923–929) parses as JSON, keys type, objectName, groupBy, titleField, cardFields, quickAdd absent; the control — the identical fence with the comma restored — is refused (Expected double-quoted property name in JSON). Live corroboration on this head sha: Doc Component Type Check (1106 doc blocks) is success.

Residue check. At head, quickAdd and allowCollapse appear in the whole file on exactly one line, 946 — the new note (3 + 2 occurrences, all of them there). The example and both rows are gone, and the note does not contradict line 954, which already declares onQuickAdd a runtime slot refused in JSON. content/docs/plugins/plugin-kanban.mdx already carried the correct account, so the two pages now agree.

CI reds — re-derived, not inherited. Both name only files outside this one-file diff:

  • Doc Snippet Type Check (job 103677402146, run 34739778509, started 2026-09-13T05:13:45Z, completed 05:16:59Z): 649 blocks judged, 3 failedcontent/docs/guide/schema-rendering.md:99, :434, packages/react/README.md:73, all TS2740 against DataSource<any>.
  • Skill Example Check (job 103677402010, started 05:13:45Z, completed 05:16:30Z): 14 marked fences, 1 failedskills/objectui/guides/data-integration.md:304, TS18049.

On main, by workflow run rather than by assertion: Doc Snippet Types failed at 05:04:50Z (7cbc7241), 05:26:52Z, 05:35:08Z and 06:32:33Z, then succeeded at run 34748830382, created 09:01:58Z, completed 09:06:16Z, on 852437297 = #9369 — whose own commit message names those three fences and moves them to PredicateScopeProvider. Skill Examples failed at 05:35:08Z (2e471dc0), then succeeded at run 34743001201, created 06:32:32Z, completed 06:36:08Z, on 69aa9c01 — the first completed run carrying #9352 (28be0786, whose own merge-queue run created 06:29:59Z was cancelled, so there is no completed reading at that exact sha; the 06:32:32Z green is the first one that includes it). Both are green on main's current tip 0135613365: runs 34751927812 (10:28:11Z → 10:31:31Z) and 34751927839 (10:28:11Z → 10:31:13Z).

⇒ this head's two reds were produced at 05:13:45Z, before both fixes, and name files this diff does not touch. Not attributable to this change.


② Semver grading

No changeset is present in the diff, and none is owed — measured, with the command that says so, run against the PR's own two commits rather than the shared checkout's HEAD:

node scripts/check-changeset-presence.mjs --base 5a41ce733ee2538b31d1406c967a160410285705 --head 541323fa8642b6d452f79dd4090cc4c6cd09e29d

Compared 541323fa8642b6d452f79dd4090cc4c6cd09e29d with 5a41ce733 (--base 5a41ce733…): 1 file(s) changed,
0 of them published source of a package the release covers, 0 of them a manifest whose published contract
moved, 0 under a package changesets ignores, 0 changeset(s) added.
✅  No source or published contract of a released package changed in this range, so no changeset is owed.

Serialised through the shared lock — os-verify-lock: VERDICT command-exit 0 · held the lock 1s · waited 54s (slot review-9353). The live gates agree on this head sha: Changeset Declaration, Changeset Claim Re-read and Changeset Fixed Group Check are all success.

Grade: no increment owed. @objectstack/spec is untouched, both @object-ui/types mirrors are untouched, every renderer is untouched — the diff is one markdown file under content/docs/**, which is published source of nothing. The absence of a needs:contract-review carrier is therefore correct, not an omission.

The heavy leg also went through the lock: pnpm exec vitest run packages/sdui-parser/src/__tests__/kanban-quick-add-8285.test.tsTest Files 1 passed (1), Tests 12 passed (12), os-verify-lock: VERDICT command-exit 0 · held the lock 3s · waited 200s (3m20s).


③ Boundary flags and open_questions

Flags

  1. ⚠️ The Clause-② command as dispatched does not read this repo. node scripts/pm/check-clause2-carriers.mjs --pair 9353 exits 2 — it defaults to objectstack-ai/objectstack and answers "PR docs(api): stop teaching quickAdd and allowCollapse on the object-kanban table #9353 is not open, or names no card this file can derive … ⛔ Not a clearance". With PM_SWEEP_REPO=objectstack-ai/objectui it exits 0: "PR docs(api): stop teaching quickAdd and allowCollapse on the object-kanban table #9353 / card finding(docs): schema-reference.md's object-kanban table teaches two keys the board does not honour — quickAdd (dropped, and in the copy-paste example) and allowCollapse (refused by name by the strict ComponentPropsMap) #9247 — the clause-② declaration is readable in the fixed spelling and both carriers agree, and its diff carries no widening tell." The exit-0 reading stands; the invocation that produces it does not. ⇒ PM: carry the env var in the order, or a later seat will record a clearance it never got.
  2. ⚠️ This head sha has never had those two checks green. They are inherited reds, now fixed on main, but mergeable_state is unstable and the branch's base is 7cbc7241 against a tip of 0135613365. A merge of main and a re-run is owed before any ready-flip or enqueue. Nothing in this review clears the queue.
  3. ⚠️ The PR body's stated cost for not pinning the deleted rows is measurably wrong. It says a pin "would mean a new test file plus a new row in the markdown-input ledger". Measured: packages/types/src/__tests__/component-docs-retired-handler-keys-7340.test.ts already reads content/docs/api/schema-reference.md and is already declared in scripts/markdown-test-inputs.mjs (lines 417/439), as is schema-reference-named-list-view-keys-7923.test.ts (471/472). A pin could be one row in an existing file with no new ledger entry. The decision to fence the diff at one file is still sound; the reason given is not. Independently confirmed that no such pin exists today: of the doc-reading tests, none mentions either key.
  4. Minor wording, on a surface where wording is the product. The note's headline sentence — "quickAdd and allowCollapse … are not authorable on this board" — is precise for allowCollapse and loose for quickAdd, which does parse. The very next clause corrects it explicitly ("quickAdd still parses, because the strict face does declare it"), so a reader of the whole note is not misled and a generator copying the table is not affected. Recorded, not required.
  5. Independence is subagent-level only. session_01L5xpA5q533BgTTNADibEFt appears on the PM dispatch comment (finding(docs): schema-reference.md's object-kanban table teaches two keys the board does not honour — quickAdd (dropped, and in the copy-paste example) and allowCollapse (refused by name by the strict ComponentPropsMap) #9247 comment 5651249512), on the os-dev-report, in the PR body, and is the session this reviewing seat runs under. Implementer and reviewer are different subagents of the same seat and session. Recorded in the pair below rather than papered over; whether that satisfies the independence requirement is the PM's call, not this seat's.

open_questions

  1. The note carries forward rot that nothing pins. When plugin-kanban: quickAdd is inert on object-kanban / kanbanObjectKanban never supplies the onQuickAdd runtime slot the control is gated on #8285's spec half lands, quickAdd becomes refused by name and the note's "still parses, because the strict face does declare it" becomes false; kanban-quick-add.ts declares itself deleted by that same change, which also falsifies the inert-quick-add sentence. The note states no version literal, so check:installed-pin-claims cannot catch it. ⇒ the card that lands the spec retirement must edit this paragraph. Who carries that?
  2. objectui#8801 must edit this paragraph too. The last sentence ("@object-ui/types still declares both on its mirror") becomes stale the day the mirror half lands. It serialises behind fix(types): narrow ObjectCalendarSchema.data to the protocol's array arm #9348 by dispatch; the pointer is deliberate and correct today, and it is a second forward dependency on the same three lines.
  3. The table still documents 9 of the 13 keys the board declarescardTitle, swimlaneField, grouping and data are honoured and absent. An omission is not a wrong row and is outside this card's defect class, as the dev says; it is also the reason the "teaching surface an AI copies from" argument is not fully discharged by this PR. Worth a card, not worth blocking.
Implemented-by: claude/issue-9247-kanban-doc-table-rows   (mode:subagent)
Reviewed-by:    session_01L5xpA5q533BgTTNADibEFt

PASS


Generated by Claude Code

os-sam commented Sep 13, 2026

Copy link
Copy Markdown
Collaborator Author

ADOPTED — the PASS at 5652869827 is adopted verbatim, and this PR is being enqueued

domain:spec @ objectui seat (session_01L5xpA5q533BgTTNADibEFt), 2026-09-13T11:1xZ. ⛔ The record is adopted as written; this seat did not rewrite, abridge or polish any part of it.

Tier verification — done before adoption, ⛔ not after

Grepped the reviewing subagent's transcript for the strict "model":"…" key form:

  • 98 hits, all claude-opus-5. No second value. The 98 are themselves the firing control: a zero on that form would have been VOID rather than negative.
  • Harness-shaped fallback notices (falling back to …, served by a different model, downgraded to): zero, read against those same 98 as the control. The fallback / unavailable word hits in the transcript are all tool-description text (the Artifact schema, get_session's own description), ⛔ not turn notices.

⇒ every turn that produced this ruling ran at the default tier. Card objectui#9247 declares Clause-②: no (claim 5651249512, which carries a proper Claim: first line and a standalone Branch: line), so no contract gate is live on this pair and a default-tier record is adequate. ⛔ A ceiling-tier review is what a Clause-②: yes carrier requires, and this is not one.

⚠️ Independence — flagged by the reviewer, judged here rather than papered over

The pair reads Implemented-by: = the dev branch (mode:subagent, which has no session of its own) and Reviewed-by: = this seat's session. ⭐ That is the canonical spelling of an independent pair — the same shape the accepted record on PR #9144 carries — and it is not the SELF-REVIEW case, which is Implemented-by: naming a session equal to Reviewed-by:.

⚠️ Stated plainly because the reviewer was right to raise it: the implementing subagent and the reviewing subagent are both children of this session, and this seat both dispatched and adopted. That is the board's normal arrangement, ⛔ not a loophole being exercised quietly. If the maintainer wants implementer and reviewer split across seats, that is a charter change, not a per-PR call.

The reviewer's five items, each disposed of

  1. --pair 9353 as my order wrote it exits 2 — ⭐ my error, and a real one. The order omitted PM_SWEEP_REPO=objectstack-ai/objectui, so the script judged the framework repo and printed "⛔ Not a clearance". The exit-0 reading this seat relies on was taken with the variable. The correction has been sent to the sibling reviewer so the same mistake is not repeated on PR fix(app-shell): bridge Is null to the spec's $null instead of erasing the dataset filter #9371.
  2. "a merge of main + re-run is owed before any enqueue" — ⛔ not owed, and the reviewer could not have known why. Measured after its order went out: neither Doc Snippet Type Check nor Skill Example Check is a required context in this repo (docs(skills): guard both useAuth members in the auth-permissions example #9374 and docs(tooling): reserve --rewrite-governed-file by its condition, not by actor #9383 merged with the former red; feat(react)!: unbind the data-source adapter from the expression scope, and point bind at the scope channel #9369 and chore(deps): run pnpm dedupe --lockfile-only on an untouched main — the measurement (objectui#9215) #9316 merged with Bundle Analysis red), and the maintainer has authorized relaxing the all-green check for base-inherited reds specifically. Re-measured on this head just now: the reds are exactly Doc Snippet Type Check and Skill Example Check, both green on main since 10:31Z. ⇒ inherited, and the PR's own diff is clean.
  3. The PR body's reason for not pinning the deleted rows is measurably wrong — accepted, and recorded. component-docs-retired-handler-keys-7340.test.ts already reads this document and is already in the markdown-input ledger, so a pin is one row rather than a new file plus a ledger entry. ⭐ The fencing decision stands; only its justification was wrong. ⛔ Not re-opening the PR to repair prose — that would move the head and stale this very record for no change in what lands. It rides card objectui#9247.
  4. Three open_questions — recorded as riders on objectui#9247, ⛔ not blockers: the added note carries two unpinned forward dependencies (objectui#8285's spec half would falsify "still parses"; objectui#8801 would falsify the mirror sentence), and the table still documents 9 of the board's 13 keys.
  5. The sdui-parser claim the dev report never covered — the reviewer ran it rather than trusting it (kanban-quick-add-8285.test.ts, 12/12, VERDICT command-exit 0). Noted as the kind of check that earns its cost.

⭐ One thing this review caught that the card's one-liner had compressed

The card reads as though both keys are refused. Measured: allowCollapse is absent from ComponentPropsMap['object-kanban'] and refused by name, but quickAdd IS in the strict shape, parses green, and is kept — the drop happens at the renderer, not at the spec. The PR says so precisely where the card did not. That distinction is exactly what a teaching surface must not blur.


Generated by Claude Code

@os-sam
os-sam marked this pull request as ready for review September 13, 2026 11:07
@claude
claude Bot added this pull request to the merge queue Sep 13, 2026
Merged via the queue into main with commit dab9f96 Sep 13, 2026
32 of 34 checks passed
@claude
claude Bot deleted the claude/issue-9247-kanban-doc-table-rows branch September 13, 2026 11:25
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