Repository navigation
Commit b53d9f3
refactor(types,plugin-calendar,plugin-gantt,plugin-list,plugin-view)!: flat object-calendar / object-gantt keys leave the published schemas; producers emit the block (#26411)
<!-- claude-projects-attribution: {"github_login":"os-support-ai"} -->
_Requested by **Yibo Wang** · [project
thread](https://claude.ai/code/project/chan_01BVUyyPie8gHwoPM18iABwB?thread=cmsg_01BVUyyPie8gHwoPM18iABwBVVaEbKjJHqT747bQHd6Uxp)_
Part of #25923 (work item 1 only; items 3, 4 and the FormField follow-up
stay on the card).
Clause-②: yes (narrowing)
Metadata-protocol: narrowed
Skills-docs: none — `skills/objectui/guides/page-builder.md` already
authors the `gantt` block and no skill authors a flat `object-calendar`
or `object-gantt` key; the two plugin READMEs are corrected here
## 维护者速读
- 改了什么:`@object-ui/types` 里 `object-calendar` 和 `object-gantt`
节点不再公开“平铺”的字段映射键(如 `startDateField`),这些键只能写在 `calendar` / `gantt`
块里;`ListView` 和 `ObjectView` 生成节点时也改为写块。
- 为什么改:spec 本来就拒绝这些平铺写法,但我们的类型还公开着它们,`objectui validate` 因此放行了日历节点上 spec
拒绝的写法,作者会被误导。
- 风险与回滚:渲染器仍读平铺写法,已有页面照常显示;唯一例外是早于写入校验的存量视图,若其 `options.gantt` 带有 spec
拒绝的值,现在显示甘特拒绝屏而不是照常绘制(数量未测,由卡片第 3 项的存量行盘点来数)。另一风险在于手写 TS
代码里写了平铺键的会编译失败(按 changeset 里的迁移改成块即可)。回滚就是 revert 本 PR。
- 先看:`ui/packages/plugin-list/src/ListView.tsx`(calendar / gantt
两个分支的出块条件)、`ui/packages/types/src/zod/objectql.zod.ts`(被删的成员)、`ui/packages/plugin-gantt/src/ObjectGantt.tsx`(`ObjectGanttFlatFields`)。
- 两分钟验证:`pnpm --dir ui exec vitest run
packages/plugin-list/src/__tests__/ListView.gantt-binding-7070.test.tsx
packages/types/src/__tests__/gantt-flat-config-declared-keys.test.ts`,预期全部通过。
- 需要你做的:无,席位落地。
## What changes
The flat field-mapping keys of `object-calendar` and `object-gantt`
leave the published `@object-ui/types` faces (TypeScript interface and
tolerant zod mirror) and move to package-local hand-off types next to
their one reader (ui/AGENTS.md Commandment #0.1). The producers emit the
block.
**Moved off the published faces**
- `ObjectCalendarSchema`: `startDateField`, `endDateField`,
`titleField`, `colorField`, `allDayField` (5). New home:
`ObjectCalendarFlatFields` / `ObjectCalendarHandoff` in
`plugin-calendar/src/ObjectCalendar.tsx`.
- `ObjectGanttSchema`: the 29 `GanttConfig` keys (`startDateField`,
`endDateField`, `titleField`, `progressField`, `dependenciesField`,
`colorField`, `borderColorField`, `parentField`, `typeField`,
`lockField`, `objectField`, `summaryExtent`, `defaultCollapsedDepth`,
`tooltipFields`, `baselineStartField`, `baselineEndField`,
`groupByField`, `resourceView`, `assigneeField`, `effortField`,
`capacity`, `quickFilters`, `autoZoomToFilter`, `timeSegments`,
`interactions`, `exportFileName`, `timeZone`, `dependencyTypes`,
`viewMode`), plus the legacy `dependencyField` alias and the `search` /
`searchableFields` pair only `ListView`'s toolbar writes (32). New home:
`ObjectGanttFlatFields` (derived from `GanttConfig`, so the two
spellings cannot fork) / `ObjectGanttHandoff` in
`plugin-gantt/src/ObjectGantt.tsx`.
**Kept**
- `ObjectCalendarSchema`: the `calendar` block, the `dateField` /
`endField` aliasKeyRefusal tombstones, and every other node key.
- `ObjectGanttSchema`: `gantt`, `staticData`, `filter`, `sort`, and
every other node key.
- Seat 2's ruling 6412606977 (the `FormField` index signature) is not
touched.
**For gantt, the strict authoring face already refused every flat key**
(its `object-gantt` arm is the `properties` bag,
`ObjectGanttBlockSchema`, objectui#10859), so the narrowing there is the
published TypeScript and zod export only. For calendar the strict face
derived from the declared keys and accepted the five flat; it now
refuses them by name, as the spec does.
**Producers.** `ListView` (calendar and gantt branches) and
`ObjectView`'s `generateViewSchema` (calendar and gantt cases) emit
`calendar: {…}` / `gantt: {…}` instead of the flat keys. They emit the
block only where the renderer's flat branch drew, so what a view shows
is unchanged, with the one exception under Acceptance notes: a calendar
once `startDateField` is declared; a gantt once both dates are, with
`titleField` floored at `'name'` as the flat branch floored it.
**Renderers are unchanged.** `getCalendarConfig` and `getGanttConfig`
still read the block first and fall back to the flat spelling, now typed
on the hand-off type. READMEs of both plugins are corrected (they said
the producers emit the flat spelling), and so are the explanatory
clauses of the two `@objectstack/spec` prescriptions that said the same
(`packages/spec/src/ui/component.zod.ts`, rework r3).
## Tests
- `@object-ui/types`: the pins that declared the flat keys now pin their
absence on both published faces and the strict-face refusal
(`calendar-flat-color-allday-8466`, `gantt-flat-config-declared-keys`,
`gantt-dependency-field-deprecated-alias`, `gantt-search-keys-10250`,
`gantt-view-mode-declared` re-pointed to `gantt.viewMode`,
`object-gantt-properties-bag-10859-b6`,
`calendar-date-alias-refusal-8355`).
- `plugin-calendar`: `calendarUnionReads-8651` pins
`ObjectCalendarComponentProps['schema']` as `ObjectCalendarHandoff` and
the hand-off key census.
- `plugin-gantt`: new `ganttHandoffFlatFields-25923` pins the hand-off
as exactly `GanttConfig`'s keys plus the three, no overlap with the
published interface, the renderer prop typed with it, and the alias's
`@deprecated` tag.
- `plugin-list` / `plugin-view`: the producer tests read the emitted
block and red on any flat key coming back; new rows pin "no block
without the axis" and the `'name'` floor.
- Reverse check: re-adding `colorField` to `ObjectGanttSchema` and
`startDateField` to `ObjectCalendarSchema` reds
`calendar-flat-color-allday-8466.test.ts(182)`,
`gantt-flat-config-declared-keys.test.ts(316)` and
`zod-mirror-parity.test.ts(4474)` under `tsc -p tsconfig.test.json`,
each naming the key or schema.
## Acceptance notes
- **Follow-up candidate (not filed):** retire the flat fallback read in
`getCalendarConfig` / `getGanttConfig` and the hand-off types with it.
No producer in this tree writes the flat spelling any more; about 80
renderer tests still author flat nodes and would move to the block.
- The tolerant mirror no longer value-checks the moved keys written flat
(`ObjectGanttSchema.safeParse({ …, colorField: 5 })` now passes
`.passthrough()`), which is why the declaration reads `yes (narrowing)`
rather than the order's `no (narrowing)`. The strict face and the spec
still refuse them; the value check lives in the block (`gantt.capacity:
'one'` is refused at `gantt.capacity`).
- **Reading (measured in rework r1; the r1 deviation was withdrawn in
r2, Prime Directive #12):** `getGanttConfig` parses a `gantt` block
against the spec's `GanttConfigSchema` (objectui#13459) and never
validated the flat branch. app-shell relays a stored row's
`options.gantt` unvalidated (`storedLegacyOptions`). So under main's
write door, a pre-door stored row whose `options.gantt` carries a
spec-refused value (e.g. `viewMode: 'hour'`) now lands on
`gantt-invalid-config` instead of drawing. The producers emit the block
unconditionally and never a flat key; such a row is converted at the
store (ADR-0087), not tolerated at a consumer. The population is
unmeasured; work item 3 (the stored-row census) on the card is where it
gets counted. The prose in `ListView.tsx`, plugin-view `ObjectView.tsx`,
`ObjectGantt.tsx` and the changeset (including its ADR-0087 marker,
which used to say "nothing that drew before stops drawing") says this.
- The object-calendar `dateField` / `endField` tombstones now prescribe
`calendar.startDateField` / `calendar.endDateField` (rework r1; this
round made the old prescription false). Pinned in
`calendar-date-alias-refusal-8355` and `calendarUnionReads-8651`, with a
control that the bare canonical is never prescribed.
- `ui/packages/app-shell/src/views/ObjectView.tsx` is not touched.
- **`@objectstack/spec` prescription prose (rework r3):** the
explanatory clauses of `OBJECT_CALENDAR_FLAT_FIELD_GUIDANCE` and
`OBJECT_GANTT_FLAT_CONFIG_GUIDANCE` in
`packages/spec/src/ui/component.zod.ts` said `ObjectView` / `ListView`
emit, or flatten into, the flat spelling. This PR made that false. They
now say the producers hand the binding off in the `calendar` / `gantt`
block, and that the flat spelling is only a stored-document fallback the
renderer still reads, not authorable. Nothing else in the prescriptions
changes, including the "Write this as a key of the … config object
instead" sentence. The changeset now carries `'@objectstack/spec':
minor`. The grade is minor because `check-changeset-no-major` grades
only the root workspace and the narrowing lives in the ui workspace
(`@object-ui/types`), while the spec diff itself is prescription prose.
Before editing, I searched for the old wording and found it nowhere else
in `packages/spec` tests, `json-schema/`, `content/docs/` or
`sdui.manifest.json` (only in historical CHANGELOGs), so nothing needed
regenerating. Rework r4 also rewrote the JSDoc around those two guidance
sets, plus the docblock of the object-gantt props schema. It used to say
the producers "emit on their runtime handoff", "EMIT when they flatten
`options.gantt`", call the flat branch the "HOT path", say that
`ObjectGanttSchema` "declares the whole flat face", and call the flat
keys "the flatten product". It now says the producers hand off the
block, the flat spelling is a stored-document fallback, and the flat
keys live on the package-local hand-off types. A sweep of this PR's ui
files fixed six more comments of the same kind: `ObjectCalendar.tsx`,
`ObjectGantt.tsx`, `objectql.ts`, `objectql.zod.ts`,
`calendar-flat-color-allday-8466` and
`object-gantt-properties-bag-10859-b6`. These are comments only; no
string, key, example or accept set moved.
## Verification
<details><summary>ui vitest (under os-verify-lock)</summary>
- `packages/types packages/plugin-calendar packages/plugin-gantt`: Test
Files 557, Tests 11881 passed / 209 skipped after the strict-face row
fix (first run: 5 failed in one file, fixed).
- `packages/plugin-list packages/plugin-view`: first run 32 failed (the
producer tests reading flat keys); after re-pointing, the 12 failing
files plus the types file: Test Files 13/13, Tests 214/214.
- Final head (`254db190`, after merging main): `pnpm --dir ui exec
vitest run packages/types packages/plugin-calendar packages/plugin-gantt
packages/plugin-list packages/plugin-view`: VERDICT command-exit 0, Test
Files 797 passed / 1 skipped, Tests 14252 passed / 209 skipped.
- Rework r2 head (`4676da49`): the same five-package command: VERDICT
command-exit 0, Test Files 797 passed / 1 skipped, Tests 14252 passed /
209 skipped. `type-check` and `lint` on plugin-list / plugin-view /
plugin-gantt: exit 0.
</details>
<details><summary>Type-check</summary>
- `pnpm --dir ui --filter '...@object-ui/types' type-check`: every
importer Done after building the missing dists (the first two runs
failed only on unbuilt `@object-ui/auth`, `layout`, `plugin-designer`,
`plugin-chatbot`, `plugin-editor` dists; none of the 561 errors named a
calendar or gantt key).
- `@object-ui/types` `tsc -p tsconfig.test.json`: exit 0.
</details>
<details><summary>@objectstack/spec (rework r3)</summary>
- Under the lock: `pnpm --filter '@objectstack/spec^...' --filter
@objectstack/spec build && pnpm --filter @objectstack/spec test` gave
VERDICT command-exit 0, Test Files 728 passed, Tests 22040 passed / 1
todo.
- Rework r4 head (`eba20284`): same command, VERDICT command-exit 0,
Test Files 728 passed, Tests 22040 passed / 1 todo.
</details>
<details><summary>Dispatch gates</summary>
- `node scripts/pm/dispatch-gates.mjs --commands` on the merged head: 35
commands, all exit 0 (`check:type-check-debt` first exited 3 while the
dogfood run held the verify lock, then 0 on re-run). `--ran`: 35
accounted, 0 NOT-MEASURED.
- `check-sdui-manifest` first exited 1 (registry sources moved); `node
scripts/gen-sdui-manifest-node.mjs` regenerated it. Main has since
retired the per-package records (#26367), so nothing of that lands here.
- Rework r2 head (`4676da49`): 35 commands, all exit 0; `--ran`: 35 run,
0 NOT-MEASURED.
- Rework r3 head (`d5d316b1`, after merging origin/main `00a4593a`):
`--commands` derived 82 commands. The first pass gave 81 exit 0 and 1
exit 3: `node scripts/check-plugin-teardown-shape.mjs --self-test`,
whose positive-control commit `621a4876` was missing from the shallow
clone. After fetching that commit, the re-run exited 0. `--ran`: 82 run,
0 NOT-MEASURED.
- Rework r4 head (`eba20284`): 82 commands, all exit 0; `--ran`: 82 run,
0 NOT-MEASURED.
</details>
<details><summary>Dogfood battery (title carries `!`)</summary>
- Merged head, under the lock: `pnpm --filter '@objectstack/dogfood^...'
build && pnpm --filter @objectstack/dogfood test`: VERDICT command-exit
1, Test Files 297 passed / 2 failed / 3 skipped, Tests 2521 passed / 10
failed / 18 skipped.
- The two red files are `test/authz-conformance.test.ts` (#17111
ledger-figure pin, 6 rows) and `test/authz-probe-blind-spot.test.ts`
(#13260 census of `packages/rest/src/rest-server.ts` and
`rest-route-ledger.ts`, e.g. `expected 70 to be 69`, 4 rows). This diff
touches no `packages/rest`, no dogfood input and no `@objectstack/*`
package.
- Re-measured (rework r1): on `origin/main` `9a0108cd` the two files
read 108/108 passed. On the branch (head `89e13213`, base `b33dd25b`)
they read 10 failed / 98 passed, because the base predates #26406's
census re-measure. CI's Dogfood Regression Gate on the merge ref is
green.
</details>
🤖 Generated with [Claude Code](https://claude.com/claude-code)
https://claude.ai/code/session_01WGufzetP4CSWdmfU9t887J
---------
Co-authored-by: Claude <noreply@anthropic.com>1 parent 1c63231 commit b53d9f3
31 files changed
Lines changed: 1051 additions & 1085 deletions
File tree
- .changeset
- packages/spec/src/ui
- ui/packages
- plugin-calendar
- src
- __tests__
- plugin-gantt
- src
- __tests__
- plugin-list/src
- __tests__
- plugin-view/src
- __tests__
- types/src
- __tests__
- zod
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
6195 | 6195 | | |
6196 | 6196 | | |
6197 | 6197 | | |
6198 | | - | |
6199 | | - | |
| 6198 | + | |
| 6199 | + | |
| 6200 | + | |
| 6201 | + | |
| 6202 | + | |
6200 | 6203 | | |
6201 | 6204 | | |
6202 | 6205 | | |
| |||
6209 | 6212 | | |
6210 | 6213 | | |
6211 | 6214 | | |
6212 | | - | |
6213 | | - | |
6214 | | - | |
| 6215 | + | |
| 6216 | + | |
| 6217 | + | |
6215 | 6218 | | |
6216 | 6219 | | |
6217 | 6220 | | |
| |||
7522 | 7525 | | |
7523 | 7526 | | |
7524 | 7527 | | |
7525 | | - | |
7526 | | - | |
7527 | | - | |
7528 | | - | |
| 7528 | + | |
| 7529 | + | |
| 7530 | + | |
| 7531 | + | |
| 7532 | + | |
7529 | 7533 | | |
7530 | 7534 | | |
7531 | 7535 | | |
7532 | 7536 | | |
7533 | 7537 | | |
7534 | | - | |
7535 | | - | |
7536 | | - | |
7537 | | - | |
7538 | | - | |
7539 | | - | |
| 7538 | + | |
| 7539 | + | |
| 7540 | + | |
| 7541 | + | |
| 7542 | + | |
| 7543 | + | |
7540 | 7544 | | |
7541 | 7545 | | |
7542 | 7546 | | |
| |||
7561 | 7565 | | |
7562 | 7566 | | |
7563 | 7567 | | |
7564 | | - | |
7565 | | - | |
7566 | | - | |
| 7568 | + | |
| 7569 | + | |
| 7570 | + | |
| 7571 | + | |
7567 | 7572 | | |
7568 | 7573 | | |
7569 | 7574 | | |
| |||
7631 | 7636 | | |
7632 | 7637 | | |
7633 | 7638 | | |
7634 | | - | |
| 7639 | + | |
7635 | 7640 | | |
7636 | 7641 | | |
7637 | 7642 | | |
| |||
7642 | 7647 | | |
7643 | 7648 | | |
7644 | 7649 | | |
7645 | | - | |
| 7650 | + | |
7646 | 7651 | | |
7647 | 7652 | | |
7648 | 7653 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
321 | 321 | | |
322 | 322 | | |
323 | 323 | | |
324 | | - | |
325 | | - | |
326 | | - | |
327 | | - | |
328 | | - | |
329 | | - | |
| 324 | + | |
| 325 | + | |
| 326 | + | |
| 327 | + | |
| 328 | + | |
| 329 | + | |
| 330 | + | |
| 331 | + | |
330 | 332 | | |
331 | 333 | | |
332 | 334 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
23 | 23 | | |
24 | 24 | | |
25 | 25 | | |
26 | | - | |
| 26 | + | |
27 | 27 | | |
28 | 28 | | |
29 | 29 | | |
| |||
132 | 132 | | |
133 | 133 | | |
134 | 134 | | |
| 135 | + | |
| 136 | + | |
| 137 | + | |
| 138 | + | |
| 139 | + | |
| 140 | + | |
| 141 | + | |
| 142 | + | |
| 143 | + | |
| 144 | + | |
| 145 | + | |
| 146 | + | |
| 147 | + | |
| 148 | + | |
| 149 | + | |
| 150 | + | |
| 151 | + | |
| 152 | + | |
| 153 | + | |
| 154 | + | |
135 | 155 | | |
136 | 156 | | |
137 | 157 | | |
| |||
149 | 169 | | |
150 | 170 | | |
151 | 171 | | |
152 | | - | |
| 172 | + | |
153 | 173 | | |
154 | 174 | | |
155 | 175 | | |
| |||
320 | 340 | | |
321 | 341 | | |
322 | 342 | | |
323 | | - | |
| 343 | + | |
324 | 344 | | |
325 | 345 | | |
326 | 346 | | |
327 | 347 | | |
328 | 348 | | |
329 | | - | |
| 349 | + | |
| 350 | + | |
| 351 | + | |
| 352 | + | |
| 353 | + | |
330 | 354 | | |
331 | 355 | | |
332 | 356 | | |
| |||
1446 | 1470 | | |
1447 | 1471 | | |
1448 | 1472 | | |
1449 | | - | |
1450 | | - | |
| 1473 | + | |
| 1474 | + | |
| 1475 | + | |
1451 | 1476 | | |
1452 | 1477 | | |
1453 | 1478 | | |
| |||
0 commit comments