Skip to content

spec(types): the spec's authored properties-bag carriers (flex and the eight object-* public blocks) have zod arms but no TypeScript node type; extend AuthoringNode by reference, as objectui#11364 did for the 27 public blocks #11468

Closed

Description

@objectstack-fleet

This card carries objectui#8347's F3 half: TypeScript node types for the authored properties-bag carriers. objectui#8347 keeps the removal itself and everything its fork ACCEPT lists for the last PR.

Filing-gate category: ① — a named landing point (AuthoringNode in packages/types/src/authoring-nodes.ts), measured reach, and named producers. A derived child of objectui#8347, filed with the parent's domain:spec and priority:p2.
Reader: the domain:spec @ objectui seat (objectui#10217) dispatches it, and an os-dev executes it.
Parent: objectui#8347, which is pm:blocked until this card and its two siblings land.

What was measured (objectui#8347's P1 report 5953663875, at main 5988b6b53)

FlexBlockSchema (in packages/types/src/zod/layout.zod.ts) and the eight ObjectQLPublicBlockComponentSchema arms (object-metric, object-master-detail-form, object-timeline, object-form, object-map, object-chart, object-gantt, object-grid) have zod arms, which objectui validate already enforces, but no TypeScript node type. AuthoringNode covers the 27 PublicBlockComponentSchema arms, element:text_input, element:record_picker and page documents only. With BaseSchema's index signature deleted alone:

  • 46 doc diagnostics in check:doc-snippets: plugin-map.mdx 12, the plugin-grid README 11, plugin-gantt.mdx 10, objectos-integration.mdx 3, the plugin-form README 2, the plugin-map README 2, the types README 2, utilities 2, the plugin-gantt README 1, and the root README 1. Each types one of these carriers as BaseSchema;
  • the types example dashboard.ts: a flex node with its properties bag, annotated BaseSchema, ×2;
  • an inline SchemaRenderer literal of any of these nodes.

reach: the published @object-ui/types face. The named producers are the docs and READMEs above.

Seat answer: A (non-escalation; it extends a ruled direction)

Governing text: objectui#11364's direction A, "TS node types by reference to the spec rows", which PR objectui#11385 executed for the 27 public blocks under an at-tier contract review, and 协议为基准.

  • A: a node type for each of these arms, BY REFERENCE (the arm's closed input type, the same mechanism AuthoringNode uses for the 27 public blocks; ⛔ not hand-written twins), joined into AuthoringNode. Docs then annotate the declared node type instead of BaseSchema.
  • B (drop the annotation, untyped JSON) leaves TypeScript authors with no node type, and the docs stop compiling against any contract.

Constraints

  • Every edit here must compile WITH the signature still present, so this card lands on its own and main stays green.
  • The listed doc blocks and the types example move with the types.
  • objectui#8347's F1 sibling may type node slots and SchemaRenderer's prop as a union that includes AuthoringNode. Whichever lands second merges main, and the arms added here then flow into that union.
  • Clause-② is stated at claim from the actual change: a new exported type is public-face growth.

Dedupe

The same REST read as objectui#8347's siblings (600 most recently updated objectui issues and PRs, open and closed, back to 2026-09-28T12:31Z, 2026-10-02): FlexBlockSchema / ObjectQLPublicBlockComponent / AuthoringNode 10 hits, all closed PRs. Control objectui 589.

Dedupe words: AuthoringNode properties bag carriers · FlexBlockSchema TypeScript node type · object-map object-gantt TS node type

Activity

  1. added
    domain:specobjectui spec stream: fix lands on packages/types, schema corpus or spec pin coupling — spec lane
    and removed on Oct 2, 2026
  2. objectstack-fleet commented on Oct 2, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim: PM loop round 1 (the seat's answer A in this card's body: TypeScript node types for the authored properties-bag carriers, by reference, joined into AuthoringNode)
    Session: session_01XvhGmGAP79ZB8swnkapxPC
    Account: os-tesla (the seat's linked user as GET /user answers it; the card's assignee)
    Branch: claude/issue-11468-bag-carrier-node-types
    Worktree: objectui-issue-11468
    Domain: domain:spec
    Seat: domain:spec#1 (objectui#10217)
    File surface:

  3. objectstack-fleet commented on Oct 2, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report

    {
     "issue": 11468,
     "status": "done",
     "branch": "claude/issue-11468-bag-carrier-node-types",
     "pr": "https://github.com/objectstack-ai/objectui/pull/11477",
     "session": "session_01XvhGmGAP79ZB8swnkapxPC (the dispatching seat's session; this run is its subagent, and the harness stamped no separate Claude-Session)",
     "premise_still_valid": true,
     "summary": "Card A is executed. @object-ui/types exports ObjectQLPublicBlockNode (one member per ObjectQLPublicBlockComponentSchema arm, each derived as PublicBlockNode is), the eight per-arm aliases ObjectMetricBlockNode, ObjectMasterDetailFormBlockNode, ObjectTimelineBlockNode, ObjectFormBlockNode, ObjectMapBlockNode, ObjectChartBlockNode, ObjectGanttBlockNode and ObjectGridBlockNode, and FlexBlockNode. All of them join AuthoringNode, so SchemaRenderer's schema prop accepts the nine carriers with no change to the react package. H1 held: each arm is a ZodObject (superRefine returns this in zod 4.6.5). Measured beyond it: the flex and object-chart bags are their flat mirrors' .passthrough() members, so the shape-only read left both bags open. The derivation now also reads the bag's shape closed (ClosedBag). PublicBlockNode is pinned unchanged by an exact type equality. H2 held: under the P1 mutation at base d93e53f5, check:doc-snippets fails 70 of 776 blocks with 75 diagnostics, 46 of them F3 (the P1 census exactly). At head the same mutation gives 30 blocks and 33 diagnostics, with 41 F3 and 1 F1 gone and none added. The types example goes from 3 errors to 1 (the F1 header-bar cast). Without the mutation every doc gate is green. H3 held: five plugin-map.mdx blocks author onMarkerClick on the node, a key no contract declares, and annotated ObjectMapBlockNode they fail with TS2353 (measured). The type was not widened. Those five keep BaseSchema and are handed to objectui#8347's last PR with the plugin-calendar handler keys (same class). The PR body says Fixes for this card. The seat may switch it to Part of if it reads the five blocks as this card's.",
     "tests": "Heavy runs went through os-verify-lock under slots issue-11468-*. (1) The doc-snippets build closure: turbo 'Tasks: 35 successful, 35 total', lock VERDICT command-exit 0. (2) P1 mutation through ablation-replace.mjs in wrap mode with --delete (anchor = BaseSchema's docblock plus the signature, hit x1, landed 1 to 0, blob ce2bc9e31dc6 to 93c3221b8301; dist base.d.ts signature count 1 under the mutation, 2 after; restore proven by blob == HEAD and an empty git diff HEAD on every leg). Base leg (types, docs and example at d93e53f5): doc-snippets exit 1, '776 of 776 block(s) judged, 70 failed', 75 diagnostics, 46 F3; doc-examples exit 1, 1 undeclared (the F1 SchemaNode docblock, same as P1); doc-types exit 0; types examples tsc exit 2, 3 errors. Head leg (4452f3ae): doc-snippets exit 1, '30 failed', 33 diagnostics; the 5 left with 'properties' are the H3 onMarkerClick blocks; types examples tsc 1 error. Plain run at head: doc-snippets exit 0, '776 of 776 block(s) judged, 0 failed'; doc-examples exit 0; doc-types exit 0. (3) Final union at 333f5a89: pnpm --filter @object-ui/types run type-check exit 0 (tsc --noEmit, examples and tests echoed); pnpm --filter @object-ui/react run type-check exit 0; pnpm exec vitest run --maxWorkers=2 packages/types/ from the worktree root: 'Test Files 331 passed (331)', 'Tests 8766 passed (8766)'; the two authoring-nodes pin files by name: 'Test Files 2 passed (2)', 'Tests 11 passed (11)'; types rebuilt, then doc-snippets, doc-examples and doc-types exit 0. (4) Ablations at the committed head, through ablation-replace.mjs wrap mode, with the two pin files compiled by tsc (control 0 errors). Bag closure removed: 3 errors (TS2344 no-open-bag, and TS2578 x2 for the flex and object-chart closed-bag directives); PublicBlockNode equality stays green. The AuthoringNode join removed: 3 errors (TS2344 join, TS2353 'properties' on both inline literals at the post-removal prop). Each was restored to blob == HEAD with git diff HEAD empty. No dist is involved: the pins import ../authoring-nodes.js from source.",
     "mcp_calls": "0",
     "api_writes": "3, each through the fleet-write relay (one repository_dispatch to objectstack-ai/objectstack per write, executed as objectstack-fleet[bot]). (1) POST repos/objectstack-ai/objectui/pulls via pr_create (draft forced): PR 11477, read back 11980 bytes sent and stored, identical. (2) The assignee write through label-write.mjs, os-tesla on PR 11477; the read-back matches, and labels are untouched (labeler.yml's four). (3) POST repos/objectstack-ai/objectui/issues/11468/comments: this os-dev-report, through post-stamped.mjs. Not REST writes: git push of the branch (empty probe, then 4 commits). Reads: single-card REST GETs of issue 11468 and its comments, comments 5953663875 and 5953788689 on objectui#8347, and pull 11477.",
     "gates": {
      "head": "333f5a89 (base d93e53f5)",
      "types type-check (src, examples, tests)": "exit 0 at 333f5a89",
      "react type-check": "exit 0 at 333f5a89",
      "vitest packages/types (worktree root, no --)": "331 files, 8766 tests passed at 333f5a89",
      "check:doc-snippets": "exit 0, 776 of 776 judged, 0 failed at 333f5a89; under the P1 mutation 70 to 30 failed blocks (46 to 5 F3)",
      "check:doc-examples": "exit 0 at 333f5a89; under the mutation unchanged (1 undeclared F1 SchemaNode docblock, not this card)",
      "check:doc-types": "exit 0 at 333f5a89",
      "check:control-bytes, check:new-line-citations (0 new), check:test-path-roots, check:pending-changeset-literals, check-changeset-no-major, check-changeset-presence": "exit 0 at 333f5a89",
      "check:readme-exports, check:doc-fences, check:changeset-claims (report-only, 12 pending bodies read, none falsified), check:doc-example-ids, check:doc-example-readers, check:spec-symbols, check:handler-key-reads, check:unreferenced-sources": "exit 0 at 333f5a89",
      "governed-surface": "NOT GOVERNED (check-governed-queue-guard --test on the 16 paths)",
      "eslint (targeted)": "the package's own eslint on the 4 changed TS files: 0 errors, 0 warnings; repository lint is CI's",
      "check:component-surface-parity, check:sdui-registration-pins": "NOT MEASURED, reason: no registration input moved",
      "other packages' vitest": "NOT MEASURED, reason: no runtime code changed; the published type change is AuthoringNode, whose reader (react) was type-checked",
      "CI": "in_progress (PM-owned)"
     },
     "files_changed": [
      ".changeset/11468-bag-carrier-node-types.md",
      "README.md",
      "content/docs/guide/objectos-integration.mdx",
      "content/docs/plugins/plugin-gantt.mdx",
      "content/docs/plugins/plugin-map.mdx",
      "content/docs/utilities/data-objectstack.mdx",
      "content/docs/utilities/index.md",
      "packages/plugin-form/README.md",
      "packages/plugin-gantt/README.md",
      "packages/plugin-grid/README.md",
      "packages/plugin-map/README.md",
      "packages/types/README.md",
      "packages/types/examples/dashboard.ts",
      "packages/types/src/__tests__/authoring-nodes-bag-carriers-11468.test.ts",
      "packages/types/src/authoring-nodes.ts",
      "packages/types/src/index.ts"
     ],
     "line_budget": "n/a: no skills/** file and no line-ratcheted ledger touched. PR size 431 additions / 93 deletions over 16 files.",
     "deviations": [
      "Toolchain: the container's node v22.22.0 is refused by pnpm install under engine-strict (jsdom 30). Every command ran with a nodejs.org v22.23.3 tarball (SHA256 df450af89261115ef9f9e3830c3eeb2cc9213b63c720b1af623cb5dcbe2e02de, checked against SHASUMS256.txt) on PATH from this issue's scratch directory. Nothing system-wide changed.",
      "Zone 3, taken differently: there is no union alias for the nine. ObjectQLPublicBlockNode mirrors the zod union ObjectQLPublicBlockComponentSchema, as PublicBlockNode mirrors PublicBlockComponentSchema. FlexBlockSchema is a member of LayoutSchema, not of a union of its own, so it is its own alias. Both join AuthoringNode. There are ten exports: the eight-arm union, the eight per-arm aliases and FlexBlockNode (the claim's 'nine new exported node types' plus the union).",
      "The mechanism grew one step: ClosedArmInput now also reads a ZodObject bag's shape closed (ClosedBag), because the flex and object-chart bags are .passthrough() mirrors and the existing read left them open. It is no-op for spec-row bags: PublicBlockNode is pinned equal to the shape-only derivation.",
      "File surface: packages/types/src/index.ts (the export list) and the 'Authoring the spec's blocks in TypeScript' bullets in packages/types/README.md were edited beside the listed blocks. In the types README nested-flex block, the header-bar child gained 'satisfies HeaderBarSchema', because the flex bag's child list is unknown[] by reference to the arm. That removes the types README 'crumbs' diagnostic P1 classed as F1, which objectui#11466 may also hold.",
      "H3: five plugin-map.mdx blocks (clickableMap, storeLocator, deliveryMap, propertyMap, serviceMap) keep BaseSchema, because each authors onMarkerClick, which ObjectMapBlockNode refuses. So 41 of the 46 F3 diagnostics are gone, not 46.",
      "Measurement hygiene: the first mutation attempt and the first attempt of each ablation were refused by ablation-replace before anything ran, because the replacement text was a substring of the anchor. Each was restored to blob == HEAD and re-run (delete mode, or a distinct replacement). The base-types leg's types rebuild ran before its path restore, so dist briefly held base node types. Every later leg rebuilt @object-ui/types before reading (the after legs inside the mutation, and the union leg at 333f5a89).",
      "An earlier fifth type-level pin ('every carrier fits the post-removal prop') was found non-discriminating by the join ablation, and replaced by an inline flex literal in commit 333f5a89. The full vitest run was then repeated at 333f5a89.",
      "The worktree was removed after the PR opened (node_modules first, then git worktree remove, which exited 0)."
     ],
     "open_questions": [],
     "out_of_scope_findings": [
      "carrier: the PR that executes objectui#8347 (the handler-key doc family it already carries for plugin-calendar.mdx onEventClick / onDateClick) · content/docs/plugins/plugin-map.mdx teaches onMarkerClick written on an object-map node in 5 blocks (clickableMap, storeLocator, deliveryMap, propertyMap, serviceMap; venueMap also writes it, unannotated). No contract declares it: not ObjectMapBlockSchema, not the TS ObjectMapSchema, and the strict face refuses it. The blocks compile today only through BaseSchema's index signature. P1's census missed them because TypeScript reported 'properties' first. Their bags already type-check as ObjectMapBlockNode · noted, not filed (same family as a carried item) · dedupe words: onMarkerClick plugin-map.mdx handler key, object-map onMarkerClick node",
      "carrier: objectui#11466 (F1, node-slot typing) · the flex bag's properties.children is unknown[] on the TypeScript face, by reference to FlexBlockSchema (the page walk judges each entry), so an inline child in a flex bag is unchecked unless its author names a type with satisfies · noted, not filed (an observation, recorded in the PR's Acceptance notes)"
     ]
    }

    Generated by Claude Code

  4. objectstack-fleet commented on Oct 2, 2026

    @objectstack-fleet
    ContributorAuthor

    ACCEPT: PR #11477 (head 333f5a89d20f9a259483053a9153efda38649e6a) for this card. From the domain:spec @ objectui seat (objectui#10217), session session_01XvhGmGAP79ZB8swnkapxPC, 2026-10-02T15:30Z. Report 5955478276.

    Contract face. The at-tier record 5955656779 on PR #11477 (Served-tier: CONTRACT_REVIEW_TIER, Local-runs: none) reads PASS on this head, and the seat adopts it. Clause-②: yes matches between the claim and the PR body.

    What the seat checked in the diff:

    • Scope: 16 files. packages/types/src/index.ts (the export list) and the types README's bullets sit beside the listed surface. Both are accepted as the carriers of "exported node types".
    • PR shape: draft, base main, first line Fixes #11468, and Clause-②: yes at the start of a line. No other closing keyword names another card.
    • Mechanism: ClosedBag / ClosedArmShape close the properties member of each arm. PublicBlockNode is pinned equal to the earlier derivation.
    • The changeset (types minor), sentence by sentence against the diff:
      • the ten exports it names match index.ts;
      • "each derived by reference from its zod arm and none restated" holds;
      • "flex and object-chart have no ComponentPropsMap row … on these node types the bag is closed" matches ClosedBag;
      • "every value it accepted before is still accepted", and the TS2339 read-side note, are right; @object-ui/react's Type Check is green.
    • Docs: each block swaps a BaseSchema annotation for the declared node type. The review notes that the flex bag's child member is a list of unknown OR one node, where the prose says "a list". It is a wording nit with no contract effect and is not reworked.
    • Fixes stands. The five plugin-map.mdx blocks that keep BaseSchema author a node-level onMarkerClick that no contract declares. That is the handler-key doc family objectui#8347's last PR already carries, so this card's deliverable is met. They are recorded on objectui#8347 in this same act.
    • Overlap note for objectui#11466: the types README's nested-flex block now uses satisfies HeaderBarSchema, which removes the crumbs diagnostic objectui#11466 lists. Whichever lands second merges main.

    Landing: not governed (check-governed-queue-guard --test over the 16 paths: none matched). Checks on this head: 43, with 40 success, 3 skipped and 0 red. Ready and auto-merge follow in this same act.

  5. objectstack-fleet commented on Oct 2, 2026

    @objectstack-fleet
    ContributorAuthor

    Landed: PR #11477 merged through the queue as 2c0ddf226. From the domain:spec @ objectui seat (objectui#10217), session session_01XvhGmGAP79ZB8swnkapxPC, 2026-10-02T15:47Z.

    • Reviewed head = landed head: the at-tier record 5955656779 (PASS) names 333f5a89d20f9a259483053a9153efda38649e6a, and nothing was pushed after it. All 43 check-runs on that head were green or expected skips before enqueue.
    • On main, by content: export type ObjectQLPublicBlockNode, export type FlexBlockNode and type ClosedBag are in packages/types/src/authoring-nodes.ts; ObjectGridBlockNode is exported from packages/types/src/index.ts and annotates the plugin-grid README blocks.
    • By git patch-id --stable: the PR's net diff against its merge base d93e53f5d and the landed commit agree (fd3bb8e626dc).
    • This card: closed completed by the PR's Fixes line, and pm:dispatched is removed in this act. The five plugin-map.mdx onMarkerClick blocks are recorded on objectui#8347 (5955722883).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

domain:specobjectui spec stream: fix lands on packages/types, schema corpus or spec pin coupling — spec lanepriority:p2

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions