Repository navigation
Commit 2cf9db7
fix(spec): the gantt, timeline and map binding warnings describe the refusals objectui left, not the floors it deleted (#19788)
Fixes #19630
Clause-②: no — author-facing warning text and its premise corrected to
what the renderer does; the warning class is held by the #16577 ruling
(B), no accept/reject change, no public surface added
## What was wrong
Three `VIEW_BINDING_BLOCKS` rows in
`packages/spec/src/kernel/functional-completeness.ts` stated renderer
fallbacks that objectui has deleted, and the warning
`checkViewCompleteness` prints on `os validate` for those three types
inherited the generic body built on the same premise ("the renderer
falls back to literal default field names ... the view renders empty").
For `map` the stale literal `locationField || 'location'` had three
carriers: the row, the block-present `map` message (which quoted it as
the renderer's read), and the `functional-completeness.test.ts` pin that
held it.
## The re-derivation, at the pin
The card's verdicts were measured at objectui `main` `0cf2d6644`. They
were **not** inherited: all three were re-derived at the objectui pin
this repo ships, `.objectui-sha` = `87af769e9a3e` (read on `origin/main`
at `43e17b8905`), from a read-only fetch of that exact commit. Every
verdict held at the pin, so there is no fork to report:
- **`gantt` — FALSE (confirmed).** `plugin-list/src/ListView.tsx` `case
'gantt'` spreads `startDateField` / `endDateField` / `titleField` only
when declared (the date floors deleted by objectui#7070, the `progress`
/ `dependencies` floors by objectui#7499, omitted rather than refused).
`plugin-gantt/src/ObjectGantt.tsx` `getGanttConfig` takes its flat
branch only with both dates, otherwise returns `null`, and the `if
(!ganttConfig)` arm renders "Gantt configuration required. Please
specify startDateField, endDateField, and titleField." A refusal by
name, not a blank chart.
- **`timeline` — HALF FALSE (confirmed).** `case 'timeline'` resolves
the axis via `resolveTimelineDateBinding` and spreads it only when
declared; the `'created_at'` floor is gone (objectui#7070 step three, on
the ruling 日期轴永不虚构), while `titleField: dateBinding.titleField ||
'name'` is kept on purpose. `plugin-timeline/src/ObjectTimeline.tsx`
ends its start-date chain with no literal rung and, with no authored
items and no start date, renders the `timeline.unconfigured.noDateAxis`
refusal ("Timeline date axis required — ...",
`data-testid="timeline-missing-date-axis"`).
- **`map` — FALSE (confirmed).** `case 'map'` forwards
`resolveListMapConfig(schema)` with no `locationField || 'location'`
floor (objectui#8169). `plugin-map/src/ObjectMap.tsx` `getMapConfig`'s
unconfigured branch returns only `{ style }` (no guessed coordinate
names) and `hasCoordinateBinding` — applied to every branch, a declared
block included — renders "Map configuration required — declare
map.locationField or map.latitudeField + map.longitudeField". Zero
`'location'` literals remain in `ObjectMap.tsx` at the pin; the one in
`ListView.tsx` is the tombstone comment.
- `kanban` (`groupByField || groupField ||
detectStatusField(objectDef)`) and `tree` (`labelField || titleField ||
'name'`) were re-read at the pin and still hold. The `plugin-view` /
`app-shell` `ObjectView.tsx` faces were grepped at the pin too: they
carry the same deletions as tombstone comments, no live floor.
## What this PR changes
- **The three rows** now state what the pin shows, name both halves of
each path, and each carries an **asserting pin citation**
(`.objectui-sha` = `87af769e9`), so the next pin bump reds on them
rather than letting them rot. `check:objectui-pin-citations` lists 4
asserting citations in this file (1 before, 3 new), 46 repo-wide.
- **The re-measurement note** that recorded the three as stale ("do not
cite them") is replaced by a short history: which card corrected which
rows, and at which ref.
- **Per-type bodies.** `VIEW_BINDING_MESSAGE` gains `gantt`, `timeline`
and `map` entries beside `calendar`, each written from its row's
reading. The generic `unboundBlockMessage` body now reaches only
`kanban` and `tree`, the two rows it is still true of.
- **The block-present `map` message** no longer quotes `locationField ||
'location'`; it names the `hasCoordinateBinding` refusal and the keys
that clear it.
- **The prescription is preserved on every body**: gantt names
`gantt.startDateField` / `gantt.endDateField` / `gantt.titleField` (the
three `GanttConfigSchema` requires); timeline names
`timeline.startDateField` / `timeline.titleField` (the two
`TimelineConfigSchema` requires) and says only the title has a renderer
default; map names `map.locationField` or the lat/lng pair.
`VIEW_BINDING_FIX` is unchanged: all three hints were already correct.
- **No severity moves and no firing moves.** Every route stays
`warning`; the same six view types warn on the same inputs. That is
consistent with #16577's ruling B (comment `5634033966`) for the
`calendar` route, whose reasoning is that both doors are loud; these
rows now measure the same two-door shape. The docblock says explicitly
that this is consistency with the ruling, not an extension of it, and it
does not reopen it.
## Tests
- The map pin at the old `:221` was re-judged in place, not dropped: it
now asserts the literal is **absent** (`not.toContain("|| 'location'")`)
and that the body names `Map configuration required`,
`hasCoordinateBinding`, `map.locationField` and `map.latitudeField`.
- New `it.each` over gantt / timeline / map: no literal-fallback
sentence, the renderer's refusal text, the component file, every key the
refusal names, severity `warning`.
- The generic-body pin shrinks from five types to `kanban` and `tree`.
**Reverse verification (one-shot, not kept).** With the fix committed
(`c0131a1325`), `functional-completeness.ts` was replaced on disk by its
`43e17b8905` blob (landing proven: old-literal count 1, new `Gantt
configuration required` count 0) and the test file run against it: **4
failed / 61 passed**, exit 1: the three new per-type pins plus the
re-judged map pin. Direction: red, as predicted. Restored with `git
checkout HEAD -- PATH` under an EXIT/INT/TERM trap; restoration proven
by `git hash-object` equal to the HEAD blob (`57a4b064e8`) and an empty
`git diff HEAD`. The test imports `./functional-completeness` from
source, so no dist rebuild sat between mutation and measurement.
## Validation — exit codes captured before any pipe, head `c0131a1325`
- `pnpm --filter @objectstack/spec build` · `vitest run
src/kernel/functional-completeness.test.ts` (**65 passed**) · `pnpm
--filter @objectstack/spec typecheck`: one locked run, `VERDICT
command-exit 0`.
- `pnpm --filter "@objectstack/lint..." --filter
"@objectstack/objectql..." build`: **0**; then `@objectstack/lint`
`vitest run src/validate-functional-completeness.test.ts`: **0** (25
passed). That suite asserts rule ids and paths, not message text.
- `pnpm --filter @objectstack/spec check:generated`: **0**.
- `node scripts/check-issue-citations.mjs --base origin/main`: **0**
(diff-scoped half; `pnpm check:issue-citations` is also in the derived
set, **0**).
- `pnpm exec eslint --no-inline-config --format json` over the two
changed sources: **0**, 2 files, 0 errors, 0 warnings. That is a proven
narrowing, not a skipped lint: `eslint.config.mjs` enables no type-aware
linting (no `parserOptions.project`, no typed rules; its own comment at
`:327-328` says so), so this diff cannot change the verdict on any file
it does not touch. The repo-wide `pnpm lint` is CI's.
- `node scripts/pm/dispatch-gates.mjs --commands --repo
objectstack-ai/objectstack` derived **82** commands; all 82 were run,
each with its exit code recorded. `--ran` reconciles: **82 derived, 80
run, 2 NOT MEASURED, 0 UNRUN**. The two NOT MEASURED are `pnpm
check:dual-build-cjs-loads` and `pnpm check:type-check-debt`, both exit
3 PREREQUISITE NOT MET because they need a full `./packages/*` build.
That is out of reach under the foreground cap, so it is declared for CI.
`check:doc-formula-expressions` and `check:lean-entry-closure` first
exited 3 (unbuilt closure); both were re-run after the closure build
above and returned **0**. `check:objectui-pin-citations`: **0** (46
asserting match the pin, 37 historical).
## Acceptance notes
- `packages/lint/src/validate-list-view-field-refs.ts` (its docblock
near `:26-31`) paraphrases the old premise of
`view/layout-without-binding` ("the renderer then falls back to literal
default field names and the view renders empty"). It is a comment in
another package, outside this card's file surface. Noted, not filed;
carrier: none.
- `resolveTimelineDateBinding` at the pin also reads a `calendar`
block's `startDateField` as a timeline axis, so a `type: 'timeline'`
view that carries a `calendar` block and no `timeline` block renders,
and still gets this warning. That is unchanged by this PR (firing did
not move), and the row now records it. Observation only.
- Released `CHANGELOG.md` entries still carry the old generic sentence.
Released entries are amended only in a dedicated docs-only PR, never as
a rider.
- Labels: the dispatch names none and a changeset is present, so no
label was written.
---
_Generated by [Claude
Code](https://claude.ai/code/session_01VWsFyWDp8Rjb2Ma6a3Cyo8)_
Co-authored-by: Claude <noreply@anthropic.com>1 parent 628e55d commit 2cf9db7
3 files changed
Lines changed: 171 additions & 58 deletions
File tree
- .changeset
- packages/spec/src/kernel
| 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 | + | |
Lines changed: 51 additions & 15 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
125 | 125 | | |
126 | 126 | | |
127 | 127 | | |
128 | | - | |
129 | | - | |
130 | | - | |
131 | | - | |
| 128 | + | |
| 129 | + | |
| 130 | + | |
| 131 | + | |
132 | 132 | | |
133 | 133 | | |
134 | 134 | | |
| |||
186 | 186 | | |
187 | 187 | | |
188 | 188 | | |
189 | | - | |
190 | | - | |
191 | | - | |
192 | | - | |
193 | | - | |
194 | | - | |
195 | | - | |
196 | | - | |
197 | | - | |
| 189 | + | |
| 190 | + | |
| 191 | + | |
| 192 | + | |
| 193 | + | |
| 194 | + | |
| 195 | + | |
| 196 | + | |
| 197 | + | |
| 198 | + | |
| 199 | + | |
| 200 | + | |
| 201 | + | |
| 202 | + | |
| 203 | + | |
| 204 | + | |
| 205 | + | |
| 206 | + | |
| 207 | + | |
| 208 | + | |
| 209 | + | |
| 210 | + | |
| 211 | + | |
| 212 | + | |
| 213 | + | |
| 214 | + | |
| 215 | + | |
| 216 | + | |
| 217 | + | |
| 218 | + | |
| 219 | + | |
| 220 | + | |
| 221 | + | |
| 222 | + | |
| 223 | + | |
| 224 | + | |
| 225 | + | |
198 | 226 | | |
199 | 227 | | |
200 | 228 | | |
| |||
212 | 240 | | |
213 | 241 | | |
214 | 242 | | |
215 | | - | |
| 243 | + | |
| 244 | + | |
216 | 245 | | |
217 | 246 | | |
218 | 247 | | |
219 | 248 | | |
220 | 249 | | |
221 | | - | |
| 250 | + | |
| 251 | + | |
| 252 | + | |
| 253 | + | |
| 254 | + | |
| 255 | + | |
| 256 | + | |
| 257 | + | |
222 | 258 | | |
223 | 259 | | |
224 | 260 | | |
| |||
0 commit comments