Repository navigation
fix(plugin-timeline): refuse a gantt row that is not an object - #10351
Merged
os-project-manager merged 1 commit intoSep 24, 2026
Merged
Conversation
classifyGanttRows now refuses every row that is not a plain object (null, a number, a string, a boolean, an array) through the existing timeline.gantt.unusableRange.malformedRow key, instead of drawing an empty, unlabelled row. The renderer now agrees with validate, which already refused these shapes at authoring time. No new key and no pack strings. This deliberately supersedes the objectui#7164 A+ clause that kept items: [0] and items: [[]] drawing; those control pins are rewritten to expect the refusal, with the ruling id (5809218505) as their reason. Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01D486C1axmXnrkJMNUfz2eb
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
|
os-project-manager
marked this pull request as ready for review
September 24, 2026 20:03
os-project-manager
deleted the
claude/issue-7364-timeline-nonobject-row
branch
September 24, 2026 20:15
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 #7364
Clause-②: no
What this does
classifyGanttRows(plugin-timelinerenderer.tsx) now refuses every gantt ROW that is not an object, not onlynull. A row that is a number, a string, a boolean or an array (items: [0],['x'],[true],[[]]) used to draw an empty, unlabelled row with no word to the author. It is now refused through the EXISTINGtimeline.gantt.unusableRange.malformedRowkey, naming the path and value, for exampleitems[0] is 0, which is not a row shapeanditems[0] is an array, which is not a row shape. No new key, no locale pack edit, no change tovalidate. The renderer now agrees withvalidate, which already refused these shapes at authoring time."Not an object" is
typeof row !== 'object' || row === null || Array.isArray(row): the set JSON can spell and the zod mirror (z.object) refuses. No prototype test is made (aDate, class instance orProxyrow cannot be written in JSON; the live-Proxy row control keeps drawing).This deliberately supersedes one clause of the objectui#7164 A+ ruling
Ruling: objectui#7364 comment 5809218505, UI closure batch 2 item 1, letter A, maintainer 「同意」. The #7164 A+ ruling required the control rows
items: [0]anditems: [[]]to keep DRAWING, and they were pinned as controls. We are overriding that clause of the A+ ruling on the maintainer's word above. The control assertions were not quietly "made green": each is rewritten to expect the refusal, with the ruling id stated beside it, and none is deleted:timeline-gantt-malformed-row-7164.test.tsx: the two control rows are removed from the DRAWS table with a comment pointing at the new block; a new blocka row that is NOT AN OBJECT is refused — objectui#7364 supersedes the #7164 controlpins[0],[[]],['x'],[true]as REFUSED atitems[0](diagnostic text, row clause, not the date clause, zero bars, empty axis,role="alert"), a non-object row beside good rows (items[1] is 0, wins over a later bad date), and a control that well-formed object rows (1 and 2 rows), a row with noitemskey and a row whoseitemsisnullstill DRAW. The file header records the supersession.timeline-gantt-date-brand-7027.test.tsxpin 6: the same two former controls move out of the DRAWN list and are asserted as refusals, with the reason.packages/types/src/__tests__/timeline-items-row-shape-7164.test.ts: header comment only. It said[0]and[[]]"still DRAW in the renderer", which this change makes false; corrected. No assertion changed.One exclusion site moved (stated, not hidden)
Array.isArray(row)now runs before U3 readsrow.items, so a revoked Proxy handed as a ROW dies atIsArrayrather thanget. That is the same move objectui#7164 already made foritemsand a row'sitems: same exclusion (JSON cannot spell a proxy), the site moved one operation up inside the same function. The pin 5 row intimeline-gantt-date-brand-7027.test.tsxis updated with that reason, and theclassifyGanttRowsdocblock says so.Verification (head
9e09349a9)pnpm exec vitest run --maxWorkers=2 packages/plugin-timeline/ packages/types/src/__tests__/timeline-items-row-shape-7164.test.ts(repo root, under the shared verify lock):Test Files 28 passed (28),Tests 353 passed (353).row == null(mutant marker count 1, fix marker count 0 on disk), then the two edited test files run:Tests 7 failed | 55 passed (62). Red: the four non-object rows, the beside-good-rows case, the revoked-Proxy-as-ROW site pin, and pin 6's control block. The well-formed row controls stayed green. Restored withgit checkout HEAD --;git diff HEADempty and the on-disk blob hash equals the HEAD blob hash.turbo run build --filter=@object-ui/plugin-timeline^...(10/10) then plugin-timelinetype-check(tsc --noEmit && tsc -p tsconfig.test.json, which lists both edited test files): exit 0.--no-inline-configon the four touched source/test files: 0 errors (17 pre-existing warnings, none on changed lines).check:new-line-citations(0 new),check:control-bytes,check:changeset-claims,check:pending-changeset-literals,check:test-path-roots,check-changeset-presence.mjs,check-changeset-no-major.mjs: all exit 0.pnpm lint/ fullpnpm testshards: declared to CI, not run locally.Acceptance notes
items: [{ label: 'R', items: null }]is still refused byvalidateand still DRAWS as an empty row in the renderer. That corner is a finding(plugin-timeline): a gantt row that isnull, or whoseitemsis a truthy non-array, crashes the render —findUnusableGanttDatereads the walk defensively andcalculateDateRangereads it bare #7164 control this ruling did not name, so it is untouched here..changeset/7364-timeline-nonobject-row.md,@object-ui/plugin-timelinepatch.Session:
https://claude.ai/code/session_01D486C1axmXnrkJMNUfz2ebGenerated by Claude Code