fix(spec): the gantt, timeline and map binding warnings describe the refusals objectui left, not the floors it deleted - #19788
Conversation
…refusals objectui left, not the floors it deleted Re-derived at the objectui pin (87af769e9): the three VIEW_BINDING_BLOCKS rows, their per-type warning bodies, the block-present map message and its test pin now state the named refusal screens, with asserting pin citations. No severity or firing change. Co-authored-by: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VWsFyWDp8Rjb2Ma6a3Cyo8
📓 Docs Drift CheckThis PR changes 1 package(s): 9 hand-written doc(s) NAME something this change touched and may need an implementation-accuracy re-verification:
⛔ 1 release-owned page(s) also name something this change touched. These are read-only:
What this run could not see
Coarse fallback — 136 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): Which tree this was computed onThis run read A worktree cut from an older # while this PR is open — GitHub drops the merge commit once it closes
git fetch origin 4aa7d38eb8fb7a3de4888736cfd4b5b35c1950e0 && git checkout 4aa7d38eb8fb7a3de4888736cfd4b5b35c1950e0
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin cc2e9511c84823e81219be092e6b285a76b36787 c0131a1325c6a6d86cc1e1812cc2aaa9f9fcd177 && git checkout -B drift-repro cc2e9511c84823e81219be092e6b285a76b36787 && git merge --no-ff c0131a1325c6a6d86cc1e1812cc2aaa9f9fcd177
node scripts/docs-audit/affected-docs.mjs --json cc2e9511c84823e81219be092e6b285a76b36787
|
Contract reviewServed-tier: ① Derived judgmentsRe-derived at the objectui pin
② Semver level
③ Boundary flags
Implemented-by: VERDICT: PASS Rendered by an isolated at-tier review subagent (card, prior ruling, precedent PR, the PR and its check-runs — not the dispatch order), adopted by Generated by Claude Code |
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_BLOCKSrows inpackages/spec/src/kernel/functional-completeness.tsstated renderer fallbacks that objectui has deleted, and the warningcheckViewCompletenessprints onos validatefor 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"). Formapthe stale literallocationField || 'location'had three carriers: the row, the block-presentmapmessage (which quoted it as the renderer's read), and thefunctional-completeness.test.tspin that held it.The re-derivation, at the pin
The card's verdicts were measured at objectui
main0cf2d6644. They were not inherited: all three were re-derived at the objectui pin this repo ships,.objectui-sha=87af769e9a3e(read onorigin/mainat43e17b8905), 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.tsxcase 'gantt'spreadsstartDateField/endDateField/titleFieldonly when declared (the date floors deleted by objectui#7070, theprogress/dependenciesfloors by objectui#7499, omitted rather than refused).plugin-gantt/src/ObjectGantt.tsxgetGanttConfigtakes its flat branch only with both dates, otherwise returnsnull, and theif (!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 viaresolveTimelineDateBindingand spreads it only when declared; the'created_at'floor is gone (objectui#7070 step three, on the ruling 日期轴永不虚构), whiletitleField: dateBinding.titleField || 'name'is kept on purpose.plugin-timeline/src/ObjectTimeline.tsxends its start-date chain with no literal rung and, with no authored items and no start date, renders thetimeline.unconfigured.noDateAxisrefusal ("Timeline date axis required — ...",data-testid="timeline-missing-date-axis").map— FALSE (confirmed).case 'map'forwardsresolveListMapConfig(schema)with nolocationField || 'location'floor (objectui#8169).plugin-map/src/ObjectMap.tsxgetMapConfig's unconfigured branch returns only{ style }(no guessed coordinate names) andhasCoordinateBinding— applied to every branch, a declared block included — renders "Map configuration required — declare map.locationField or map.latitudeField + map.longitudeField". Zero'location'literals remain inObjectMap.tsxat the pin; the one inListView.tsxis the tombstone comment.kanban(groupByField || groupField || detectStatusField(objectDef)) andtree(labelField || titleField || 'name') were re-read at the pin and still hold. Theplugin-view/app-shellObjectView.tsxfaces were grepped at the pin too: they carry the same deletions as tombstone comments, no live floor.What this PR changes
.objectui-sha=87af769e9), so the next pin bump reds on them rather than letting them rot.check:objectui-pin-citationslists 4 asserting citations in this file (1 before, 3 new), 46 repo-wide.VIEW_BINDING_MESSAGEgainsgantt,timelineandmapentries besidecalendar, each written from its row's reading. The genericunboundBlockMessagebody now reaches onlykanbanandtree, the two rows it is still true of.mapmessage no longer quoteslocationField || 'location'; it names thehasCoordinateBindingrefusal and the keys that clear it.gantt.startDateField/gantt.endDateField/gantt.titleField(the threeGanttConfigSchemarequires); timeline namestimeline.startDateField/timeline.titleField(the twoTimelineConfigSchemarequires) and says only the title has a renderer default; map namesmap.locationFieldor the lat/lng pair.VIEW_BINDING_FIXis unchanged: all three hints were already correct.warning; the same six view types warn on the same inputs. That is consistent with spec(ui): the list-view calendar guard gates onappearance.allowedVisualizationsONLY —type: 'calendar'with nocalendar:block parses CLEAN at all three doors #16577's ruling B (comment5634033966) for thecalendarroute, 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
:221was re-judged in place, not dropped: it now asserts the literal is absent (not.toContain("|| 'location'")) and that the body namesMap configuration required,hasCoordinateBinding,map.locationFieldandmap.latitudeField.it.eachover gantt / timeline / map: no literal-fallback sentence, the renderer's refusal text, the component file, every key the refusal names, severitywarning.kanbanandtree.Reverse verification (one-shot, not kept). With the fix committed (
c0131a1325),functional-completeness.tswas replaced on disk by its43e17b8905blob (landing proven: old-literal count 1, newGantt configuration requiredcount 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 withgit checkout HEAD -- PATHunder an EXIT/INT/TERM trap; restoration proven bygit hash-objectequal to the HEAD blob (57a4b064e8) and an emptygit diff HEAD. The test imports./functional-completenessfrom source, so no dist rebuild sat between mutation and measurement.Validation — exit codes captured before any pipe, head
c0131a1325pnpm --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/lintvitest 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-citationsis also in the derived set, 0).pnpm exec eslint --no-inline-config --format jsonover the two changed sources: 0, 2 files, 0 errors, 0 warnings. That is a proven narrowing, not a skipped lint:eslint.config.mjsenables no type-aware linting (noparserOptions.project, no typed rules; its own comment at:327-328says so), so this diff cannot change the verdict on any file it does not touch. The repo-widepnpm lintis CI's.node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstackderived 82 commands; all 82 were run, each with its exit code recorded.--ranreconciles: 82 derived, 80 run, 2 NOT MEASURED, 0 UNRUN. The two NOT MEASURED arepnpm check:dual-build-cjs-loadsandpnpm 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-expressionsandcheck:lean-entry-closurefirst 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 ofview/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.resolveTimelineDateBindingat the pin also reads acalendarblock'sstartDateFieldas a timeline axis, so atype: 'timeline'view that carries acalendarblock and notimelineblock renders, and still gets this warning. That is unchanged by this PR (firing did not move), and the row now records it. Observation only.CHANGELOG.mdentries still carry the old generic sentence. Released entries are amended only in a dedicated docs-only PR, never as a rider.Generated by Claude Code