types: declare the gantt block face on ObjectGanttSchema (fixes #6475) - #6704
Merged
Conversation
Declares `gantt?: GanttConfig` on both `ObjectGanttSchema` faces (TS interface + zod mirror), closing the last of the 28 keys objectui#6051 measured that `ObjectGanttSchema` did not declare. Unlike the other 27, this one narrows the accept set: a `gantt` block previously rode through `.passthrough()` unvalidated, and is now parsed against the spec's `GanttConfigSchema`, which requires `startDateField`/`endDateField`/ `titleField`. Maintainer ruling, objectui#6475 (2026-08-27), Option A: enforce immediately, no warning window. Also updates the gantt-flat-config-declared-keys.test.ts pin that previously asserted the block face was undeclared, to assert the new enforced behaviour (trio-missing refused, trio-complete accepted), and fixes a zod-mirror-parity.test.ts false-positive triggered by a `Spec` token in a docstring landing inside ObjectTreeSchema's export-boundary scan window. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_8ca04858-ea8e-5b85-9182-de59aa49e00c
os-sales
marked this pull request as ready for review
August 28, 2026 17:21
This was referenced Aug 28, 2026
Contributor
✅ Console Performance Budget
The eager closure is every chunk the entry reaches through static imports — what the browser fetches and parses before the app renders. The entry chunk on its own is a small fraction of it. 📦 Bundle Size Report
Size Limits
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #6475
What changed
Declares the
ganttblock face onObjectGanttSchema, on both declaration faces:GanttConfigExtensionFields(added by #6472) is reused unchanged, so both authoring faces (the nested block and the flattened top-level spelling) are built from one field map and cannot fork. This is the 28th and last of the keys objectui#6051's census foundgetGanttConfigreading offschemathatObjectGanttSchemadid not declare — severed out of that PR because, unlike the other 27, it narrows the accept set rather than only naming a spelling.Maintainer ruling followed exactly
Ruling of 2026-08-27 (
以上同意), Option A: declare as-is, spec requiredness enforces immediately, no warning window.Framing: this surfaces existing breakage, it does not create new breakage
A
ganttblock missing the required trio is already non-functional at runtime today:getGanttConfig's block branch (packages/plugin-gantt/src/ObjectGantt.tsx) already feeds the block toGanttConfigSchema.safeParseand logs[ObjectGantt] Invalid gantt configurationon failure. What changes is when the author is told — runtime console silence becomes an authoring-time refusal that names the missing field. This is adeclared = enforcedrestoration; the spec has requiredstartDateField/endDateField/titleFieldsince rc.6, nothing here invents requiredness.Clause-② — exactly what the CLI now refuses that it accepted before
ObjectGanttSchemais a member ofAnyComponentSchema, so it reachessafeValidateSchemaand thereforepackages/cli/src/commands/{validate,check}.ts.ganttblock present, missing any ofstartDateField/endDateField/titleField.passthrough()unvalidated)ganttblock present, all three fields presentganttblock (flat spelling, or none)Nothing else about
ObjectGanttSchema's accept set moves.Re-taken census on current
main(post-#6472), populations kept separategit ls-files | wc -l→ 5641 tracked files today (the original 5095-file scan predated #6472's landing and the file count has grown since). A baregrep -n "gantt:"returns 121 hits across 56 files and conflates unrelated populations, per the card's own warning. Re-run with each population isolated and a positive control on every zero:gantt—packages/i18n/src/locales/{ar,de,en,es,fr,ja,ko,pt,ru,zh}.ts(10 files, 20gantt: {hits — a nested chrome-string namespace, e.g.gantt: { column: { taskName: … } }), plus prose describing that namespace (packages/plugin-gantt/docs/verification/README.md,packages/plugin-gantt/scripts/verify-i18n.mjs,packages/plugin-gantt/demo/main.tsx's own localzhpack). None reachObjectGanttSchema..changeset/*.mdbodies referencinggantt:as a conventional-commit scope prefix or descriptive text (7 files). Not metadata.gantt(icon maps, label maps, the Create-View-Dialog per-view-type field-descriptor array,packages/cli/src/utils/known-schema-types.ts's'plugin-gantt:object-gantt'registry string) — 7 files. These key a lookup table by the view-type string, not an authoredObjectGanttSchema.ganttvalue.as any-cast test fixtures that never reach the zod mirror —plugin-gantt's own 14.test.tsxfiles (allschema={{ … } as any}props, includingObjectGantt.blockPrecedence.test.tsx's deliberately-incomplete{ colorField: 'flat_color' }block used to test the renderer's own dev-mode warning, not CLI validation), pluspackages/react/src/spec-bridge/__tests__/P1SpecBridge.test.ts(transformListView(spec: any), a pure pass-through with no validation) andpackages/app-shell/src/views/ObjectView.titleFieldConvergence.test.tsx(mocksListViewto captureprops.schema, never renders or parses it). Positive control:pnpm --filter @object-ui/plugin-gantt type-check— clean (0 errors) — proves these are not silently-any-typed; they are genuinely never parsed.ListViewSchema.gantt— a different schema (type: 'list-view'), unaffected by this PR: it already takes the spec'sGanttConfigSchemaunmodified (not.partial()'d, unlike kanban/calendar/gallery/timeline) viaspecFieldsExcept(...), so it already required the trio before this PR and continues unchanged. Two fixtures under this population (packages/plugin-list/src/__tests__/ListView.test.tsx:2696,2721, missingtitleField) are pre-existingas unknown as ListViewSchema-cast render fixtures that never reach.safeParse— not a casualty of this PR, and not this PR's schema.content/docs/plugins/plugin-gantt.mdx(11gantt: {blocks, all 11 trio-complete),packages/plugin-gantt/README.md(one commented+elided illustration// gantt: { startDateField: …, endDateField: …, … }, and one flat-faceconst gantt: ObjectGanttSchema = {...}— a variable namedgantt, not agantt:block key),skills/objectui/guides/page-builder.md(1"gantt": {block, trio-complete — a different, pre-existing defect in the same example is already tracked at Published skillobjectui/guides/page-builder.mdpresents sixGanttConfigkeys as top-level siblings of theganttblock — beside a block they are read by nothing #6508, not restated here). None of these are compiled or validated; all are trio-complete regardless.ObjectGanttSchema's discriminator —examples/schema-catalog/src/schemas/plugin-gantt/{construction-project-phases,project-timeline-with-dependencies,sprint-development-timeline}.json(3 files,type: "object-gantt", each with a"gantt": {...}block). This is the population closest to "what a human or AI author would actually write" in this repository. All 3 are trio-complete. (Not machine-validated by any CI workflow today — confirmed by grepping.github/workflows/**forschema-catalog, which returns only comments — so this PR does not newly break CI on them; the finding is that they would pass even if it did.)pnpm-lock.yaml(packages/plugin-gantt:workspace path),packages/plugin-timeline/src/renderer.tsx+examples/schema-catalog/.../plugin-timeline/gantt-style-timeline.json+packages/components/src/renderers/complex/TIMELINE.md(allTimelineSchema's ownvariant: 'gantt', a different schema),content/docs/api/schema-reference.md(enum value list),packages/plugin-gantt/src/GanttView.tsx(an export-filename fallback string),packages/plugin-gantt/package.json(akeywordsentry).Net: zero blocks missing the trio in every population that can plausibly reach
ObjectGanttSchema's parser — including the one population (examples/schema-catalogJSON) that is genuine authored metadata rather than a TS/TSX test fixture. This matches, and modestly strengthens, the original 5095-file scan's finding on the now-5641-file tree.The out-of-tree question the ruling asked to be recorded rather than answered here: whether authored
ganttblock metadata missingtitleFieldexists outside this repository (customer apps,objectstackfixtures) remains unmeasured by an in-repo census by construction — the maintainer ruled Option A anyway, per the standing no-gradualism rule.The trio-missing pin, shown red before the fix (ablation)
packages/types/src/__tests__/gantt-flat-config-declared-keys.test.ts's test "theganttBLOCK face is still undeclared, and today rides through UNVALIDATED" asserted the pre-fix state (ganttabsent fromObjectGanttSchema.shape, a trio-missing block accepted). It has been rewritten to assert the post-fix state — renamed "theganttBLOCK face is declared, and the spec trio now enforces at parse time" — asserting:ganttnow in.shape; a block missingtitleFieldis refused and names the missing field; an empty block is refused; a wrong-typedganttvalue is refused; a trio-complete block is accepted.Ablation, prediction before running:
git checkout HEAD~1 -- packages/types/src/objectql.ts packages/types/src/zod/objectql.zod.ts(revert only the two production files to their pre-fix content, keeping the rewritten test at HEAD). Predicted: the rewritten pin test fails red onexpect(Object.keys(ObjectGanttSchema.shape)).toContain('gantt'); the other 16 tests in the two files (the flat 27-key pins,zod-mirror-parity) stay green, since nothing else in this PR touches them.grep -c 'gantt?: GanttConfig;' objectql.ts1→0;grep -c 'gantt: SpecGanttConfigSchema.extend(GanttConfigExtensionFields)' objectql.zod.ts1→0; the old severed-state comment markeris DELIBERATELY still undeclared herereappeared (0→1).Test Files 1 failed | 1 passed (2)/Tests 1 failed | 16 passed (17). The one failure is precisely the predicted assertion:AssertionError: expected [ Array(64) ] to include 'gantt'at thetoContain('gantt')line.git checkout HEAD -- packages/types/src/objectql.ts packages/types/src/zod/objectql.zod.ts. Confirmed:git diff HEAD --statempty;git hash-objecton each of the two files equalsgit rev-parse HEAD:plus that file's path, for both files; the full pin suite (gantt-flat-config-declared-keys.test.ts+zod-mirror-parity.test.ts+gantt-declared-keys.test.ts) reruns green (26/26).#6472's derived-pin family — untouched, verified still passing
FlatFaceGaps(in the same test file) — the type-level pin thatExcludeofDeclaredKeysofGanttConfig, againstDeclaredKeysof the flatObjectGanttSchemaTS, must benever— is unmodified. AddinggantttoObjectGanttSchema's own declared keys only grows theExclude's target set (the flat face's declared-keys side), which cannot introduce residue on the source side. Still compiles clean, confirmed by the greentype-checkrun below (which compiles every*.test.tsin the package, including the@ts-expect-errorcompile-time pins).A second, unrelated fix this PR needed to stay green
zod-mirror-parity.test.ts'sSPEC_DERIVED_PAIRSre-check scans raw text betweenexport constboundaries inpackages/types/src/zod/*.zod.tsfor a\bSpec[A-Z]\w*token to detect which mirrors reference a spec schema. My first pass at the docstring above the privateGanttConfigExtensionFieldsconst — which sits textually between theObjectTreeSchemaandObjectGanttSchemaexport boundaries — mentionedSpecGanttConfigSchemain prose, and that mention was misattributed toObjectTreeSchema(which references no spec schema at all), flippingSPEC_DERIVED_PAIRS matches what the mirror sources actually dored. Fixed by rewording the docstring to avoid the literal token, with a comment recording the trap so the next editor of that docstring doesn't reintroduce it.Gate table (all on commit
698685911, the current HEAD)packages/typestype-check (tsc --noEmit + examples + test projects — compiles every*.test.ts, including the@ts-expect-errorcompile-time pins)pnpm --filter @object-ui/types type-checkpackages/plugin-gantttype-check (consumer sweep, dependency closure built first)pnpm --filter @object-ui/plugin-gantt type-checkpackages/typesfull vitest (includes zod-mirror-parity, both gantt derived-pin files, base-schema parity)pnpm exec vitest run --root . packages/types/Test Files 69 passed (69)/Tests 801 passed (801)packages/plugin-ganttfull vitest (consumer sweep)pnpm exec vitest run --root . packages/plugin-gantt/Test Files 51 passed (51)/Tests 422 passed (422)check:control-bytesnode scripts/check-control-bytes.mjsscanned 5557 tracked text file(s)check:spec-symbols(relevant: this PR derives fromSpecGanttConfigSchema)node scripts/check-spec-symbol-derivation.mjsnode scripts/check-changeset-presence.mjs1 changeset(s) addednode scripts/check-changeset-no-major.mjsNo changeset declares a major bumppackages/typeslint, narrowed to the 3 touched files,--format jsonpnpm exec eslint src/objectql.ts src/zod/objectql.zod.ts src/__tests__/gantt-flat-config-declared-keys.test.ts --format json0 errors, 19 warnings — all pre-existing:grep -c '\bany\b'onobjectql.tsis identically 25 onorigin/mainand on this branch, and lintingorigin/main's copy of the file directly reproduces the same 19no-explicit-anywarnings byte-for-bytepackages/typeslint, full package (canonical gate command)pnpm --filter @object-ui/types lint247 problems (0 errors, 247 warnings)Narrowing proof (three legs, per the repo's own convention): ① the 247-warning population above is read from eslint's own
--format json/text summary, not guessed; ②eslint.config.jshas noparserOptions.project/projectServiceanywhere in this repo — type-aware linting is off, so nothing in this diff can move any judgment on a file this diff did not touch; ③ the direct A/B (lintorigin/main'sobjectql.tsbytes vs. this branch's) reproduces the identical 19-warning population, proving the narrowed run and the full-package run agree and that this diff added zero lint findings.objectui has no
scripts/pm/os-verify-lock.shorscripts/pm/dispatch-gates.mjs— that shared-lock/gate-derivation infrastructure lives only inobjectstack. Gates above were run directly per this repo's own AGENTS.md testing conventions (root-relativepnpm exec vitest runplus a path, neverpnpm --filter PKG testorcd packages/x), and the union above is the full set the dispatch named plus the one adjacent gate (check:spec-symbols) this PR's spec-derived declaration touches.Fence held
Only
packages/types/src/objectql.ts,packages/types/src/zod/objectql.zod.ts,packages/types/src/__tests__/gantt-flat-config-declared-keys.test.ts(updating the pin this PR's ruling directly obsoletes), and the changeset.packages/types/src/index.tsand itspackage.jsonexportsmap (held by #6527's B patch round) were not touched or read for editing purposes.Generated by Claude Code
Generated by Claude Code