feat(plugin-calendar): declare the three record-source keys object-calendar already honours - #8340
Merged
os-justin merged 2 commits intoSep 7, 2026
Conversation
…lendar already honours `ComponentPropsMap['object-calendar']` declares nine top-level keys; after objectui#8201's first slice the registrations published six. These are the remaining three — `data`, `staticData` and `loading` — and with them this block's reverse-parity backlog is empty. Each was measured at its own sink, and they are not the same sink: `data` and `loading` are read off the PROPS channel at the renderer boundary (`resolveExternalData` / `resolveExternalLoading` in `index.tsx`), `staticData` off the SCHEMA by the shared record-source ladder's rung 2. `loading`'s coupling to `data` was slice 1's reasoning and is now a measurement: authored `loading: true` replaces a `data`-fed calendar with its loading placeholder and does nothing at all to a `staticData`-fed one. Each declared description NAMES the position it is true about, and a pinned row keeps those sentences in place — a description recommending a write the renderer would drop is this gate's own failure mode one layer in. objectui#8212's three-part obligation is paid for both array-armed keys: the `inputs` entry, deletion of the `UNPUBLISHED_EXEMPTIONS` entry, and a `MEMBER_PINS` entry apiece — never an exemption, so `MEMBER_PIN_EXEMPTION_CEILING` does not move. Both halves of the shrink-only backlog ceiling move 8 -> 5. Two findings recorded rather than assumed. "An authored `data` skips the internal fetch" is true on BOTH carriers — `SchemaRenderer` spreads the node key as a prop while the ladder also reads `schema.data`, and a bare array carries no `provider`, so no query is issued either way — which makes it an assertion that cannot fail; the pin rests on the authored ROWS BEING DRAWN instead, and the companion row is labelled as such. And `staticData` joins `SUPERSEDES_BINDING` in the console's binding-reach probe, with its ladder rung quoted: filling it is the author telling the block not to fetch. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01YBWFb5YgMU5dw8p2VKj16S
…endar-data-staticdata-loading # Conflicts: # apps/console/src/__tests__/registry-inputs-spec-parity.test.ts
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-justin
marked this pull request as ready for review
September 7, 2026 13:55
os-justin
enabled auto-merge
September 7, 2026 13:56
os-justin
deleted the
claude/issue-8314-calendar-data-staticdata-loading
branch
September 7, 2026 14:20
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 #8314
Slice 2b of objectui#8201, and the one that empties
object-calendar's reverse-parity backlog:data,staticDataandloadingare now DECLARED on bothplugin-calendarregistrations, so the html tier stops reporting working metadata asunknown-prop. Every key@objectstack/specdeclares for this block is discoverable.Measured per key, at its own sink — and the sinks are not the same
dataarrayresolveExternalData(rest.data)inindex.tsx, forwarded as the component'sdataprop, whereArray.isArraymakeshasExternalDatastaticDataarrayObjectCalendarloadingbooleanresolveExternalLoading(rest.loading), applied only underhasExternalDataloading's coupling todatawas slice 1's reasoning; it is now a measurement. Authoredloading: truereplaces adata-fed calendar with its loading placeholder and does nothing at all to astaticData-fed one — one controlled pair, only the row-carrier differs, opposite verdicts. So it ships declared on exactly those terms, with the coupling named in its published description.⛔ The false green this PR was written around — measured, not inherited
objectui#8313 found
object-kanban'sdatadoubly guarded. The same two-carrier arrangement exists here and produces a different false green, so it was re-derived rather than ported:SchemaRendererspreads every non-metadata node key as a React prop, so an authoreddataarray arrives BOTH asrest.dataat the renderer boundary AND asschema.datainside the component, where the ladder's rung 1 returns it verbatim as a record-source config. A bare array carries noprovider, so it matches no fetch branch and no query is issued either way. "Authoringdataskips the internal fetch" is therefore true of a tree where the boundary dropsdataentirely — an assertion resting on it cannot fail.Confirmed by ablation: with
data={externalData}deleted from the boundary,expect(dataSource.find).not.toHaveBeenCalled()passed and the very next line (the authored rows are drawn) reddened. The pin rests on the rows; the query row is kept, ordered query-first so the ablation reads off the failure line, and labelled as a companion rather than as the claim.The three-part obligation (objectui#8212), paid for both array keys
inputsentries;UNPUBLISHED_EXEMPTIONSentries deleted in the same change;MEMBER_PINSentry apiece — never an exemption, soMEMBER_PIN_EXEMPTION_CEILINGstays 62.Both halves of the shrink-only backlog ceiling move together, as the ratchet requires.
d8ab2dc0c, where the ledger readtoBe(8)— not the 4 the dispatch brief predicted, because #8313 (object-kanban's four array keys) had not landed yet. The first commit here therefore moved 8 → 5. #8313 then merged while this branch was open,mainmoved to614d85b19, and the merge conflicted on exactly those lines. Resolved by re-deriving rather than by picking a side: the ceiling now reads 1, and the whole remaining backlog isobject-kanban.quickAdd— the escalated key, untouched here. Both the history table and the prose carry both steps.Neither array key declares an
of, and that is derivedComponentPropsMap['object-calendar'](installed@objectstack/spec17.3.0) rows both keys asz.array(z.unknown()).optional(). Every coarse member kind parses —['a', 1, true, [], {}, null]is accepted whole — so no single-kindofis available (objectui#8067's rule), and the READ SITE is the whole of the member contract there is. Same reading thefilterandsortentries on this block already record.Clause ② — measured, not asserted
All three parse together on one strict
safeParsecall while a probe key on the same call drawsunrecognized_keys:So this restores
declared = enforcedrather than publishing anything new — the grounds objectui#8186 and objectui#8223 cleared on, re-measured because objectui#8172 falsified exactly this assumption forlimit.Descriptions name the POSITION they are true about
Each published description says when the key is honoured, not only what it means, and a pinned row keeps those sentences in place — a description recommending a write the renderer would drop is this gate's own failure mode one layer in. The negative half is pinned too: no description may teach the
{ provider, items }config spelling, because the contract refuses it by kind (invalid_type,expected: 'array') and recommending it would harden a second dialect (AGENTS.md #0.1).One rider, in the file that owns it
staticDatajoinsSUPERSEDES_BINDINGinapps/console/src/__tests__/public-block-binding-reach.test.tsx. That probe fills EVERY declared input and then asserts the block queried itsobjectName;staticDatais rung 2 of the ladder, one aboveobjectName, so filling it is the author telling the block not to fetch. Without the entry the probe manufactures its own finding — which it did, as a red, the moment the declaration landed. Added with the guard quoted, exactly as that ledger's own docblock requires, and the file's instance count moved with it.Verification — every verdict quoted, all of it re-run after the merge
Type-check ran only after
pnpm --filter '@object-ui/console^...' build, twice — a staledistreports TS2307/TS2882 across untouched files and is not a verdict.Every ablation ran from the committed implementation, mutated a READ SITE (never a pin), proved the mutation reached disk by
git hash-objectdiffering fromgit rev-parse HEAD:PATH, and restored by state (git diff HEADempty and the hash equal again):data={externalData}at the boundarystaticDatarung (packages/core)staticData-dependent rowsloading={externalLoading}at the boundaryloading-honoured rowobject-calendar.dataexemptioncarries no stale unpublished-key exemptionand the backlog ceilingobject-calendar.staticDataMEMBER_PINSentryobject-calendar pins the member shape of every array/object input it declaresloading's POSITION sentenceUnder vitest every
@object-ui/*specifier resolves to that package'ssrc(vitest.config.mtsresolve.alias), so no build stands between a source mutation and the measurement.What is NOT here
object-kanban.quickAddis untouched — its disposition is the product ruling objectui#8285 owns.getCalendarConfig'scalendar: {}behaviour is the ruled objectui#7071 one and was not "fixed".ObjectCalendaralso honours an off-spec{ provider, items }config object underdata(measured — rows drawn, no query issued), a spellingComponentPropsMaprejects by kind. Whether the renderer's extra dialect is retired or the contract widened is a product/contract ruling, not a measurement.🤖 Generated with Claude Code
https://claude.ai/code/session_01YBWFb5YgMU5dw8p2VKj16S