Repository navigation
fix(plugin-timeline,plugin-calendar,plugin-kanban): a failed load no longer keeps a data view on its error screen after a later load succeeds (objectui#10663) - #10680
Conversation
…ws (objectui#10663) ObjectTimeline set `error` only in its fetch catch and cleared it nowhere, so one failed load kept the error screen up after later loads succeeded. Since objectui#10623 a failed data-invalidation re-read was enough to get there. The current run of the fetch effect now clears `error` when it commits rows, and only the current run writes `error` at all (a run sequence, the objectui#10578 shape). A failed background re-read is still reported: this block has no silent mode. Claude-Session: https://claude.ai/code/session_01KUxVUa7e39aNjhkKi1gsoy Co-authored-by: Claude <noreply@anthropic.com>
…run commits rows (objectui#10663) ObjectCalendar and ObjectKanban set `error` only in their fetch catch and cleared it nowhere, the same defect objectui#10578 fixed on ObjectGantt. Since objectui#10572 a failed data-invalidation re-read was enough to keep either block on its error screen until a remount. Each now clears `error` when the current run commits rows, inside the fetch effect's existing `isMounted` guard. The calendar also clears it where host `data` is committed, beside the ceiling reset that sits there for the same reason. A failed background re-read is still reported: neither block has a silent mode. Claude-Session: https://claude.ai/code/session_01KUxVUa7e39aNjhkKi1gsoy Co-authored-by: Claude <noreply@anthropic.com>
…ars (objectui#10663) Claude-Session: https://claude.ai/code/session_01KUxVUa7e39aNjhkKi1gsoy Co-authored-by: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KUxVUa7e39aNjhkKi1gsoy Co-authored-by: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KUxVUa7e39aNjhkKi1gsoy Co-authored-by: Claude <noreply@anthropic.com>
|
changeset-claim-re-read
|
✅ 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
|
Contract reviewServed-tier: Read: card objectui#10663 (body, triage ① Derived judgmentsThe triage's binding text ( 1. 2. The run-sequence guard cannot let a superseded run clear or set the error. Effect runs execute synchronously in commit order, so 3. The rows' lifecycle is unchanged (separate finding, as the brief asked). 4. 5. 6. "Does a failed background re-read keep the last good rows?" stated and true. For all three the 7. Census population and completeness, judged independently. I re-derived the census on
8. Nothing asked is missing; nothing done that was not asked. The measurement is the first pin case of the timeline file (red on base by construction, see 10). The 9. Existing pins edited or deleted: none. The file list holds three added test files and no modified test. Nothing was weakened. The two controls the PR cites ( 10. Can the new pins fail? Yes; each has a lit control and a negative leg. All three files mount through the real
11. objectui#10664 boundary holds. Grep over the three sources' diff for ② Semver level
③ Boundary flags
Implemented-by: VERDICT: PASS |
Fixes #10663
Clause-②: no
A data view that fails one load no longer stays on its error screen after a later load succeeds. No export, schema, prop or accept set moves. Dispatched by the
domain:uiseat 5, sessionhttps://claude.ai/code/session_01KUxVUa7e39aNjhkKi1gsoy.What changed
The card's census found three data views with the objectui#10578 defect. Each set
errorin its fetchcatch, cleared it nowhere, and returned the error screen early whenevererrorwas set. Since objectui#10623 (timeline) and objectui#10572 (calendar, kanban), each also re-reads on every data-invalidation event, so one failed background re-read was enough to keep a healthy view on its error screen until a remount.Each now takes the objectui#10578 shape: the current run clears
errorwhen it commits rows. The clear is not made when a run starts, so the report stays until rows land.ObjectTimeline(@object-ui/plugin-timeline): the fetch effect had no run guard. AfetchSeqRefrun sequence now scopes botherrorwrites to the current run: the clear on commit, and the failure write in thecatch. A superseded run can no longer clear the current run's error, or raise the error screen over the current run's rows. The rows write itself is untouched (see Acceptance notes).ObjectCalendar(@object-ui/plugin-calendar): the clear sits on each commit branch of the fetch effect (inline provider,object,api), inside the run's existingisMountedguard. It also sits in the host-dataeffect, beside the row-ceiling reset that is already there for the same reason: the handed-over rows are not the query that failed.ObjectKanban(@object-ui/plugin-kanban): the clear sits on the fetch commit, inside the run's existingisMountedguard. Host, bound and inline cards are read straight from props, so there is no other commit site.Does a failed background re-read keep the last good rows? No, for all three. None has a silent mode (
ObjectGanttandObjectMapdo). The failure is reported, the rows stay in state but are not drawn, and the next re-read that succeeds takes the screen back. Each pin file pins this.Files:
packages/plugin-timeline/src/ObjectTimeline.tsx(+24/-2),packages/plugin-calendar/src/ObjectCalendar.tsx(+21/-1),packages/plugin-kanban/src/ObjectKanban.tsx(+11/-0). Three new pin files beside them. Threepatchchangesets, one per package.The boundary with this seat's parallel objectui#10664 holds: no changed line in the three sources touches an effect's dependency list, a
useEffect(or auseCallback((grep over the diff: 0 hits). The removed lines are the timeline'sreactimport line, its barecatchwrite and the calendar's one-lineapicommit.Census: every data view under
packages/plugin-*/srcandpackages/components/src/renderersthat keeps anerrorstate from a fetchThe population was enumerated from two sides: every
set…Error(writer, and everyuseStateerror slot or object-shapederrorwrite. Each writer was read. A third side, every file that callsfind(oraggregate((67 files), confirms that the views with no error state have no error screen to stick.ObjectTimelineObjectCalendarObjectKanbanObjectGanttObjectMapObjectGrid,ListView(loadError),ObjectTree,ObjectChartObjectDataTable,ObjectMetricWidget,ObjectPivotTableDatasetWidget,DatasetReportRendererdata-list,record-picker, theelementsaggregateLineItemsPanel(plugin-form)domain:ui#4seat's live claim, PR objectui#10650. Probe reproduced; reported to the seatOutside the data-view population, listed so the census is complete:
ObjectForm,DrawerForm,ModalForm,SplitForm,TabbedForm,WizardFormnever clearerroreither. They are record-page renderers, not data views, by the product's own split inanchors.ts("List / Interface page = a data view ... Record page renders one object record."). Each also runs two fetches (the object schema and the record) with no run guard, so "clear on a successful commit" has no single home: a record read that succeeds over a stale schema would clear a schema failure. A probe reproduced the defect onObjectFormthrough its objectui#10572 bus re-read. Reported to the seat, not changed here.react-page'sloadErrorguards a dynamic import of the code runtime, not a data fetch.plugin-chatbothooks,Mermaid,ImportWizardand the designer metadata pages are not data views, and each clears anyway.saveError,submitError,addError,exportErrorandmutationErrorare write errors, not load errors.Pins: red on base, green on head
Each pin file mounts its view through the real
SchemaRendererand its package's own registration, and holds everyfindopen by hand. The second load is a data-invalidation re-read (notifyDataChanged).Base leg: the three sources were swapped to their base blobs (
4758b33) on the committed head4f1d532, and the three pin files ran with the two controls. Result:Tests 8 failed | 21 passed (29), with both controls green. The restore was proven by blob equals HEAD for each file and an emptygit diff HEAD. Head leg, same five files:Tests 29 passed (29). The six pin and source blobs are identical at the final head5abe386.dataafter a failed own fetch clears itControls:
ObjectGantt.errorClears-10578.test.tsxandObjectMap.busReread-10623.test.tsxwere green on base and on head in both legs.Ablations
The superseded-success pins cannot fail on base, because base never clears. Their red legs are ablations on the committed head, each through the objectstack
ablation-replace.mjsin WRAP mode. The anchor had to hit once, and each landing is proven by an anchor count of 1 to 0 and a blob change. Each restore is proven by blob equals HEAD and an emptygit diff HEAD.isCurrent():1 failed | 4 passed, the superseded-success pin.isCurrent():1 failed | 4 passed, the superseded-failure pin.object-arm clear moved outsideisMounted:1 failed | 4 passed, the superseded-success pin.isMounted:1 failed | 3 passed, the superseded-success pin.Local verification (HEAD
5abe386, after mergingorigin/mainat7baede3)pnpm turbo run buildwith--filter='PKG^...'for each of the three packages,--concurrency=2:Tasks: 13 successful, 13 total.pnpm exec vitest run packages/plugin-timeline/ packages/plugin-calendar/ packages/plugin-kanban/plus the two control files, at5abe386:Test Files 143 passed (143),Tests 1109 passed (1109). The same three suites alone at2d03929:Test Files 141 passed (141),Tests 1094 passed (1094).pnpm --filter @object-ui/PKG type-checkfor each of the three packages, at2d03929: exit 0, with the script name echoed. The last merge (2d03929to5abe386) brought oneapps/consoletest and one changeset, outside all three packages' dependency closures. Each new pin file is in its package'stsconfig.test.jsonprogram (--listFilesOnly: 1 hit each).5abe386, each exit 0:check:control-bytes,check:test-path-roots,check:vi-mock-specifiers,check:vi-mock-inherit,check:vi-mock-override-shape,check:shell-escape-residue,check:unreferenced-sources,check:i18n-keys,type-check:coverage,lint:coverage,check:pending-changeset-literals,check-changeset-no-major,check-changeset-overwrite,check-changeset-fixed.check:new-line-citations: "VERDICT new-cross-file-line-citations: 0 new citation(s)".check-changeset-presence: "6 source file(s) of 3 released package(s) changed, and this change declares 3 changeset(s)".check-governed-queue-guard --testover the nine paths: NOT GOVERNED.check:changeset-claims(report-only): details under Acceptance notes.check:sdui-registration-pins, reason: it exits 2 with "No console build to weigh at apps/console/dist/assets" (a missing prerequisite, not a verdict). This diff touches no registration and nosideEffectsfield; CI builds the console and runs it.eslint.config.jslints**/*.{ts,tsx}and declares noparserOptions.projectorprojectService, so no type-aware rule runs and this diff cannot move any untouched file's verdict. The--format jsonoutput counted 6 files, 0 errors. The source files carry 26, 30 and 30 warnings on head, the same as their base blobs. The pin files carry 6, 9 and 6 warnings, the sameanypattern the sibling pins use.Acceptance notes
error): the timeline's rows write is unguarded. A superseded answer that lands late overwrites the current run's rows. Probe:currentShown=false supersededShown=true. Itsfinallyalso releasesloadingfor any run. The same race onObjectMapwas repaired in PR objectui#10649 (its case B). This PR's guard covers the twoerrorwrites only; the rows write is outside this card's ruled scope.ObjectGanttandObjectMapkeep the last good rows on a failed background re-read. The timeline, calendar and kanban report it. This PR states and pins the second behaviour and does not add a silent mode.data, bound rows and authored items straight from props and commit nothing for them. If a view flips from fetching for itself to host rows after a failure, the error stays until the next successful fetch of its own. The calendar commits host rows to state, so it clears there.setLoading(true)andloadingis checked beforeerror. That is pre-existing, and this PR does not change it.check:changeset-claimslists 12 pending changesets that nameObjectCalendar.tsxorObjectKanban.tsx. None of them describes theerrorlifecycle (grep: the only hit is a@ts-expect-error), so all still hold.LineItemsPaneland the six record forms are reported to the seat with probe readings, as above.Generated by Claude Code