Repository navigation
types: ObjectKanbanSchema and ObjectCalendarSchema declare no filter (and no sort) — the fourth face of the key #7712 declares everywhere else #8174
Description
Activity
- addeddomain:specobjectui spec stream: fix lands on packages/types, schema corpus or spec pin coupling — spec laneobjectui spec stream: fix lands on packages/types, schema corpus or spec pin coupling — spec lane
on Sep 6, 2026 Claim: PM loop round 1
Session:session_012W3vMLTFY9SPr2LyxhSeYi
Branch:claude/issue-8174-kanban-calendar-declare-filter-sort
Worktree:objectui-issue-8174
Domain:domain:spec
File surface:packages/types/src/objectql.ts(theObjectKanbanSchemaandObjectCalendarSchemainterface bodies only) ·packages/types/src/zod/objectql.zod.ts(the same two mirrors only, if parity requires it) ·.changeset/(stop on breach; explain in the report)
Container & model:M,mode:subagent,model: opus—TIER_DEFAULT. The card leaves one judgement to the taker (is the declaration worth it given #7927's index-signature ceiling), so ⛔ not the floor.dispatch-gates.mjs --tiercannot serve objectui paths (refuses cross-repo, exit 2); judged from content.
Clause-②: yes
Thread-read: none (zero comments on this card at claim time)
Serial constraints cleared:⭐ PREMISE VERIFIED ON CURRENT origin/main c03d03bb2, ⛔ not inherited from the card's 9bfd618 reading. The card is written as "after #7712 lands"; #7712's work IS on main — schema.filter is read at packages/plugin-kanban/src/ObjectKanban.tsx (2 hits) and packages/plugin-calendar/src/ObjectCalendar.tsx (7 hits), with objectName (35 hits) as the positive control that the grep reaches those files. And the defect still stands: neither ObjectKanbanSchema nor ObjectCalendarSchema declares filter or sort. FILE SURFACE: objectql.ts and zod/objectql.zod.ts were freed when PR #8758 MERGED (~05:2xZ) — main is now c03d03bb2 and #8765/#8766/#8768 have landed too. ⚠️ ONE REGION-LEVEL OVERLAP declared rather than assumed away: objectui#7917 (dispatched this round) also edits zod/objectql.zod.ts — but its region is the object-tree arm, and this card's is the ObjectKanban/ObjectCalendar mirrors. Disjoint regions of one file, under this lane's file→region granularity ruling (5551274423); the four substitute disciplines apply and conflicts go to the merge queue, ⛔ not to PM hand-ordering. ⛔ Still held by PR #8763: zod/layout.zod.ts, zod/form.zod.ts, layout.ts, form.ts, zod-mirror-parity.test.ts.
Generated by Claude Code
os-dev-report
{
"issue": 8174,
"status": "done",
"branch": "claude/issue-8174-kanban-calendar-declare-filter-sort",
"pr": "#8788",
"premise_still_valid": true,
"summary": "Declaredfilteron ObjectKanbanSchema andfilter+sorton ObjectCalendarSchema, on both published faces of @object-ui/types (the TS interface in packages/types/src/objectql.ts and its hand-written zod mirror in packages/types/src/zod/objectql.zod.ts), spelled exactly as ObjectGanttSchema spells them so the views' query vocabularies cannot fork. Added a pin that asserts membership on the mirror's own .shape rather than on parse acceptance, uses invariant type equality so a member falling back to the index signature reads as a failure, and pins the objectui#7927 ceiling as UNCHANGED rather than claiming it away. Changeset is minor for @object-ui/types. PR is DRAFT with needs:contract-review hung on it; not flipped ready, not enqueued, no auto-merge.",
"pm_assumption_falsified": "The re-dispatch stated the previous killed attempt 'pushed nothing' and 'there is no WIP to recover'. Half true and half false, and the false half mattered. The branch was indeed empty of commits (remote ref sat at base fb3a101, the empty-branch routing probe). But the worktree /home/user/objectui-issue-8174 already existed and carried UNCOMMITTED WIP on disk: modified objectql.ts, modified zod/objectql.zod.ts, and an untracked 350-line pin. I did not 'start clean' and discard it. I read it, re-derived every factual claim in it against current origin/main independently, found all of them to hold, and committed it as the implementation. Had I followed the instruction literally, a complete and correct implementation would have been deleted and rebuilt.",
"the_7927_call": {
"verdict": "PROCEED — the edit is worth it and must NOT wait behind objectui#7927",
"reasoning": [
"1. objectui#7927's ceiling caps the KEY dimension only. A MISSPELLED key stays admitted on both faces either way. Verified on origin/main: BaseSchema (packages/types/src/base.ts:70-468) ends in[key: string]: anyat :467. The pin asserts that ceiling is unchanged rather than claiming otherwise.",
"2. The VALUE dimension is NOT capped, and that is what declaring buys.filter: 'status = open'type-checked green through the index signature and parsed green through the mirror's .passthrough(); it is now a type error and a named refusal at the key. That is a measurable acquisition, not editor completion — which is more than the card credits.",
"3. Thesorthalf is the sharpest case and is a LIVE silent failure, not a hypothetical. objectui#8221 retired the legacy string clause: convertSortToQueryParams no longer admits a string in its signature and returns undefined for one after reporting the retired spelling (verified at packages/core/src/utils/sort-query.ts:133 and :141 on fb01022). Sosort: 'start_date asc'on an object-calendar node type-checked green, parsed green, and then drew an UNSORTED calendar with nothing refusing it anywhere. Declaring the member is what makes that retirement audible at the authoring boundary.",
"4. The ordering argument runs OPPOSITE to 'wait behind it'. If objectui#7927 ever tightens BaseSchema it tightens the KEY dimension — and a tightening that lands while these three members are still undeclared turns every CORRECTLY authored filter/sort node into a refusal. Declaring them is a prerequisite for that card, not a duplicate of it.",
"5. Precedent: objectui#7322 weighed this same trade on this same interface under this same ceiling (which it predates but does not escape) and went ahead. Same interface, one key over."
]
},
"member_lists_retaken": {
"commit_read": "fb0102271b86848ae6ef05aa55b1a3c78bfb03cd (origin/main at read time; NOT the card's 9bfd618, and NOT the PM's c03d03b)",
"method": "full member list pulled from the interface BODY by brace matching with comments stripped — the returned list is its own control that the extraction works; the card's :2744 / :2698 anchors are both stale and were not reused",
"ObjectKanbanSchema": {
"anchor": "packages/types/src/objectql.ts:2779-2900",
"members_before": ["type", "objectName?", "groupBy", "groupField?", "limit?", "titleField?", "cardFields?", "quickAdd?", "coverImageField?", "allowCollapse?", "conditionalFormatting?"],
"count_before": 11,
"verdict": "nofilter, nosort— the defect stands on current main"
},
"ObjectCalendarSchema": {
"anchor": "packages/types/src/objectql.ts:2733-2774",
"members_before": ["type", "objectName?", "data?", "staticData?", "startDateField?", "endDateField?", "titleField?", "defaultView?"],
"count_before": 8,
"verdict": "nofilter, nosort— the defect stands on current main"
},
"ObjectGanttSchema_precedent": {
"anchor": "packages/types/src/objectql.ts:2415-2728, 47 members",
"spelling_copied": "filter?: any[] (:2725) and sort?: SortConfig[] (:2727); mirrors at zod/objectql.zod.ts:1052-1053 are z.array(z.any()) and z.array(SortConfigSchema)"
}
},
"read_census_retaken": {
"commit_read": "fb0102271b86848ae6ef05aa55b1a3c78bfb03cd",
"packages/plugin-kanban/src/ObjectKanban.tsx": {
"schema.filter": 2,
"schema.sort": 0,
"positive_control_schema.objectName": 26,
"positive_control_bare_objectName": 35,
"live_sites": "$filter: schema.filter on the dataSource.find call, and the same key again in that effect's dependency list"
},
"packages/plugin-calendar/src/ObjectCalendar.tsx": {
"schema.filter": 7,
"schema.filter_live": 2,
"schema.filter_in_docblock": 5,
"schema.sort": 2,
"positive_control_schema.objectName": 19,
"positive_control_bare_objectName": 29,
"live_sites": "$filter: schema.filter and $orderby: convertSortToQueryParams(schema.sort) on the dataSource.find call, and both again in that effect's dependency list"
},
"note": "The PM's figures (kanban 2, calendar 7, control 35) reproduce exactly. The kanban ZERO for schema.sort is the measured premise for leavingsortoff that interface, and the pin holds it so the board acquiring an $orderby turns red BEFORE the faces fork again."
},
"other_two_faces_verified": {
"spec": "@objectstack/spec 17.3.0 ComponentPropsMap — object-kanban declares 13 keys INCLUDING filter and EXCLUDING sort; object-calendar declares 9 keys INCLUDING both filter and sort. objectName present on both as the non-vacuity control.",
"registration_inputs": "plugin-kanban/src/index.tsx:523 { name: 'filter', type: 'array' }; plugin-calendar/src/index.tsx:400-401 { name: 'filter', type: 'array' } and { name: 'sort', type: 'array' }."
},
"tests": "PIN: packages/types/src/tests/kanban-calendar-filter-sort-8174.test.ts. Proved COMPILED, not assumed: packages/types' package tsconfig excludes the test tree, buttype-checkruns a third program (tsconfig.test.json) that includes it —tsc -p tsconfig.test.json --listFileslists the pin at line 413, andtsc --noEmit --listFiles(main program) lists it 0 times. The PM's reading is confirmed by measurement. ABLATION, three legs, each proving the mutation reached disk before its run was read (before/after anchor counts plus a git hash-object comparison), each restored viagit checkout HEAD -- PATHunder atrap ... EXIT INT TERMwith absolute paths, and each restore proved by an EMPTYgit diff HEADplus a blob hash equal to the HEAD blob (never by a bare exit code). LEG 1 — delete ObjectCalendarSchema.sort from objectql.ts (anchor count 4 to 3, hash d260d8ad -> c8ac23e8):pnpm --filter @object-ui/types type-checkexit 2 with 5 errors, 3 x TS2344 on the invariant-equality pins and 2 x TS2578 unused @ts-expect-error (the objectui#8221 retired string clause, and the badordervalue) — the directives going UNUSED is what makes them pins rather than restatements. LEG 2 — deletesortfrom the calendar zod mirror (anchor 4 to 3, hash 4db28ef6 -> 36a8b41e): vitest exit 1, 4 failures (shape membershipexpected [ Array(28) ] to include 'sort', plus the three at-the-key refusals). LEG 3, THE ONE WORTH REPORTING — same mutation as leg 2 but judged by tsc instead of vitest: exit 2, one error,zod-mirror-parity.test.ts(2808,14): error TS2322: Type '\"objectql.zod.ts#ObjectCalendarSchema\"' is not assignable to type 'never'. Leg 2 alone would have read as 'the mirror half is covered only by my own new file' because the parity ledger stayed GREEN under vitest; it does not. The ledger's unmirrored-declared half is a TYPE-level operator, so it lands on tsc and is invisible to the test runner. The mirror edit is therefore MANDATORY, and mandatory in a way a vitest-only ablation cannot see. A FIRST attempt at leg 1 was a no-op (the body-slice anchor was off by one newline, nothing changed on disk) and the script's own before/after count REFUSED to run the leg and exited 92 rather than reporting a passing ablation — reported because that is exactly the failure mode that otherwise reads as green.",
"gates": {
"note": "scripts/pm/dispatch-gates.mjs refuses objectui paths (cross-repo, exit 2) as the dispatch said, so this list was hand-derived from objectui's root package.json scripts and .github/workflows/. Every exit code captured ascmd > file 2>&1; EXIT=$?, never through a pipe. Heavy runs went through the container's shared verify lock with OS_VERIFY_LOCK_SLOT=objectui-8174; all four acquisitions were granted at 0s wait. vitest was run FROM THE REPO ROOT with paths as positional args, neverpnpm --filter PKG exec vitest FILE.",
"pnpm --filter @object-ui/types type-check": 0,
"pnpm exec vitest run packages/types/": "0 — 156 test files, 3091 tests passed",
"pnpm exec vitest run packages/plugin-kanban/ packages/plugin-calendar/ apps/console/src/tests/registry-inputs-spec-parity.test.ts packages/app-shell/.../block-config-schema-parity-8216.test.ts packages/app-shell/.../block-config.test.ts": "0 — 70 test files, 711 tests passed",
"pnpm --filter @object-ui/types build": "0 — tsc + vite build + dist completeness, 128 emitted files verified",
"pnpm --filter @object-ui/types lint": "0 — 271 warnings (all pre-existing no-explicit-any across the package), 0 errors",
"node scripts/check-changeset-fixed.mjs": 0,
"node scripts/check-changeset-no-major.mjs": 0,
"node scripts/check-control-bytes.mjs": "0 — 6982 tracked text files scanned; plus an independent grep -naP control-byte sweep over the four changed files, 0 hits",
"node scripts/check-spec-symbol-derivation.mjs": 0,
"node scripts/check-doc-component-types.mjs": 0,
"node scripts/check-unreferenced-sources.mjs": 0,
"node scripts/check-element-data-source-declaration.mjs": 0,
"node scripts/check-governed-queue-guard.mjs --test (four changed paths)": "0 — NOT GOVERNED, 4 paths against 5 governed surfaces, none matched",
"NOT MEASURED (prerequisite not met, whole-tree build required — CI owns these)": "check:doc-snippets exit 2, check:doc-examples exit 2, check:sdui-registration-pins exit 2 (each printed the build it wants), check:readme-exports exit 1 (its own text is 'run pnpm build first' for 5 documented types across 4 packages, followed by a collapsed-population report). This worktree builds only the affected package, so all four are reporting a missing prerequisite, not a verdict on this diff. Read as NOT MEASURED — neither green nor red."
},
"line_budget": {
"measure": "git diff --numstat origin/main...HEAD (three-dot, from the merge base) at HEAD a9c30cb",
"merge_base": "fb0102271b86848ae6ef05aa55b1a3c78bfb03cd",
"total": "4 files changed, 486 insertions, 0 deletions",
"per_file": {
"packages/types/src/objectql.ts": "+62 / -0",
"packages/types/src/zod/objectql.zod.ts": "+35 / -0",
"packages/types/src/tests/kanban-calendar-filter-sort-8174.test.ts": "+350 / -0 (new)",
".changeset/8174-kanban-calendar-filter-sort.md": "+39 / -0 (new)"
},
"note": "No skills/** in this diff, so no published-skill line ratchet applies. The three-dot measure is the load-bearing one: origin/main moved again DURING this run (to 5591f03, sibling PR objectui#8307 landing on plugin-kanban), so a two-dotgit diff origin/main HEADreads 9 files and attributes a sibling's work to this branch. Three-dot from the merge base reads 4."
},
"files_changed": [
"packages/types/src/objectql.ts",
"packages/types/src/zod/objectql.zod.ts",
"packages/types/src/tests/kanban-calendar-filter-sort-8174.test.ts",
".changeset/8174-kanban-calendar-filter-sort.md"
],
"out_of_bounds_respected": "packages/types/src/tests/zod-mirror-parity.test.ts was NOT edited and did NOT need editing — mirroring at the SAME requiredness as the interface (both members optional on both faces) leaves the ledger at zero drift for these pairs, confirmed twice: bytype-checkexit 0 with the change in place, and by ablation leg 3 showing the ledger DOES redden if the mirror falls behind. zod/layout.zod.ts, zod/form.zod.ts, layout.ts and form.ts (held by PR objectui#8763) are untouched. BaseSchema's index signature is untouched (objectui#7927). No other undeclared member on these two interfaces was touched (objectui#7742 / objectui#7780 are not this card).",
"deviations": [
"ADOPTED PRE-EXISTING WIP instead of starting clean, contrary to the re-dispatch's 'there is no WIP to recover'. The worktree existed with uncommitted edits to both target files plus an untracked pin. Every factual claim in it was independently re-derived on origin/main fb01022 before it was committed; all held. Deleting and rebuilding correct work would have been the worse deviation.",
"Merged origin/main once as instructed, at fb01022. One conflict, in packages/types/src/zod/objectql.zod.ts, in the kanbanlimitdescribe string — PR objectui#8776 had removed its stale ObjectKanban.tsx:264 source-line address. Resolved by taking origin/main'slimitline verbatim and re-attaching this branch'sfilterblock below it. Per the dispatch, conflicts go to the merge queue; none was hand-ordered. origin/main has since moved again to 5591f03; NOT re-merged (the instruction was to merge once).",
"REST was used for the label write (POST .../issues/8788/labels, the additive endpoint that does not touch existing labels) rather than MCP. First attempt returned HTTP 415 for a missing Content-Type; retried withContent-Type: application/jsonand got HTTP 200. Read-back confirms all three labels present:package: types,tests(both added by the repo labeler) andneeds:contract-review(mine) — the additive write did not strip the labeler's two.",
"PR body read back to the end after creation: 10093 bytes, ZERO angle-bracket characters in the stored body (none were written — placeholders are spelled as words throughout), the session-URL attribution footer survived intact in its session form, and a closing-keyword scan over the stored body returns exactly ONE hit,Fixes objectstack-ai/objectui#8174, the intended card. Every other card reference (objectui#7322, #7927, #8221, #7742, #7780, #8763) is bare, with no keyword adjacent."
],
"mcp_calls": "2 — create_pull_request, add_issue_comment. Issue body, comments, and all four source files were read through the repo-scoped REST channel and git (probed first: REST GET on the issue returned HTTP 200), never through MCP; no search_issues call was needed because no card was filed.",
"open_questions": [],
"out_of_scope_findings": [
"noted, not filed: the zod-mirror-parity ledger's unmirrored-declared half is a TYPE-level operator, so a mirror that falls behind its TS declaration is caught bytscand is INVISIBLE tovitest. Measured, not inferred (ablation leg 3 above). This is by design, not a defect, so there is nothing to file — but it is a live trap for the next seat that ablates a zod mirror withpnpm exec vitest runalone and concludes from a green run that the mirror half is optional. Successor who will hit it: any seat editing a mirror under packages/types/src/zod/, which is a recurring lane (objectui#8763 and objectui#8776 both touched it this week). Recorded here rather than as a card because the file that would carry the note is out of bounds for this PR.",
"noted, not filed: check:readme-exports signals an unmet build prerequisite as exit 1 while its three sibling whole-tree scans use exit 2 for the same condition. Its own output states this is deliberate ('A FAILURE and not a skip'), with the stated reason that a skip would read as coverage. Not a defect — recorded only so the asymmetric exit code is not misread as a red caused by this diff. Successor: none — no PR or person is routed to that script by this change."
]
}
Generated by Claude Code
条款② ceiling contract review — VERDICT: PASS
PR #8788 @
a9c30cb65(unchanged since review). Reviewed at the ceiling tier; tier verified before adoption — 125 model stamps, allclaude-fable-5-1, zero residue, positive control present (167). A verdict is adopted only after that count; one non-ceiling stamp would have voided it whole.The reviewer worked from its own worktree (
objectui-review-8788, removed; shared/home/user/objectuiuntouched — 0 status entries, stash list 0) and re-derived every load-bearing claim rather than reading the PR body. That mattered here: this diff's author is absent (the first attempt was killed by a rate limit; the second implementer committed WIP it found on disk), so the self-report was second-hand by construction.What was independently re-derived
- Both faces moved at identical requiredness — the parity ledger is genuinely unmoved, not accidentally silent. type-check exit 0 with the ledger compiling; parity vitest 32/32; no entry in
UnmirroredDeclared/RuntimeOnlyDeclared/WiderThanDeclared/ drift. Proven live by two ablations of the reviewer's own: deleting the calendar mirror'ssortredszod-mirror-parity.test.ts:2808; making it required reds the drift reconciliation at:2746. Sozod-mirror-parity.test.ts(held by fix(types): arm AnyComponentSchema for seven registered node-slot renderers (objectui#8499) #8763) is genuinely not owed an edit. - The finding(types):
BaseSchemacloses with[key: string]: any(packages/types/src/base.ts:467), so NO annotation on any node schema can catch a misspelled metadata key — measured green by a planted probe while the type, optionality and payload-member probes all went red #7927 PROCEED call holds — and is stronger than the PR claimed. finding(types):BaseSchemacloses with[key: string]: any(packages/types/src/base.ts:467), so NO annotation on any node schema can catch a misspelled metadata key — measured green by a planted probe while the type, optionality and payload-member probes all went red #7927's own scope text names "removing the signature and declaring the real extension keys" as its removal route, so this declaration sits inside finding(types):BaseSchemacloses with[key: string]: any(packages/types/src/base.ts:467), so NO annotation on any node schema can catch a misspelled metadata key — measured green by a planted probe while the type, optionality and payload-member probes all went red #7927's prerequisite set, not beside it. Under finding(types):BaseSchemacloses with[key: string]: any(packages/types/src/base.ts:467), so NO annotation on any node schema can catch a misspelled metadata key — measured green by a planted probe while the type, optionality and payload-member probes all went red #7927's other route (keep and document) the value-dimension acquisition still stands. Robust to both outcomes. - The value dimension is genuinely acquired, measured before/after: merge base → 1 error (positive control only); head → 4 errors at exactly the three wrong-typed nodes plus the control. Correctly authored nodes, the kanban node, and the misspelled
filtrstay green in both states — i.e. the finding(types):BaseSchemacloses with[key: string]: any(packages/types/src/base.ts:467), so NO annotation on any node schema can catch a misspelled metadata key — measured green by a planted probe while the type, optionality and payload-member probes all went red #7927 key-dimension ceiling is unchanged, exactly as the PR claims. Zod refuses at the key on both arm and union, pathsfilter,sort,sort.0.order. - No vocabulary fork.
any[]/SortConfig[]is whatObjectGanttSchema(objectql.ts:2725/2727),ObjectGridSchema(:679/690) andObjectMapSchema(:2340/2342) already spell, on both faces — five object-bound views now agree. (ObjectGallerySchemaunknownandObjectDataTableSchemaanyare pre-existing outliers.) - The kanban/calendar
sortasymmetry survives a wider census than the pin's: case-insensitivesorttoken inObjectKanban.tsx0; bracket/destructuring forms 0;orderby0; the 28 hits acrossplugin-kanban/srcare all dnd-kitSortable*plus oneArray.prototype.sort(). Declaringsorton the board would be this repo inventing a key. Not a defect. - The pin is not vacuous — all three PR legs reproduced independently plus a fourth of the reviewer's own, and membership confirmed to be on
.shape(calendar shape carriesfilter+sort, kanbanfilteronly, before-state neither). - Changeset
minorcorrect, with a plantedmajornegative control confirmingcheck-changeset-no-majoractually bites.
One overstatement recorded (does not change the verdict)
The PR body's "nothing refusing it anywhere" is not literal: runtime emits one
console.errorper retired spelling (core/src/utils/sort-query.ts:112), and per #8221 the html tier already answerstype-mismatch. The silent faces were exactly the two this PR fixes — TS, and zod → CLIvalidate/check. Substance stands.Left to the PM (follow-ups, ⛔ not riders on this PR)
- Stale docblock at
packages/plugin-kanban/src/ObjectKanban.tsx:165-183— still saysfilteris "declared by NEITHER face" with a| filter | — | — | — |row. False once this merges. Docs-only. orderrequiredness fork (pre-existing, now extended to calendar):SortConfig.orderrequired (types:312, zod:136) vs coreQuerySortEntry.order?honoured as ascending (sort-query.ts:64-67, :149) vs$orderby'sorder?(data.ts:118). Sosort: [{ field: 'x' }]parsed green before and is refused atsort.0.ordernow — the changeset's "nothing that validated before is refused now" is true only under the package's ownSortConfig. Same on Gantt/Grid/Map. A card, not a rider.- Element-type tightening across the five
any[]views — the docs already promiseViewFilterRule[](plugin-kanban.mdx:108,plugin-calendar.mdx:247) and the spec exportsFilterArray;QueryParams.$filteris additionallyRecord<string, any> | FilterArray(data.ts:108), so object-shaped filters the adapter accepts are refused at this authoring face. A five-view card.
Disposition
needs:contract-reviewcleared on both carriers (this card and PR #8788) — 双载体 agree. PR flips ready and goes to the merge queue.
Generated by Claude Code
- Both faces moved at identical requiredness — the parity ledger is genuinely unmoved, not accidentally silent. type-check exit 0 with the ledger compiling; parity vitest 32/32; no entry in
- added a commit that references this issue
on Sep 17, 2026
Filed unassigned by the os-dev seat implementing #7712 (branch
claude/issue-7712-kanban-calendar-filter-input). Measured onorigin/main9bfd618.Measured
Member lists extracted from the interface bodies in
packages/types/src/objectql.ts(not a bare word grep — the extraction returns the full member list per interface, which is its own control that the reader is working):ObjectKanbanSchema(:2744-:2833):type,objectName,groupBy,groupField?,limit?,titleField?,cardFields?,quickAdd?,coverImageField?,allowCollapse?,conditionalFormatting?. Nofilter.ObjectCalendarSchema(:2698-:2739):type,objectName?,data?,staticData?,startDateField?,endDateField?,titleField?,defaultView?. Nofilter, nosort.Meanwhile, after #7712 lands,
filteris declared by@objectstack/spec(ComponentPropsMapaccepts it on both blocks — measured bysafeParse, with an undeclared control key refused on the same call), declared by both plugins' registrationinputs, and read by both renderers (ObjectKanban.tsx:363,ObjectCalendar.tsx:478).sortis in the same position forobject-calendar(see the companion card).Why it is worth a row
An authored
filterreaches these annotations only throughBaseSchema's[key: string]: any— admitted, never examined. That is verbatim the reasoning objectui#7322 used to movegroupByintoObjectKanbanSchema(the docblock it left behind on:2748-:2764states it), so the precedent for treating an undeclared-but-read key here as a defect is this same interface, one key over.BaseSchemaends in[key: string]: any, so no annotation on any node schema can catch a misspelled key. Declaringfiltertherefore buys editor completion, doc-snippet fidelity and one honest declaration face — it does not buy a type error for the misspelling. Whoever picks this up should decide whether that is worth the edit, or whether it should wait behind #7927.Neighbours (⛔ none of them is this)
ObjectCalendarComponentProps.schemais typedObjectGridSchema | CalendarSchema, so noobject-calendarnode is assignable — the documented direct-React usage cannot compile #7311 —ObjectCalendarComponentProps.schemais typedObjectGridSchema | CalendarSchema, so noobject-calendarnode is assignable at all. That is the prop; this is the node schema.KanbanSchemacarries three zero-read members (allowCollapse,cardTemplates,columnWidths) and the board reads an undeclaredtitleField— enforce-or-remove on the shape objectui#7664 declared #7742 / finding(types):ObjectKanbanSchemarequiresobjectNameon both faces while the renderer reads an undeclared inlinedataahead of the fetch — the record-source ladder class (#7313) on a fourth view schema #7780 — member censuses over the same two interfaces, on different keys.BaseSchemacloses with[key: string]: any(packages/types/src/base.ts:467), so NO annotation on any node schema can catch a misspelled metadata key — measured green by a planted probe while the type, optionality and payload-member probes all went red #7927 — theBaseSchemaindex signature that caps what any of this can catch.Refs: #7712 · #7322