Repository navigation
feat(types): arm object-timeline by reference to its spec row (objectui#10859, batch 3) - #11248
Conversation
…ctui#10859, batch 3) `safeValidateSchema` refused every `object-timeline` document at `type`: the block is registered and curated, and `@objectstack/spec` 17.5.0 declares its `ComponentPropsMap` row, but `AnyComponentSchema` carried no arm. `ObjectTimelineBlockSchema` is built the way batch 2 built `object-metric`: `BaseSchema` + the literal + `properties` = the row by reference through the import boundary (its spec defaults stripped), plus the node's `dataSource` binding as the spec's `ElementDataSourceSchema`, and the objectui#9256 refusals of both content channels. It joins `ObjectQLPublicBlockComponentSchema`. The bare-key ratchet falls 73 -> 72; the census rows the new export and the new spec import force are added. Claude-Session: https://claude.ai/code/session_0122Knsowci76D2rBWReCzzZ 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#10859 (body and all 19 comments — the route A release Check-runs on the head: 43 in all — 40 success, 3 skipped ( ① Derived judgments
② Semver level
③ Boundary flagsDev
Implemented-by: VERDICT: PASS |
…e-count the propsBag docblock (objectui#10859, batch 3 patch 1)
`object-metric` and `object-master-detail-form` are elementDataSourceBlock-
wrapped and read the node's `dataSource` through ElementDataSourceGate, but
their arms did not declare it, so the strict authoring face refused a
spec-valid bound node by name. Both now declare it with the construct the
`object-timeline` arm uses: the spec's ElementDataSourceSchema by reference,
described by the module's ELEMENT_DATA_SOURCE_BINDING_DESCRIPTION. One
strict-face row per arm in the batch-2 pin.
The propsBag docblock no longer counts its importers ("two" was false once
`object-timeline` joined). Existing parity rows, the README and the pending
changeset name the new member; no census row added.
Claude-Session: https://claude.ai/code/session_0122Knsowci76D2rBWReCzzZ
Co-authored-by: Claude <noreply@anthropic.com>
✅ 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: Delta review on the round-1 record Read: the round-1 record; the delta and the net diff; the card's one comment newer than the record, the dev's round report Check-runs on the head. First read: 42 — 34 success, 3 skipped, 5 ① Derived judgments
② Semver level
③ Boundary flagsDev
Implemented-by: VERDICT: PASS |
Part of #10859
Clause-②: yes
Clause-②: yes, copied from the PM claim5915916825:@object-ui/types/zodaccepts a new node type (object-timelinewas refused attypeand now has an arm), a widening of the published accept set. Batches 1 and 2 declaredyeson the same method.Batch 3 of objectui#10859, route A (release
5867551936: "a specComponentPropsMaprow counts as a published declaration.propertiesis judged by reference").object-timelineis registered by@object-ui/plugin-timeline, curated by ADR-0080, and declared by@objectstack/spec17.5.0'sComponentPropsMap['object-timeline']row, butAnyComponentSchemahad no arm for it. SosafeValidateSchema, andobjectui validatewith it, refused every document naming it withinvalid_unionattype. The card stays open for the designer six, the (ii) and (iii) keys, and the flat-arm fork measured below.What changed
packages/types/src/zod/objectql.zod.ts: newObjectTimelineBlockSchema, built the way batch 2 builtObjectMetricBlockSchema. It isBaseSchema, plus theobject-timelineliteral, plusproperties, which ispropsBag('object-timeline', stripImportedDefaults(SpecObjectTimelinePropsSchema)): the shared helper, the row by reference, no copy and no third helper. The node also declaresdataSourceas the spec'sElementDataSourceSchemaby reference (see below), and the two batch-2 arms (object-metric,object-master-detail-form) declare the samedataSourcewith the same construct (patch round 1).bodyandchildrenare refused by name with the objectui#9256neitherContentChannelGuidanceconstruct. The arm joinsObjectQLPublicBlockComponentSchema, soAnyComponentSchema's arm list does not change.packages/types/src/zod/index.zod.ts: one barrel export.packages/types/src/__tests__/object-timeline-arm-10859-b3.test.ts: the new pin.packages/cli/src/__tests__/registered-types-validate-ratchet-10859.test.ts:REFUSED_AT_TYPEgoes from 73 to 72, the moved key is named in the docblock, and one row countsobject-timelineas armed. Draft PR objectui#11069's hunks are not touched.packages/types/src/__tests__/zod-mirror-parity.test.ts: the oneEXCLUSIONSrow the new export forces, in batch 2's wording; patch round 1 rewords the two batch-2 rows to name their newdataSourcemember (no new row). The union row's "the two public-block arms above" became "the public-block arms above", because "two" is no longer true..changeset/10859-object-timeline-zod-arm.md:'@object-ui/types': minor, with no BREAKING banner because this is a pure widening.Files beyond the claimed surface. Each one was forced, and each is named here:
imported-defaults-8317.test.ts: its census goes red for any spec schema a mirror imports without anIMPORTEDrow. This change adds one row.registered-type-arms-10859-b2.test.ts: its exact list ofObjectQLPublicBlockComponentSchemaliterals gainsobject-timeline; patch round 1 adds one row per batch-2 arm (adataSource-bound bag node, strict and tolerant faces, with a lit control).packages/types/src/zod/README.md: the "ObjectQL Public Blocks" group now lists the new arm (AGENTS.md Add automated testing infrastructure and CI/CD workflows #2).Zone 2: the PM's mechanism assumptions, measured before building
object-timelineis registered (ComponentRegistry.register('object-timeline', ObjectTimelineRenderer, …)) and listed inKNOWN_SCHEMA_TYPES.packages/types/src/zod/exported no arm for it. On basecb2f6fb5bf, both{ type: 'object-timeline' }and{ type: 'object-timeline', properties: { objectName: 'task' } }are refused on both faces with exactly oneinvalid_unionat['type'].@objectstack/specis 17.5.0.ComponentPropsMap['object-timeline'] === ObjectTimelinePropsSchemaat runtime. The row is strict, has no required member, and has 15 keys. Unlike batch 2's rows, it carries spec defaults (timeline.scale,navigation.mode/preventNavigation/openNewTab/size), so the import boundary hands back a rebuilt copy. The pin holds that this face writes no default into a parsed document; its control is that the spec's own parse does. The renderer reads neither content channel:ObjectTimelineand therenderer.tsxit composes have nochildren/bodyread (one comment hit), and the registration rendersObjectTimelinethroughElementDataSourceGate. So the arm refuses both channels.import '@object-ui/plugin-timeline',SchemaRendererinsideSchemaRendererProvider, a recording adapter), with a temporary file that is not committed:{ type, properties: { objectName: 'campaign', timeline, limit: 25 } }givesfind("campaign", {"$top":25}), thetimeline-canvasrenders, and both seeded titles are drawn;{ dataSource: { object: 'campaign' }, properties: { timeline } }givesfind("campaign", {"$top":100})and renders;objectNamemakes 0findcalls;timelinewith no date axis renderstimeline-missing-date-axis, which shows the bag'stimelineis read.EXCLUSIONSrow forObjectTimelineBlockSchema. The spec import forced oneIMPORTEDrow in the objectui#8317 census, listed above.One addition the order did not name:
dataSource. The registration is wrapped inelementDataSourceBlock, so the node reachesObjectTimelinethroughElementDataSourceGate, which reads the node'sdataSource(measured in item 3). That key is the spec'sPageComponentSchema.dataSource, not a member of the props row. Without a declaration, the strict authoring face would refuse a spec-valid{ type: 'object-timeline', dataSource: { object: … } }by name. It is declared the way objectui#11070 declared it onobject-gridand the other gate-wrapped arms of the same module:stripImportedDefaults(SpecElementDataSourceSchema)with the module's existingELEMENT_DATA_SOURCE_BINDING_DESCRIPTION. The declaration is by reference, and nothing is restated.Tests (every run below at head
9fe676e31c, throughos-verify-lock.sh, slotissue-10859)Red on base, first. On base with only the pin present,
vitest runover the pin and a temporary measurement file givesTests 16 failed | 2 passed (18). That is 16 red pin rows and 1 green pin row, plus the measurement file. The one green pin row is the lit control, which says the fixture is spec-valid by the spec's own row.Green.
registered-type-arms-10859-b2,imported-defaults-8317,zod-mirror-parityand the ratchet:Test Files 6 passed (6),Tests 312 passed (312). That run included a temporary measurement file, not committed.pnpm exec vitest run packages/types/ packages/cli/:Test Files 316 passed (316),Tests 7432 passed (7432).Arm-list consumer sweep (ruling
5862923926). It covers every tracked test file matching one of the following, found withgit grep -lwandgit grep -l:AnyComponentSchema,StrictAnyComponentSchema,safeValidateSchema,ObjectQLPublicBlockComponentSchema,nodeOracles,KNOWN_SCHEMA_TYPES,propsLevelOf,PUBLIC_BLOCKS,unmirroredAlias,collectArms,getPublicConfigs,ComponentPropsMap,validateSchemaorStrictAuthoringFace;check-handler-key-read-sites,block-config-schema-parity,registry-inputs-spec-parity,strict-authoring-face,zod-mirror-parity,objectql.zodorindex.zod.That is 326 files. The 144 outside
packages/types/andpackages/cli/gaveTest Files 144 passed (144),Tests 2575 passed (2575). They include app-shell'sblock-config-schema-parity-8216,public-contract,registry-inputs-spec-parity,public-block-binding-reachandcheck-handler-key-read-sites.Type check.
pnpm --filter @object-ui/types buildexited 0 with✓ dist completeness: 1 package(s) complete.pnpm --filter @object-ui/types type-check(tsc --noEmit && tsc -p tsconfig.examples.json && tsc -p tsconfig.test.json) exited 0, andtsc -p tsconfig.test.json --listFilesOnlylists the new pin.Runtime ablation. This used
ablation-replace.mjsin WRAP mode with its own EXIT/INT/TERM trap.ObjectTimelineBlockSchemawas removed fromObjectQLPublicBlockComponentSchema: the anchor went from 1 to 0 hits, and the blob went from71b873d0a086to69e995b14a66.Tests 18 failed | 20 passed (38), withrefuses 73 registered bare key(s) at type; the pin is 72.@object-ui/types/zodtosrc, so no build ran between mutation and reading.71b873d0a086, andgit diff HEADis empty.Type-level reverse validation. The bag was replaced with
z.strictObject({ objectName: z.string().optional() }).tsc -p tsconfig.test.jsonthen exited 2 with exactly one error:TS2344 Type 'false' does not satisfy the constraint 'true'on the pin's bag-equality row. Restored: blob equals HEAD, andgit diff HEADis empty.End to end.
objectui validateran in-process throughvalidate()fromcommands/validate.ts, with a temporary file that is not committed.✓ Schema is valid!and exits 0.dataSource-bound timeline prints✓ Schema is valid!and exits 0.properties.variant: 'grid'prints✗ Schema validation failed!and exits 1.Gates (exit code captured before any pipe; each gate's own verdict line)
node scripts/check-changeset-presence.mjsexit 0:8 source file(s) of 2 released package(s) changed, and this change declares 1 changeset(s)pnpm changeset:checkexit 0:No changeset declares a major bumppnpm check:control-bytesexit 0:OK (scanned 9642 tracked text file(s); skipped 85 binary)pnpm check:handler-key-readsexit 0:OK 140 arm(s), 212 registration(s) … every judged read is a declared member of its armpnpm check:new-line-citationsexit 0:0 new citation(s)check:pending-changeset-literals,check:changeset-claims(report-only),check:test-path-roots,check:spec-symbols,check:installed-pin-claims,check:element-data-source-declaration,type-check:coverage,markdown-test-inputs.mjs --audit,census:changeset-polarity,check:doc-types,check:unreferenced-sources,check:esm-specifiers.check-governed-queue-guard.mjs --test) printedNOT GOVERNED — 9 path(s).eslint --no-inline-config --format jsonover the 7 changed.tsfiles. The population comes from each package's own lint script:@object-ui/typeslints.and@object-ui/clilintssrc. Result: 0 errors and 3 warnings (no-explicit-any). The same 3 warnings are on the two base blobs, so this change adds none.eslint.config.jshas noprojectServiceorparserOptions, so linting is not type-aware, and this diff cannot move any untouched file's verdict. The fullpnpm lintis CI's.check:readme-exports. Reason: the population collapsed because 34 packages are unbuilt (packagesRead: found 3, floor is 25), so the gate itself says this run proves nothing. No README code fence changed; CI measures it.git merge-tree --write-treeagainstorigin/mainb32e7debc8exits 0. Against PR objectui#11069's heada11f73347d, the only conflict ispackages/cli/src/commands/check.ts, which conflicts betweenmainand that PR on its own. The ratchet file merges clean.The fork for the next batch: the three flat-arm neighbours (measured, no edit)
ObjectFormSchema,ObjectMapSchemaandObjectGanttSchemaare FLAT arms inobjectql.zod.ts, while the installed spec gives each block apropertiesrow, and each row isComponentPropsMap[...]by identity. The producer column comes from a classifier over each node literal:propertieskey opens on the node.object-metricnodes are all BAG (8), and objectui'sobject-formnodes are FLAT.{ type, properties: { objectName } }(spec row: valid)object-formobjectNameinvalid_type,modeinvalid_value. Strict face addspropertiesunrecognized_keys.content/docs5,examples5 (byo-backend-console 2, schema-catalog 2 JSON + 1 test),skills1, designer 2 (ObjectManager/FieldDesignerruntime form schemas). Alsoplugin-formREADME 3, plus 20 runtime composers in package sources (app-shell, plugin-form, plugin-view), which the validator never sees.new-project-wizardpage, whichobjectui validaterefuses today (the carrier note5885358145).object-mapcustom"no record source" at the root. Strict face addsproperties.content/docs15 (+1 Schema API block), schema-catalog 3 JSON, console test fixtures 2. Alsoplugin-mapREADME 3 (+1 Schema API block), and runtime composers inListView/ObjectView.object-ganttcustom"no record source" at the root. Strict face addsproperties.content/docs11 (+1 Schema API block), schema-catalog 3 JSON,skills1, console test 1. Alsoplugin-ganttREADME 10 (+1 Schema API block), and runtime composers inListView/ObjectView.The flat spelling of each block is accepted on both faces (controls). objectstack was read at
origin/main72f8c38201:examples,apps,content,skillsandpackages/studio, with zero FLAT producers of any of the three. Converting a flat arm to the bag while live flat producers exist is a narrowing, and it needs its own ruling. The dev report'sopen_questionscarries it with the four-axis analysis.Acceptance notes
dataSourceon batch 2's arms: folded into this PR in patch round 1 (26f8120ca2).object-metricandobject-master-detail-formare gate-wrapped (elementDataSourceBlock) and read the node'sdataSource. At9fe676e31ctheir batch-2 arms did not declare it, soStrictAnyComponentSchemarefused{ type: 'object-metric', dataSource: { object: 'task' } }withunrecognized_keys ['dataSource'](measured on the built dist), while the tolerant face accepted it. Both arms now declaredataSourcewith the same construct asobject-timeline, with one row per arm in the batch-2 pin, reproduced red first. Both arms are still unreleased, so against the last release this only shapes what they accept on arrival.object-timelineproducers: no authored document in objectui or objectstack writes one today. The only writers areListView/ObjectViewruntime composers, which never meet the validator. So this arm changes no shipped document's verdict.Implemented by
session_0122Knsowci76D2rBWReCzzZ(https://claude.ai/code/session_0122Knsowci76D2rBWReCzzZ), branchclaude/issue-10859-object-timeline-by-reference.Generated by Claude Code