Repository navigation
feat(types)!: an authored object-gantt takes its props in the spec's properties bag; the flat spelling is refused by name (objectui#10859, batch 6) - #11337
Conversation
…properties bag (objectui#10859, batch 6) ObjectGanttBlockSchema is the authored object-gantt arm: BaseSchema + the literal + NODE_ENVELOPE + properties = the installed 17.5.0 ComponentPropsMap['object-gantt'] row by reference through propsBag, the dataSource binding, one aliasKeyRefusal per row member (less the node-level label the spec's page component also declares), the flat mirror's GanttConfig members and dependencyField alias pointed at properties.gantt.KEY, the objectui#9256 channel refusals, and the record-source rule read in the bag through requireRecordSource(..., 'properties'). It joins ObjectQLPublicBlockComponentSchema; the flat ObjectGanttSchema mirror leaves ObjectQLComponentSchema (9 to 8) and stays exported. The TypeScript twin is re-declared as the post-hoist, code-composed reading, not retired. Claude-Session: https://claude.ai/code/session_011p7ikEivgXefNDaE5S5Uec Co-authored-by: Claude <noreply@anthropic.com>
…iage it forces (objectui#10859, batch 6) New pin object-gantt-properties-bag-10859-b6.test.ts: both faces accept the bag (object-bound, inline, provider, dataSource-only, node-level label), the flat spelling is refused by name on both faces (row members to properties.KEY, GanttConfig members and the dependencyField alias to properties.gantt.KEY), the row is judged by reference with no authored default, the record source is read in the bag and counts the binding, and the flat mirror stays published. Forced census rows: zod-mirror-parity (one EXCLUSIONS row), imported-defaults-8317 (one IMPORTED row), registered-type-arms-10859-b2 (literal list), objectql-union-arms-7363 (9 to 8), public-block-responsive-styles-10872 (DECLARES_DATA_SOURCE and the record-source carve-out). Fixture triage where a face now judges the bag: content-channel-e3-residual-9256, objectql-record-source-refinement-6939, strict-face-read-keys-11070. The three schema-catalog gantt entries move their props into the bag. Claude-Session: https://claude.ai/code/session_011p7ikEivgXefNDaE5S5Uec Co-authored-by: Claude <noreply@anthropic.com>
…ui#10859, batch 6) The three schema-catalog gantt entries now write their props in the properties bag. The render-identity pin's anti-vacuity row reads the bag (its PRE_REPAIR readings hold unchanged, since SchemaRenderer hoists it), and the catalog-plans pin, which mounts ObjectGantt directly, hoists the bag the way SchemaRenderer does before drawing each plan. Claude-Session: https://claude.ai/code/session_011p7ikEivgXefNDaE5S5Uec Co-authored-by: Claude <noreply@anthropic.com>
… rendered (objectui#10859, batch 6) Through the real registry and a recording adapter: the bag queries its object with its own filter and sort and hands the chart one task per row; the two flat spellings code still composes make the identical call and hand the chart the same tasks; a dataSource-bound bag queries the bound object; a bag on inline rows draws them without a host query; control: a bag naming another object never queries the fixture's. Claude-Session: https://claude.ai/code/session_011p7ikEivgXefNDaE5S5Uec Co-authored-by: Claude <noreply@anthropic.com>
…sets (objectui#10859, batch 6)
content/docs/plugins/plugin-gantt.mdx and packages/plugin-gantt/README.md
author their object-gantt nodes as { type, properties: { ..., gantt } }; the
flat field-mapping keys are described as the ObjectView / ListView handoff,
and the direct ObjectGantt mounts keep their flat schema prop, now said so.
Changesets: @object-ui/types minor with a BREAKING (authoring) banner, and
@object-ui/plugin-gantt patch for the README and the two new src/ pins.
Claude-Session: https://claude.ai/code/session_011p7ikEivgXefNDaE5S5Uec
Co-authored-by: Claude <noreply@anthropic.com>
…i#10859, batch 6) Claude-Session: https://claude.ai/code/session_011p7ikEivgXefNDaE5S5Uec 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
|
|
Generated by Claude Code |
Contract reviewServed-tier: PR objectui#11337 (objectui#10859, batch 6, ① Derived judgments
② Semver level
③ Boundary flags
Out-of-scope notes, against the filing classes and measured reach:
The PR body: each sentence checked is true at this head — the arm, the union counts, the five producers and the one governed listing, the 23 files and their forcing, the per-face base measurement, the draft state, the two changesets, the Implemented-by: VERDICT: PASS Generated by Claude Code |
…ties-bag Claude-Session: https://claude.ai/code/session_011p7ikEivgXefNDaE5S5Uec 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
|
…jectui#11168 slice 3, round 3) origin/main db0beb2: PR B (#11351, 17dc167), objectui#11331 (bef9f20) and #11337 (db0beb2). Two conflicts, both resolved by measurement: - apps/console registry-inputs-spec-parity.test.ts: the per-owner total. Census of the merged ledgers: unjudgedBlocks 2 (object-gantt, object-timeline), offSpecInputs 0, unpublishedKeys 3, refusedArms 0 (B emptied the map), memberPins 0, so objectui#11168 owns 5; 8652 and 8649 stay 0. Neither side's 6 or 7. - packages/app-shell i18n.ts (en and zh): B's deletions of option.layout.inline / grid kept, with this branch's reworded object-form.columns row. Claude-Session: https://claude.ai/code/session_01VhxTqosz7wn54ahqyxgERT Co-authored-by: Claude <noreply@anthropic.com>
Part of #10859
Clause-②: yes (narrowing)
Clause-②: yes (narrowing), copied from the PM claim5924906396:@object-ui/types' authoring faces widen (a spec-shapedobject-ganttbag node that is refused today parses) and narrow (a flatobject-ganttnode that parses today is refused). This is objectui's narrowing-as-minorrule with a BREAKING (authoring) banner in the changeset, as in batches 1 to 5.Batch 6 of objectui#10859, the last flat-arm block. It executes seat 1's flat-arm answer at PR objectui#11248's ACCEPT (
5917261346) for ONE block,object-gantt, following batch 5 (PR objectui#11309) as merged with PR objectui#11312 (onerequireRecordSource(type, rungs, at); the cross-seat pointer5924134305). The card stays open for the designer six and the (ii) / (iii) keys.What changed
packages/types/src/zod/objectql.zod.ts: newObjectGanttBlockSchema, batch 5's construct. It isBaseSchema+ theobject-ganttliteral +NODE_ENVELOPE+properties = propsBag('object-gantt', stripImportedDefaults(SpecObjectGanttPropsSchema)): the shared helpers and the installed 17.5.0 row by reference, no copy, no new helper. Beside it:dataSource, the spec'sElementDataSourceSchemaby reference (the registration iselementDataSourceBlock-wrapped);aliasKeyRefusalper member of the row, keyed by the row's own key set read off the crossed row ("Did you meanKEY→properties.KEY?"), lesslabel(see Deviations);aliasKeyRefusalper member of the row'sganttblock, pointed atproperties.gantt.KEY, plus the flat mirror's legacydependencyFieldpointed atproperties.gantt.dependenciesField. These are the flatGanttConfigkeys the flat mirror declared on the node;body/childrenrefused with the flat mirror's objectui#9256 string;requireRecordSource('object-gantt', RECORD_SOURCE_KEYS, 'properties'). It counts a non-emptydataSource.object, so a bag node bound only throughdataSourceparses on both faces.ObjectQLPublicBlockComponentSchema.ObjectGanttSchema(the flat mirror) leavesObjectQLComponentSchema(9 to 8 arms), stays exported, and stays paired with its TypeScript twin in the parity census. Its docblock gains a "No longer an authoring arm" section.packages/types/src/objectql.ts: the TypeScriptObjectGanttSchemais re-declared, not retired. Its members are unchanged; its docblock says it is the node asObjectGanttreads it afterSchemaRendererhoistsproperties, and as code composes it. The TypeScript union's docblock names the zod union's new count.packages/types/src/zod/index.zod.ts(one barrel export) andpackages/types/src/zod/README.md(the ObjectQL public-block group lists the arm, 7).content/docs/plugins/plugin-gantt.mdx, the threeexamples/schema-cataloggantt entries,packages/plugin-gantt/README.md.packages/types/src/__tests__/object-gantt-properties-bag-10859-b6.test.ts(both faces, the row by reference, the flat keys, the record source, the split) andpackages/plugin-gantt/src/ObjectGantt.propertiesBag-10859.test.tsx(render through the real registry)..changeset/10859-object-gantt-properties-bag.md(@object-ui/typesminor, BREAKING (authoring) banner) and.changeset/10859-plugin-gantt-properties-bag-docs.md(@object-ui/plugin-ganttpatch: README and the two touchedsrc/test files; no runtime change).Files beyond the claimed surface, each forced:
zod-mirror-parity.test.ts(oneEXCLUSIONSrow;EXPECTED_MIRROR_PAIRSuntouched),imported-defaults-8317.test.ts(oneIMPORTEDrow),registered-type-arms-10859-b2.test.ts(the exact literal list gainsobject-gantt),objectql-union-arms-7363.test.ts(8 arms,object-ganttnot among them),public-block-responsive-styles-10872.test.ts(object-ganttjoinsDECLARES_DATA_SOURCEand the record-source carve-out);content-channel-e3-residual-9256.test.ts,objectql-record-source-refinement-6939.test.ts,strict-face-read-keys-11070.test.ts, the schema-catalogobjectql-record-source-render-identity-6939.test.tsx(its anti-vacuity row reads the bag; its PRE_REPAIR render readings hold unchanged) and plugin-gantt'sObjectGantt.catalogPlans-11141.test.tsx(it mountsObjectGanttdirectly, so it hoists the catalog bag the waySchemaRendererdoes).Zone 1, measured before building
@objectstack/spec17.5.0:ComponentPropsMap['object-gantt']exists and is the exportedObjectGanttPropsSchema(17 members, strict; itsganttmember is the 29-keyGanttConfig).PageComponentSchemarefuses{ type: 'object-gantt', objectName, gantt }withunrecognized_keys ['objectName', 'gantt']("Unrecognized key(s) on this page component … ADR-0089 D3a") and accepts the same props inproperties. A flatstartDateFieldis refused the same way. Control: a flataction:buttonactionTypeis refused the same way. The row exists, so the bag is that row by reference (no mirror bag, unlikeobject-chart).5262f7dd3, 138 tracked files nameobject-gantt: 11CHANGELOG.md, 27 pending changesets, 77 test files and 23 others:plugin-gantt.mdx(10 nodes and the Schema API block), the 3 schema-catalog entries,packages/plugin-gantt/README.md(8 nodes)schemaprop, no hoist)plugin-gantt.mdx"Task Click", README "Interactive Gantt" and "Integration with Data Sources"ListView.tsx,ObjectView.tsx(flatten a stored gantt view, write the flatGanttConfigkeys and thesearchpair)SchemaRendererand never meet the zod facesobjectql.ts,objectql.zod.tsObjectGantt.tsx,plugin-gantt/src/index.tsx,register-plugins.tsknown-schema-types.ts,public-blocks.ts,record-source.ts, comments (ValueDataSource.ts,plugin-tree/src/index.tsx,registerCatalogBlocks.ts), twoscripts/check-*ledgers, prose (component.prompt.md,data-source.md)skills/**skills/objectui/guides/page-builder.md"Gantt plugin example" (one flat node, plus prose teaching the flat field keys on the node)Stop line: not tripped. No objectui context builds anything from the zod
ObjectGanttSchemaobject: its only non-test reader was theObjectQLComponentSchemaunion, and that union's only reader isAnyComponentSchema. The non-page contexts that keep the flat spelling depend on the TypeScript twin (the composers,ObjectGantt'sschemaprop) or on the registration'sinputs(the sdui-parser html tier), not on that object.3. The arm, as above.
ObjectGanttSchemais re-declared, not retired.4. Producers: rewritten as above; one governed producer listed.
5. Pins: below. The objectui#10859 ratchet does not move:
object-ganttwas never refused attype.Batch 5's finding, re-measured. On base,
safeValidateSchemaalready accepts the flat{ type: 'object-gantt', dataSource: { object: 'task' }, gantt }(PR objectui#11312 counts the binding on every arm), so the finding no longer reproduces on the flat arm. For the bag arm it is answered: adataSource-only bag node parses on both faces (pinned), anddataSource: { object: '' }with no rung is refused.Zone 2, re-measured
5262f7dd3.object-gantt(table above).strict-face-read-keys-11070.test.ts;git merge-tree --write-tree HEADagainst its head139a49137exits 0, and againstorigin/main5262f7dd3exits 0.Tests (heavy runs through
os-verify-lock.sh, slotissue-10859){ type: 'object-gantt', properties: { objectName, gantt } }refused bysafeValidateSchema(RECORD_SOURCE_REQUIREDat the root) and by the strict face (the same, plusunrecognized_keys ['properties']); the flat node accepted on both.0c673ccb8:pnpm exec vitest run packages/types/ packages/cli/ scripts/__tests__/:Test Files 510 passed | 2 skipped (512),Tests 13626 passed | 2 skipped (13628), VERDICT command-exit 0.pnpm exec vitest run packages/plugin-gantt/ examples/schema-catalog/:Test Files 130 passed | 1 skipped (131),Tests 2911 passed | 114 skipped (3025), VERDICT command-exit 0 (the skips are the zone-conditionalskipIfpins). The second run holds every test that reads a markdown file this PR changes outsidepackages/typesandscripts(markdown-test-inputs.mjsledger),readme-navigation-example.test.tsamong them.packages/typesandpackages/clithat nameAnyComponentSchema,StrictAnyComponentSchema,safeValidateSchema,ObjectQLPublicBlockComponentSchema,ObjectQLComponentSchema,ObjectGanttBlockSchema,nodeOracles,KNOWN_SCHEMA_TYPES,propsLevelOf,PUBLIC_BLOCKS,unmirroredAlias,collectArms,getPublicConfigs,ComponentPropsMap,validateSchemaorStrictAuthoringFace, or referencecheck-handler-key-read-sites,block-config-schema-parity,registry-inputs-spec-parity,strict-authoring-face,zod-mirror-parity,objectql.zod,index.zod,ObjectGanttSchema,object-ganttorplugin-gantt. Three chunks, atceead94adplus the two triage edits later committed byte-identical asc572b020c:78 passed / 1 failed (79)(the render-identity anti-vacuity row, then triaged),73 passed / 1 failed (74)(the catalog-plans pin, then triaged), and79 passedplus the two triaged files:Test Files 81 passed (81) / Tests 1610 passed, VERDICT 0. Later commits add the render pin, the docs and the changesets; their markdown readers are re-run in the final union above.pnpm --filter @object-ui/types build && pnpm --filter @object-ui/types type-check, VERDICT 0 (dist completeness: 1 package(s) complete (138 emitted files verified)); the b6 pin is intsconfig.test.json's--listFilesOnly. Afterpnpm --workspace-concurrency=2 --filter '@object-ui/plugin-gantt^...' --filter '@object-ui/example-schema-catalog^...' build(VERDICT 0):@object-ui/plugin-gantt type-checkand@object-ui/example-schema-catalog type-check, VERDICT 0 (the two plugin-gantt pins and the catalog render-identity pin are in their test programs).scripts/ablation-replace.mjs, two nested WRAP legs plus the driver's own EXIT/INT/TERM trap with an absolute path and a blob check): the flat arm restored, i.e.ObjectGanttBlockSchemaout of the public-block union (anchor x1 to x0, blobbc957ee9to8390b06a) andObjectGanttSchemaback intoObjectQLComponentSchema(anchor x1 to x0, blob toe5be71a8; on diskObjectGanttBlockSchema,x0 in the public union andObjectGanttSchema,x1 in the ObjectQL union). Over 13 test files (the two new pins, the census and triaged files, the catalog pins and the objectui#10859 ratchet):Tests 93 failed | 783 passed (876). Red: 78 b6 rows, 4 of 6939, 3 catalog validate rows, 2 of 9256, 2 of 10872, one each in 7363, b2 and 11070, and the render pin's validator row. Green: the census files whose subject is the export itself (zod-mirror-parity,imported-defaults-8317), the ratchet, the catalog-plans pin (a direct mount), every render row, and the 26 b6 rows that read the spec or the arm directly (the lit controls, the per-member page-component split, the row-by-reference row, the binding and channel refusals the flat arm shared, the spec-divergence row and the flat-mirror row). Direction red, as expected. Restored: blob == HEADbc957ee9,git diff HEADempty (both tool legs and the driver). Vitest aliases@object-ui/types/zodto source, so no build sat between the mutation and the run.z.strictObject({ objectName: z.string().optional() }).optional()madetsc -p tsconfig.test.jsonexit 2 with exactly one error,TS2344: Type 'false' does not satisfy the constraint 'true'on the bagEqualrow of the b6 pin. Restored, blob == HEAD,git diff HEADempty.find('task', …)with its own$filterand$orderbyand hands the chart one task per row, titled by itsganttblock; the two flat spellings a composer builds (theganttblock on the node, and the flattenedGanttConfigkeys) make the identical call and hand the chart identical tasks; a bag bound only throughdataSourcequeries the bound object; a bag on inline rows draws them with no host query; control: a bag naming another object queries that object and nevertask. The catalog render-identity pin draws the three bag entries exactly as its recorded pre-repair DOM.Gates (exit codes captured before any pipe)
check:control-bytes("OK (scanned 9809 tracked text file(s); skipped 85 binary)"; a self-scan over the 23 changed files gives 0 hits),check:new-line-citations("VERDICT new-cross-file-line-citations: 0 new citation(s)"),node scripts/check-changeset-presence.mjs("15 source file(s) of 2 released package(s) changed, and this change declares 2 changeset(s)"),changeset:check("No changeset declares amajorbump."),check:handler-key-reads("OK 140 arm(s), 212 registration(s) (138 keyed onto an arm), 56 reachable handler read(s), 56 judged"),check:spec-symbols,check:element-data-source-declaration("14 gate-consuming file(s) checked"),check:component-surface-parity,check:installed-pin-claims,check:test-path-roots,check:vi-mock-specifiers,check:vi-mock-inherit,check:vi-mock-override-shape,check:unreferenced-sources,check:esm-specifiers,type-check:coverage("43/43 packages compile their tests"),check:registry-bare-names,check:prompt-keys,check:pending-changeset-literals,census:changeset-polarity,check:skill-examples.check:doc-types,check:doc-fences,check:doc-example-ids,check:doc-example-readers,docs:check-links("Links are valid across 17 scan roots."),node scripts/markdown-test-inputs.mjs --audit("108 candidate test files, all adjudicated; 80 declared entries, all present."), and the whole rootscripts/__tests__/suite (in the union above). After thecheck-doc-snippet-types.mjs --build-filterclosure build (turbo "Tasks: 35 successful, 35 total"):check:doc-snippets("Semantic phase: 698 of 698 block(s) judged, 0 failed."),check:doc-examples,check:readme-exports, each exit 0.check:changeset-claims(report-only): five pending changesets describe what the validators say about anobject-ganttwritten flat (6475-gantt-block-face-declared,6939-objectql-record-source-refinement,9256-e3-residual-content-channels,11070-strict-face-read-keys,11117-datasource-objectname-waiver). They are not edited; this change's types changeset names how those readings happen in the bag now, so the release notes read together.node scripts/check-governed-queue-guard.mjs --testover the 23 paths: "NOT GOVERNED".pnpm exec eslint --no-inline-config --format jsonover the 15 changed.ts/.tsxfiles: 0 errors, 37 warnings, the same count file for file as the base blobs linted through--stdin(the new and the other touched files carry 0). Population: each touched package lints.;eslint.config.jssets no type-aware parser project, so no untouched file's verdict can move. The fullpnpm lintis CI's.Deviations
labelis not refused flat. The order asks for onealiasKeyRefusalper bag member.labelis a row member AND a node-level key of the spec's ownPageComponentSchema(its display label): measured, the spec's page component acceptslabelon anobject-ganttnode while it refuses every other row member written there. Refusing it would make objectui refuse a spec-valid document, solabelkeepsBaseSchema's member. The pin re-derives the split from the installed spec for every row member, so a spec that moves it turns the pin red.GanttConfigmembers anddependencyFieldare refused by name on the bag arm, beyond the row-key set: they were declared members of the flat mirror, and their bag home is the row'sganttblock (batch 5's precedent forlocationField/titleField). The key set is the row's ownganttmember, read off the crossed row.search/searchableFields(flat-mirror members, absent from the row) are left undeclared on the bag arm, as batch 4 left the row-absent members ofobject-form: unjudged by the tolerant face, refused by the strict one, refused by the row inside the bag. A list view writes them onto the node it composes, which never meets these faces.@object-ui/plugin-ganttpatch: the README, and two test files undersrc/, which the presence gate counts as published source.requireRecordSource's docblock said neitherobject-mapnorobject-gantthas aComponentPropsMaprow (both have had one since 17.5.0); the flat mirror'sganttmember comment and the TypeScript twin'sganttcomment said the mirror reachesvalidatethroughAnyComponentSchema; theObjectQLComponentSchemadocblock's opening sentence named two departed arms out of four.AGENTS.mdand the role file, the commits carry the model-free pair and this body the session-URL footer.Acceptance notes
markersas an array of unknown andnavigationas unknown, soproperties.markers: [{ date: 5 }]andproperties.navigation: { mode: 'nope' }parse, where the flat mirror refuses both (invalid_typeatmarkers.0.date,invalid_valueatnavigation.mode). The row's own contract, taken by reference; no producer writes either.skills/objectui/guides/page-builder.md"Gantt plugin example" authors a flatobject-ganttnode (objectNameandgantton the node), whichobjectui validaterefuses after this change, and its prose says the flat field keys may be written on the node.check:skill-examplesexits 0 on it (it does not runsafeValidateSchema). Per the answer's step 4 it goes through the governed path; batch 4 noted itsobject-formsibling on objectui#11183.bindon the node, which the spec's page component refuses (unrecognized_keys ['bind']) while objectui'sBaseSchemadeclares it. The flat node at base carried the same key; unchanged here.Written in session
https://claude.ai/code/session_011p7ikEivgXefNDaE5S5Uec(the dispatching seat's session; this dev ran as its subagent).Generated by Claude Code