Skip to content

ObjectGanttSchema still does not declare the gantt block face — declaring it enforces the spec's required trio and changes the CLI's refusal behaviour (severed from #6051) #6475

Description

@claude

Severed from objectui#6051 / PR #6472 by PM ruling (2026-08-26) so the decision is
recorded on its own card rather than bundled into a 27-key declaration PR. Filed
unassigned; triage grades it. The measurement below is complete — nothing needs
re-deriving to act on this.

What is proposed

Declare the gantt BLOCK face on ObjectGanttSchema, on both declaration faces:

// packages/types/src/objectql.ts
gantt?: GanttConfig;// packages/types/src/zod/objectql.zod.tsgantt: SpecGanttConfigSchema.extend(GanttConfigExtensionFields).optional(),

GanttConfigExtensionFields already exists in the mirror (PR #6472 added it as
the single field map the flat face is built from), so this is a two-line change
plus the pin entries.

Why it is a real undeclared read

getGanttConfig (packages/plugin-gantt/src/ObjectGantt.tsx) reads it:

// 2. Check schema.gantt (the block face, ObjectGridSchema style)if(schema.gantt){config=schema.ganttasGanttConfigEx;}

An AST enumeration of every top-level key read off the schema prop in
packages/plugin-gantt/src/** (non-test) on 854222c5e found 47 keys, of
which 28 were undeclared. PR #6472 declared 27. gantt is the 28th, and it is
the only one left undeclared — so the published type still does not teach the
block spelling, and an author writing { type: 'object-gantt', gantt: { … } } in
TypeScript gets no completion, no checking, and no error on a misspelt member.

Why it was severed rather than shipped — the accept-set change

This is the ONE key of the 28 whose VALUES get stricter, and the reason is not the
key itself:

  • gantt had no mirror entry at all, so a block rode through .passthrough()
    entirely unvalidated;
  • declaring it as GanttConfig means it is parsed, and GanttConfig derives from
    the spec's GanttConfigSchema, which requiresstartDateField,
    endDateField and titleField;
  • ObjectGanttSchema is a member of AnyComponentSchema, so this reaches
    safeValidateSchema and therefore the CLI's validate and check commands
    (packages/cli/src/commands/{validate,check}.ts).

Net effect: a gantt block missing one of those three moves from "accepted, then
warned about at runtime" to "refused at authoring/validate time."

The case FOR enforcing it (recorded so the next reader does not re-derive it)

  1. It is not a new contract.getGanttConfig's block branch already feeds
    the block to GanttConfigSchema.safeParse and logs
    [ObjectGantt] Invalid gantt configuration on failure. The flat branch returns
    before reaching that check. Declaring gantt as GanttConfig makes the
    declared face equal the face the renderer was already checking — declared = enforced restoration, not a widening of the rules.
  2. The spec already says so.GanttConfigSchema (rc.6, 19 keys) declares
    startDateField, endDateField and titleField required. Nothing here
    invents requiredness.
  3. Zero measured casualties in this repo. A scan of all 5095 tracked files
    for authored gantt: { … } blocks found no metadata block missing the
    trio. The apparent hits are i18n translation namespaces that happen to be named
    gantt (packages/i18n/src/locales/*.ts), prose, and as any test fixtures
    that never reach the zod mirror. The README's block example
    (packages/plugin-gantt/README.md:250) is a commented, elided one-liner, not a
    compilable example.
  4. It closes the last hole in the "one vocabulary, two faces" property PR
    feat(types,plugin-gantt): declare the flattened GanttConfig face ObjectGantt reads (#6051) #6472 established. That PR's derived pin
    (Exclude<DeclaredKeys<GanttConfig>, DeclaredKeys<ObjectGanttSchema>> must be
    never) proves every block-face key is declared at the top level; it does not
    and cannot prove the block key itself is declared.

The case AGAINST shipping it inside #6051 (the PM's ruling, recorded verbatim in substance)

  1. It changes a published CLI's refusal behaviour. Warning at runtime becoming
    refusal at build time is a real behaviour change for authors, whatever the spec
    says.
  2. The zero-casualty scan is in-repo only. 5095 tracked files measures this
    tree
    . Authored metadata living outside it is exactly the population an in-repo
    census cannot see — a blind spot that has produced false negatives on this seat
    before. Not a reason to doubt the number; a reason not to let it carry a
    published-surface decision by itself.
  3. Bundled, it would have been invisible. Nobody reading "declare the
    flattened GanttConfig face" would know they were also approving a CLI refusal
    change.

What a decision needs to cover

  • Ship as-is (block declared, spec requiredness enforced), or
  • ship with the requiredness relaxed on the objectui face — which forks the
    vocabulary from the spec and is not recommended, or
  • ship behind a deprecation period: declare gantt, keep the CLI's refusal
    behind a flag or a warning for one release, then enforce.

Whoever rules should also settle the out-of-tree question directly: is there
authored gantt block metadata outside this repository (examples, customer apps,
objectstack fixtures) that omits titleField?

Related: objectui#6051 / PR #6472 (declared the other 27), objectui#6469 (the flat
vs block PRECEDENCE question, separate), objectui#5903 / PR #6053 (the cast-read
sibling).

Generated by Claude Code


Generated by Claude Code

Metadata

Metadata

Assignees

No one assigned

    Labels

    domain:uiobjectui ui stream: fix lands on the published library or apps — objectui execution seatneeds-user-decision

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions