Repository navigation
fix(plugin-gantt, app-shell): refuse an invalid gantt block; designer spec derivations fail loudly - #13490
Conversation
… spec derivations fail loudly ObjectGantt renders a refusal naming each GanttConfigSchema issue instead of drawing the unvalidated block. The metadata-admin *-schema.ts derivations no longer catch a failed derivation from the bundled spec and degrade the form. Co-authored-by: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AdaeVx4N1y9QsiBkJ31nfJ
A hoisted vi.mock of zod leaked its failing toJSONSchema into view-schema.test.ts in the same worker; vi.doMock + doUnmock keeps it inside the throwing cases. Co-authored-by: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AdaeVx4N1y9QsiBkJ31nfJ
Co-authored-by: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AdaeVx4N1y9QsiBkJ31nfJ
✅ 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
|
席位核对 — ACCEPT · PR #13490 @
|
Contract reviewServed-tier: Written 2026-10-25T03:45Z · face: narrowing ( ① Derived judgments
② Semver level
③ Boundary flagsDev report: 6392494130 on #13459. Seat ACCEPT: 6392708594 on the PR, echoed on the card at 6392845769. PR author login
Implemented-by: VERDICT: PASS The narrowing refuses what the published spec already refused, is pinned in both directions, and widens nothing; the designer half moves a build-time failure from a silent degraded form to a red test and an error boundary with no published surface touched. Generated by Claude Code |
Requested by Elon · project thread
Fixes #13459
Clause-②: no
Metadata-protocol: narrowed
What changes
1.
ObjectGanttrefuses aganttblock that failsGanttConfigSchema(packages/plugin-gantt/src/ObjectGantt.tsx).Before:
safeParsefailure →console.warn→ the unvalidated block was returned and drawn, so a misspelt or missing key still rendered a plausible chart. NowgetGanttConfigreturns{ config: null, invalidBlock }on that branch and the component renders a refusal (role="alert",data-testid="gantt-invalid-config") naming every parse issue by its path in the block, e.g.gantt.endDateField: …,gantt: Unrecognized key: "startField". The console warning and the shadowed-flat-keys warning still fire. Unchanged: a valid block, the flat ObjectView / ListView spelling (still not parsed, as before), and the "Gantt configuration required" screen for a view with no binding.2. The five designer spec derivations fail loudly (
packages/app-shell/src/views/metadata-admin/{dashboard,package,page,report,view}-schema.ts).The ten
try { … } catch { console.warn(…) }sites (sevenz.toJSONSchemaderivations, three form clones) and their_…Failedmemo flags are removed. Their only input is the bundled@objectstack/spec, so a failed derivation is a build-time fact: it fails the tests beside these files, and at runtime it propagates to the route'sErrorBoundary(console/AppContent.tsx), which shows the error and reports it, instead of rendering a form silently missing fields. The getters' return types narrow fromJsonSchema | undefinedtoJsonSchema. No runtime input reached those catches: the dashboard form's only runtime argument,locale, goes throughlocalizeMetadataForm, which does not throw on an unknown locale.tzShift.ts(timeZonefallback) is out of scope per the claim (it waits on a spec-row decision).Tests
On head
e26d1cd:packages/plugin-gantt/src/ObjectGantt.invalidBlockRefusal-13459.test.tsx(4): an undeclared key and a missing required field are each refused with the path named and no chart; the console diagnostic stays; CONTROL: a valid block renders its tasks.packages/app-shell/src/views/metadata-admin/spec-derivation-13459.test.ts(14): each of the seven getters derives an object schema from the bundled spec, and each THROWS (and does not warn) whenz.toJSONSchemathrows. The failingtoJSONSchemais a scopedvi.doMock+doUnmock: a first version used a hoistedvi.mock, which leaked intoview-schema.test.tsin the same worker (3 failures, fixed ina3b60c1).git checkout HEAD --,git diff HEADempty after):ObjectGantt.tsxreverted toorigin/main→ the three refusal cases fail, CONTROL passes;view-schema.tsreverted → the threeview-schema.*throw cases fail, the rest pass.pnpm exec vitest run packages/plugin-gantt/→ Test Files 100 passed | 1 skipped (101), Tests 775 passed | 114 skipped.git grep -lEover the five module names and their callersPackageFormDialog,*DefaultInspector,ViewColumnInspector,ViewVariantInspector,ReportConfigPanel) → Test Files 88 passed (88), Tests 721 passed. Blind spot: a test reaching these modules through another import path is not in that set; CI's shardedpnpm testruns the whole package.type-check:@object-ui/plugin-ganttexit 0,@object-ui/app-shellexit 0 (turbo, bothtsc --noEmitandtsconfig.test.json).eslint --no-inline-configon the touched files 0 errors;check:new-line-citations,check:changeset-claims,check-changeset-no-major,check-changeset-presence,check:i18n-keys,check:vi-mock-specifiers,check:vi-mock-inherit,check:vi-mock-override-shape,check:control-bytes,check:test-path-rootsall exit 0.check:readme-exportsNOT MEASURED (needs every package's dist; CI builds first).Acceptance notes
ObjectTimelinestill only warns on a failedTimelineExtensionSchema.safeParse(its refusal covers a missing date axis only). Same shape as this card's gantt half; not changed here (outside the claimed surface).if (!specXForm || typeof specXForm !== 'object') return undefinedguards in the form getters remain: they are not catch-and-warn sites and the existing tests assert the forms are defined.Generated by Claude Code
🤖 Generated with Claude Code
https://claude.ai/code/session_01AdaeVx4N1y9QsiBkJ31nfJ