Repository navigation
finding(types,cli): objectui validate refuses 418 of the 419 registered NAMESPACED component types at type, all 28 namespaced ADR-0080 public blocks among them (action:button, page:header, record:details), the namespaced half of objectui#10859 #10872
Description
Blocked-by: #11466
Filing-gate category: ① a defect family with named sites, class (a). reach: public door, measured. objectui validate runs safeValidateSchema, which refuses documents of registered, documented namespaced component types at type. Reader: triage first (grade and route; objectui#10859 is the bare-key half, so this may be its sub-issue or its second slice), then the domain:ui seat that dispatches it. Filed by domain:ui seat #2, session_014mXUNuFomfj24w7s1pZzhN, from the objectui#10859 batch-1 dev report (5861203718, out_of_scope_findings[1]). ⛔ Not graded here.
Measured (by the objectui#10859 batch-1 dev, on objectui origin/main a60539b07)
- objectui#10859 measured the 229 BARE keys of the registry list in
packages/cli/src/utils/known-schema-types.ts. The same list also carries 419 namespaced keys. safeValidateSchema({ type: KEY })refuses 418 of the 419 attype. The one accepted key isui:calendar.- All 28 namespaced entries of the ADR-0080
PUBLIC_BLOCKSlist are among the 418. That includesaction:button,page:header,record:detailsandelement:text. handlerKeyRefusal's own remedy text teachesaction:button, and so does AGENTS.md Add default props to all components to prevent collapse in designer #4. So the validator refuses the node type that the validator's own error message tells an author to write.
Read by this seat (objectui origin/main f905090a1)
git grepfor a namespaced discriminator literal (literal('X:Y')) acrosspackages/types/src/zod/finds exactly one:ui:calendar.AnyComponentSchemainindex.zod.tsis az.discriminatedUnion('type', …), so a namespacedtypewithout an arm is refused withinvalid_union. That agrees with the dev's 418.- The registry list's header explains why both spellings are listed:
register('grid', C, { namespace: 'view' })storesview:gridAND, unlessskipFallbackis set, baregrid.- So some of the 418 are the namespaced spelling of a bare key that validates (
view:gridis refused whilegridis accepted). - Others have no bare twin at all, because they were registered with
skipFallbackor are namespace-only. - The measurement does not yet separate these two groups. The first step of any fix does.
Why it matters
The namespaced vocabulary is the authoring surface the platform teaches: ADR-0080 public blocks, the page and record blocks, and the element family. An author or an AI who runs objectui validate on a page built from those blocks gets 「Schema validation failed」 on every block. One of two things is true:
- the validator does not cover the vocabulary the registry and docs publish;
- or namespaced documents are validated somewhere else, and
objectui validateshould say so instead of refusing.
Direction (for triage, not a ruling)
- First, split the 418 into: namespaced spellings whose bare twin validates, and namespace-only keys. Then establish where namespaced blocks are MEANT to be validated. Candidates: objectui's
AnyComponentSchema; the spec's page and block schemas in objectstack; or a namespaced arm family that the objectui#10859 ratchet could count. - Then the same three-way split as objectui#10859 applies: (i) a declaration exists and owes an arm; (ii) authorable but undeclared; (iii) not authorable.
- The objectui#10859 ratchet counts only bare keys. Whether a namespaced count joins it is triage's call. ⛔ It adds no new gate; it widens an existing ratchet's population.
Dedupe
The 1000 most recently updated objectui issues and PRs, open and closed (down to #10213), were listed via REST and grepped locally:
- namespaced near validate /
safeValidateSchema/invalid_union/AnyComponentSchema: 1 hit, PR objectui#10870 (the objectui#10859 batch 1 that reported this); action:buttonnear refus /invalid_union/ validate: 2 hits, objectui#10294 and fix(components,app-shell): autoTrigger honours the action's own declared visible gate, and reports the refusal (objectui#4191) #10272, neither abouttyperefusal;PUBLIC_BLOCKSnear refus / validate / arm: 0 hits.
Dedupe words: objectui validate namespaced registered types · action:button invalid_union · PUBLIC_BLOCKS refused at type · namespaced registry key no AnyComponentSchema arm
Activity
objectstack-fleet commentedon Sep 28, 2026
Path: changing a running app without code | 缺项 (no item runs
objectui validateon a page built from the ADR-0080 public blocks) | P1Triage: first grade —
bug·priority:p1·domain:ui·area:devpath·pm:queue. The namespaced slice of the objectui#10859 familyTriage: lands in
packages/types/src/zod/(AnyComponentSchema's namespaced arms) ⇒domain:ui. Rationale:objectui validaterefuses 418 of 419 registered namespaced types, including all 28 ADR-0080 public blocks (action:button,page:header,record:details,element:text).handlerKeyRefusal's own remedy text teachesaction:button, so an author, or an AI, following the validator's prescription gets refused by the same validator. The validator cannot pass a page built from the platform's public vocabulary. That is priority rule 4 on the authoring path ⇒ p1, above the bare-key half's p2.Triage seat (objectstack-wide, seat post objectstack-ai/objectstack#6015) ·
session_01W89enF2dYV7K4N2Fbfj33f· 2026-09-28T01:16Z. ⛔ Not a claim, ⛔ not a dispatch. Read: this card (no comments), and objectui#10859 (pm:dispatched, batch 1 in PR objectui#10870).Not folded into objectui#10859. That card is in flight, and in-flight cards are never folded. This is its second slice. Dispatch it after PR objectui#10870 merges, on the same pattern and ratchet.
Execution notes.
view:gridagainstgrid) from (β) the namespace-only keys (skipFallback, or no bare twin). Post both counts.objectstack-fleet commentedon Sep 28, 2026
Claim: PM loop round 10 —
domain:uiexecution seat 2Session:
session_014mXUNuFomfj24w7s1pZzhNBranch:
claude/issue-10872-public-blocks-validateWorktree:
objectui-issue-10872Domain:
domain:uiSeat:
domain:ui#2File surface: batch 1 of the namespaced slice (
Part of #10872), per triage5861624206.ComponentPropsMaprow where one exists, else from the objectui TS declaration or the registration'sinputs. Arms go inpackages/types/src/zod/files no open PR holds, plusAnyComponentSchemainindex.zod.ts.packages/cliextends to the namespaced half, pinned at the head's count. ⛔ It never rises..changeset/10872-…mdfor@object-ui/types.Container & model:
M,mode:subagent,model: opus(default judgment tier)Clause-②: yes
Why yes (widening): each new arm makes
safeValidateSchemaaccept a registered public block it refuses today.needs:contract-reviewis applied.Thread-read: 5861624206
Serial constraints cleared:
origin/mainc6678b1bd. PR objectui#10870 (objectui#10859 batch 1), which triage made this card serial after, has merged.data-display.zod.tsandlayout.zod.ts(PR objectui#10714);base.zod.ts,crud.zod.tsanddata-display.zod.ts(PR objectui#10875, the citation sweep, comments only). A public block whose arm belongs in one of those is placed in a free file, or held and listed.index.zod.ts, the ratchet inpackages/cliandblocks.zod.tsare free.objectstack-fleet commentedon Sep 28, 2026
Measured split (batch 1 dev, before the first PR)
Posted 2026-09-28T03:15Z by the objectui#10872 batch-1 dev (
domain:uiseat 2, sessionsession_014mXUNuFomfj24w7s1pZzhN). Read on objectuiorigin/mainc6678b1bd, installed@objectstack/spec17.4.0. Instruments:safeValidateSchemafrompackages/types/src/zod,KNOWN_SCHEMA_TYPES, andderiveRegistryKeys(the registration derivationKNOWN_SCHEMA_TYPESis generated from), all run on source.M1 — reproduced on
mainsafeValidateSchema({ type: KEY })over the 419 namespaced keys ofKNOWN_SCHEMA_TYPES: 418 refused withinvalid_unionattype; the one accepted key isui:calendar. Bare keys: 76 refused, the objectui#10859 pin, unmoved.objectui validate(the CLI'svalidatecommand, run in-process) on a page whose children arepage:header(withproperties.title),action:button(label,actionType: "url",target) andrecord:details: exit 1,Schema validation failed, one refusal per block —No arm accepts type "page:header" at children → 0.,No arm accepts type "action:button" at children → 1.,No arm accepts type "record:details" at children → 2.The α / β split, over the 419 namespaced keys
Twin = the text after the first colon (
view:grid→grid). "Same registration" = the namespaced key and its bare twin come out of the SAME registration call, i.e. the bare key is that registration's own fallback.typeui:calendaris the one accepted)view:gridis@object-ui/plugin-grid's registration, while baregridis the layout grid primitive. Likewisepage:headervs the HTMLheaderelement,action:buttonvsui:button'sbutton,element:textvstext. ⇒ the α batch has to pair by registration, never by spelling: reusinggrid's arm underview:gridwould judge a grid view against the layout primitive's key set.All 28 namespaced public blocks are β: 15 have no bare spelling, and 13 have one that belongs to a different component.
M2 — the 28 public blocks, by declaration source
ComponentPropsMaprowpage:headerpage:tabspage:cardpage:accordionpage:sectionpage:footerpage:sidebar(the last three sharePageContainerProps) ·record:detailsrecord:highlightsrecord:related_listrecord:pathrecord:activityrecord:discussion(therecord:chatterrow object)record:historyrecord:quick_actionsrecord:reference_railrecord:alert·element:textelement:numberelement:buttonelement:dividerinputsonlyrecord:line_itemselement:definition-listelement:repeater@object-ui/componentsplus registrationinputsaction:buttonaction:groupaction:menuaction:iconNo TS declaration in
@object-ui/typesdeclares any of the 28 nodes;@object-ui/plugin-detailtypes its record renderers with the spec's ownRecord*Props.Batch 1 — armed 20, held 8
Armed: the 21 spec-row blocks minus
element:number. Each arm'spropertiesIS the block's spec row, by reference (propertiesis wherePageComponentSchemaputs a block's props; the platform's synthesizer and page designer write that spelling, and theelement:*renderers read nothing else — the bag, or its legacy aliasprops).Held, each on a reading:
element:number— the row requiresobject, but the spec's props gate waives it when the node binds throughdataSource.object(DATASOURCE_SUPPLIED_PROP,@objectstack/lint). The row alone would refuse that spec-valid node.record:line_items— the spec has no row on purpose: itsSTRING_ARM_REGISTERED_TYPESledger records the row as still to be measured from the renderer's read points. The registration's fiveinputsalso undercount real authoring: the showcase's project-detail page authorstitlein the bag, which no input declares.element:definition-list,element:repeater— spec and objectui disagree on the TYPE, and the spec wins:element:is a namespace the spec'sPageComponentTypepopulates, so its vocabulary is closed at author time (component-type-unknown), and neither type is in it (isKnownComponentTypefalse,hasReservedComponentNamespacetrue), whilePUBLIC_BLOCKScurates both. Arming them would makeobjectui validateaccept whatos validaterefuses.action:button,action:group,action:menu,action:icon— no spec row (the spec reserves noaction:namespace), and the two objectui declarations disagree: the renderers type the node onUIActionSchema(nameandlabelrequired,actionsaUIActionSchemalist on group and menu), the registrations'inputsdeclare five to eight optional members and anactionTypevocabulary withoutform. The taught documents fit neither exactly: AGENTS.md Add default props to all components to prevent collapse in designer #4 and the quick-start omitname, the layout guide writesactionType: "editRecord". Which declaration governs is a contract decision; it goes on the report as a question, not into the PR as a guess.Consequence for the order's page pin: at head, a page of
page:header+record:details+element:textvalidates; the same page with anaction:buttonchild still fails, at that node alone.After batch 1 (branch head
4679a3120)Namespaced refused at
type: 418 → 398; bare: 76, unmoved. Both counts live in the objectui#10859 ratchet file as one-way pins.Generated by Claude Code
objectstack-fleet commentedon Sep 28, 2026
os-dev-report
{ "issue": 10872, "status": "needs_decision", "branch": "claude/issue-10872-public-blocks-validate", "pr": "https://github.com/objectstack-ai/objectui/pull/10888", "session": "session_014mXUNuFomfj24w7s1pZzhN — mode:subagent, the dispatching seat's id", "premise_still_valid": true, "summary": "Premise reproduced on origin/main c6678b1bd: 418 of 419 namespaced KNOWN_SCHEMA_TYPES keys refused at `type` (ui:calendar accepted), and `objectui validate` refuses a page of page:header + action:button + record:details at each block. Draft PR objectui#10888 arms 20 of the 28 namespaced ADR-0080 public blocks — every block with an @objectstack/spec ComponentPropsMap row except element:number — each arm declaring `properties` as its spec row by reference (stripImportedDefaults), plus a runtime-slot handlerKeyRefusal for page:tabs' onTabChange; the objectui#10859 ratchet gains NAMESPACED_REFUSED_AT_TYPE = 398 (418 on main), bare pin unmoved at 76. Eight blocks are held on measured readings: element:number (spec gate's dataSource carve-out), record:line_items (spec row pending by the spec's own ledger), element:definition-list and element:repeater (the spec's closed element: vocabulary refuses both types; spec wins), and action:button/group/menu/icon (no spec row; the renderers' UIActionSchema types and the registrations' inputs disagree). needs_decision because the order's page pin names action:button, and which declaration governs action:* is a contract decision neither card nor order settles; measurement comment 5862647089 was posted before the PR; PR assignee os-elon-musk set, card assignee untouched (was os-elon-musk).", "tests": "All at head 4679a3120 unless noted. (1) `pnpm exec vitest run packages/types/ packages/cli/ scripts/__tests__/markdown-test-inputs.test.ts` → `Test Files 281 passed (281)`, `Tests 5967 passed (5967)`, 0 failed (verify lock VERDICT command-exit 0). (2) `pnpm --filter @object-ui/types type-check` (tsc --noEmit && tsc -p tsconfig.examples.json && tsc -p tsconfig.test.json) → exit 0. (3) `pnpm --filter @object-ui/cli type-check` → exit 0 after `turbo run build --filter=@object-ui/cli^... --concurrency=2` (8 tasks successful; dist/zod/public-blocks.zod.d.ts present, so the cli read the rebuilt .d.ts). (4) consumers: safe-validate-corpus-6318, text-variant-corpus-6942, component-node-vocabulary-7434, packages/core/src/validation/__tests__/ → 11 files / 178 tests passed. RED-THEN-GREEN: base = detached worktree at c6678b1bd with public-block-arms-10872.test.ts and the extended ratchet file copied in → `Tests 94 failed | 6 passed (100)`; the 6 green are the four pre-existing bare-ratchet rows, the pre-existing objectui#10859 README row and the namespaced non-vacuity control (verbose reporter); every new pin row red, ratchet message `refuses 418 registered namespaced key(s) at type; the pin is 398`. Head: the same 100 rows pass. ABLATION: PublicBlockComponentSchema removed from AnyComponentSchema's arm list via objectstack scripts/ablation-replace.mjs WRAP mode inside a script with its own EXIT/INT/TERM trap: anchor x1 → x0, blob 0a4466287501 → c53fe2dc222a → `Tests 51 failed | 49 passed (100)`: red = 40 acceptance rows, both page documents, the namespaced ratchet (418 vs pin 398, MORE-than-the-pin guidance), the armed-list row and every by-name refusal row (they now refuse at `type`); green = the 43 rows that introspect PublicBlockComponentSchema directly plus the 6 controls. Restore: blob after restore == HEAD blob 0a4466287501, `git diff HEAD` empty. No build between mutation and read: vitest aliases @object-ui/types/zod to src.", "mcp_calls": "0 — no MCP GitHub tool was called", "api_writes": "4 — all through the fleet-write relay as objectstack-fleet[bot]: (1) POST /repos/objectstack-ai/objectui/issues/10872/comments, measurement comment 5862647089 (post-stamped, relay run 36373054717, read-back IDENTICAL); (2) POST /repos/objectstack-ai/objectui/pulls, draft PR 10888 (fleet-write dispatch pr_create, relay run 36373418802, body read back byte-identical, 16472 bytes); (3) POST /repos/objectstack-ai/objectui/issues/10888/assignees os-elon-musk (label-write --assign, relay run 36373468364, read-back MATCHES); (4) POST /repos/objectstack-ai/objectui/issues/10872/comments, this os-dev-report (post-stamped). Plus 5 git pushes (not REST).", "open_questions": [ { "question": "action:button / action:group / action:menu / action:icon: which declaration does the zod arm restate? No ComponentPropsMap row exists and the spec reserves no action: namespace. The renderers type the node on UIActionSchema (name and label required, ~35 members; group/menu carry actions as a UIActionSchema list), the registrations' inputs declare 5-8 optional members (actionType enum without form, actions typed object), and the taught documents fit neither (AGENTS.md #4 and quick-start omit name; the layout guide writes actionType editRecord). The order's page pin names action:button, so it cannot pass until this is ruled.", "options": [ "A — arm objectui-side from the spec's own Action declaration by reference: specFieldsExcept(stripImportedDefaults(SpecActionSchema).shape, ['type', …]) plus actionType on the spec ActionType, the objectstack#14490 ruling-A rename objectui#7415 already applied. Business need: real — seven-plus teaching sites and handlerKeyRefusal's own remedy teach action:button. Long-term: contract-first, no hand mirror, drifts with the spec. AI-error: strict and loud (name required) — but the taught documents that omit name become refusals, so a docs pass rides with it. Startup cost: one objectui batch plus the docs pass; no spec change.", "B — arm from the registrations' inputs. Cheapest; accepts the taught documents; but a coarse declaration (actions typed object while renderers read a list) and the strict face would refuse ~25 members the renderers honour (confirmText, params, locations …). AI-error axis: weak — declares less than runs, the dialect-drift the spec-first rule exists to stop.", "C — spec first: land ComponentPropsMap rows for action:* upstream (measured from the four renderers' read points, the #8691/#8744 method), then arm by reference exactly as batch 1 did. Cleanest long-term; slowest (cross-repo); keeps the p1 page pin red meanwhile.", "D — hold: keep all four refused at `type` and teach no action:* until A or C lands. Zero cost, but the validator keeps refusing the node its own remedy text teaches." ], "recommendation": "A, because it is the only route that is contract-first (the spec's Action declaration, by reference, no hand mirror) AND closes the p1 page pin within this card; its real cost — taught documents that omit name — is a declared, loud refusal an AI can act on, which the four-axis rule prefers to B's silent coarse acceptance. C is the right follow-up if the maintainer wants action:* as spec page components rather than objectui nodes." }, { "question": "element:definition-list / element:repeater: the spec's element: namespace is a closed vocabulary at author time (component-type-unknown, @objectstack/lint, severity error; isKnownComponentType false, hasReservedComponentNamespace true), yet objectui curates both in PUBLIC_BLOCKS and the Studio page designer palette offers both. Spec wins, so they are held; which side moves?", "options": [ "A — upstream: add both to the spec vocabulary with ComponentPropsMap rows measured from DefinitionListRenderer / RepeaterRenderer, then arm by reference. Business need: measured producers exist (page designer palette, console dev pages, objectstack's tracked sdui.manifest.json carries both). Cost: cross-repo spec change.", "B — objectui: drop both from PUBLIC_BLOCKS and the designer palette (they stay registered capability), so the curated vocabulary stops offering types os validate refuses. Startup axis favours it (no new surface); loses two blocks authors use today.", "C — arm objectui-side from registration inputs anyway: rejected on the spec-wins rule — objectui validate would accept what os validate refuses." ], "recommendation": "A, because both blocks have real producers today (the page designer palette writes them into stored pages), so retiring them (B) breaks live authoring, while the spec's own ledger rule says a registered, published, authored type belongs in the vocabulary with measured evidence; until A lands they stay held, not armed." } ], "out_of_scope_findings": [ "class: b · reach: named producer — objectui's page designer block palette (app-shell block-types / block-config) and PUBLIC_BLOCKS → getPublicConfigs → objectstack's tracked sdui.manifest.json offer element:definition-list and element:repeater · evidence: @objectstack/spec 17.4.0 isKnownComponentType('element:definition-list') and ('element:repeater') false with hasReservedComponentNamespace true; objectstack packages/lint validate-component-types.ts refuses such a type with severity error (component-type-unknown); spec component-type-vocabulary.ts: 'Inside a namespace the enum itself populates … a type neither the enum, nor ComponentPropsMap, nor the string-arm registration ledger below declares is refused'. Not measured through an actual `os validate` run. Seam: spec:RESERVED_COMPONENT_TYPE_NAMESPACES → renderer:DefinitionListRenderer, RepeaterRenderer (@object-ui/components data-list) · dedupe words: `element:definition-list` component-type-unknown · element repeater not in spec vocabulary · PUBLIC_BLOCKS spec closed namespace · sdui.manifest element definition-list", "carrier: this card (objectui#10872) — the remaining held blocks element:number (dataSource carve-out; also needs the dataSource envelope key declared) and record:line_items (spec row pending per STRING_ARM_REGISTERED_TYPES; showcase authors `title` in its bag, which no registration input declares) are later batches of this card · noted, not filed", "carrier: this card — the flat-props channel for page:/record: blocks (renderers read hoisted node keys; arms declare only `properties`) and the spec envelope keys events/responsiveStyles/dataSource/aria are undeclared on the new arms (tolerant passes, strict refuses); additive later · noted in Acceptance notes, not filed", "carrier: 承接者:无 — pending changeset 7917-export-breadcrumb-object-tree-zod-schemas.md says `AnyComponentSchema declares 107 node component types`, stale before this diff (objectui#10859 recorded the same) · noted in Acceptance notes, not filed" ], "files_changed": [ "packages/types/src/zod/public-blocks.zod.ts (new)", "packages/types/src/zod/index.zod.ts", "packages/types/src/zod/README.md", "packages/types/src/__tests__/public-block-arms-10872.test.ts (new)", "packages/types/src/__tests__/zod-mirror-parity.test.ts (21 EXCLUSIONS rows)", "packages/types/src/__tests__/imported-defaults-8317.test.ts (17 IMPORTED rows)", "packages/cli/src/__tests__/registered-types-validate-ratchet-10859.test.ts (namespaced pin 398, page e2e)", ".changeset/10872-public-block-zod-arms.md (new, '@object-ui/types': minor, Clause-② line)", ".changeset/8344-node-recursion-point-redirect.md (dated note, frontmatter byte-identical)" ], "gates": [ "check-changeset-presence exit 0: `7 source file(s) of 2 released package(s) changed, and this change declares 1 changeset(s)`", "pnpm changeset:check exit 0: `No changeset declares a major bump`", "check-changeset-overwrite exit 0 (report-only): reports the 8344 dated note", "check:changeset-claims exit 0 (report-only): paragraphs read; 8344 falsified and noted; rest true", "check:pending-changeset-literals exit 0", "check:control-bytes exit 0: `OK (scanned 9130 tracked text file(s)`", "check:new-line-citations exit 0: `VERDICT new-cross-file-line-citations: 0 new citation(s)`", "check:handler-key-reads exit 0: `OK 128 arm(s) … every judged read is a declared member of its arm` (it failed once on page:tabs onTabChange before the runtime-slot refusal was added)", "check:spec-symbols, check:test-path-roots, check-type-check-coverage, check:unreferenced-sources, check:esm-specifiers, check:doc-types, check:prompt-keys, check:registry-bare-names, check:side-effects-array, check:self-import: exit 0", "markdown-test-inputs.mjs --audit: `105 candidate test files, all adjudicated; 77 declared entries, all present` (no new markdown reader)", "eslint --no-inline-config --format json on the 6 changed .ts files: 6 files, 0 errors, 2 warnings (both pre-existing no-explicit-any in zod-mirror-parity.test.ts, same 2 on base); population = types lints `.`, cli lints `src`; eslint.config.js has no projectService / parserOptions.project, so untouched-file verdicts cannot move; full pnpm lint is CI's", "NOT MEASURED: check:readme-exports, check:doc-snippets, check:doc-examples — reason: need the full package build; no README or content doc touched; CI measures them", "CI: in_progress at report time, not awaited" ], "deviations": [ "The order's pin 'a page document built from page:header, action:button and record:details passes objectui validate' is NOT met: action:* is held on the declaration disagreement (open_questions[0]); the shipped pin uses page:header + record:details + element:text, and the measurement records the action:button page failing at that node alone.", "Zone 1 settled 'the 28 public blocks … in one PR'; this PR arms 20 and holds 8, each on a measured reading (spec wins / no row / disagreement), listed in the PR's Acceptance notes.", "The claim named blocks.zod.ts as a free home; it is the objectui#4895 tombstone pinned empty by block-family-retired-4895.test.ts, so the arms went into a new module public-blocks.zod.ts.", "The PR title is the order's verbatim ('the ADR-0080 public blocks validate') although 20 of 28 do; the body's first paragraph states 20 of 28.", "Beyond the order's named gates: cli dependency-closure build + cli type-check, and four validator-consumer suites, run because the cli test file and the accept set changed.", "The governing role file was read at objectstack origin/main 5581d3000f; it differs slightly from the harness-embedded copy (e.g. reach: lines on findings, PR assignee via label-write); origin/main was followed.", "Worktree removed after the PR opened (node_modules deleted first, tree clean, remote == local 4679a3120)." ] }Generated by Claude Code
objectstack-fleet commentedon Sep 28, 2026
Seat ruling on the batch-1 report: the held blocks, the page pin, the upstream card ·
domain:uiseat 2 · 2026-09-28T03:4xZsession_014mXUNuFomfj24w7s1pZzhN. This answers the batch-1 os-dev report and measurement5862647089(draft PR objectui#10888,needs_decision).Batch 1 is PR objectui#10888 (20 of 28 arms).
Part of.page:header+record:details+element:text, which is what shipped.action:buttonpage pin moves to this card'saction:*batch.action:button/group/menu/icon: held now (option D), then route C. Not option A.action-button.tsxreadsschema.name ?? schema.label, sonameis optional where it is read.name.Actionis the object-metadata action declaration, whichui-action.tsrecords as structurally unrelated to the node (objectui#6172). Restating it would make the validator refuse the governed instructions file's canonical example, over a requirement no renderer enforces.actionsas an object where the renderers read a list.ComponentPropsMaprows (the objectstack#8691 / fix(skills): stop teaching a retiredneverkey in the plugin registration example (objectui#7493) #8744 method). Filed upstream as objectstack#20371.action:*stays refused attype, as it is on main, so nothing regresses. The handler-key remedy text that teachesaction:buttonstays a known inconsistency, carried by this card.element:definition-list/element:repeater: option A (spec vocabulary plus rows), held until it lands.@object-ui/components;sdui.manifest.json;Later batches of this card:
element:number(thedataSourcecarve-out);record:line_items(the spec row is pending per the spec's own ledger);events/responsiveStyles/dataSource/aria);action:*and the twoelement:*blocks, after objectstack#20371.Fix round 1 (sent):
block-config-schema-parity-8216node oracle judges the new arms atproperties, where the designer writes. ⛔ No ledgering of the 29 rows.page:tabsbecoming its own arm.Seat error, recorded: the order said "run the tests this order names, not wider sweeps" and named only the types and cli suites. The two red shards (app-shell's block-config parity and the handler-key census) both read the arm list, and the order steered the dev away from them. Any later order that changes the component arm list names the arm-list consumer sweep as a gate.
domain:uiseat 2 · ruling · 2026-09-28T03:4xZ146 remaining items
objectstack-fleet commentedon Oct 4, 2026
os-dev-report
{ "issue": 10872, "status": "done", "branch": "claude/issue-10872-reference-rail-readme", "pr": "https://github.com/objectstack-ai/objectui/pull/11584", "session": "session_01FjqrwXPfSMkSfkKYDSRkN2", "premise_still_valid": true, "summary": "Draft PR objectui#11584 (first line `Fixes #10872`, second `Clause-②: no`) replaces the one README sentence that taught flat `record:reference_rail` `entries` as working with a sentence saying the entries go in the node's `properties` bag, as the example above it shows, and that `objectui validate` refuses a flat `entries` on the node, naming `properties.entries`. The premise was re-measured on main f1c9379 before editing: both faces refuse the flat node and accept the bag node (table below). The sweep of the same README found no other line teaching a flat member as working; the diff is 3 added and 2 removed lines in `packages/plugin-detail/README.md`, nothing else. No changeset is owed: `check-changeset-presence` subtracts `*.md` from published source, and its verdict at the final commit says so.", "tests": "Premise probe, run at base f1c9379 through os-verify-lock.sh (slot issue-10872-dev; VERDICT command-exit 0, held 4s, waited 0s; shared-box seconds): a throwaway vitest file in packages/types/src/__tests__ called safeValidateSchema and StrictAnyComponentSchema.safeParse on the flat node and the bag node, writing the issues to a file in the scratchpad (the repo's vitest config swallows console output). Result: tolerant+FLAT success=false, one invalid_type issue at ['entries'], message 'Unrecognized key(s) on this `record:reference_rail` node: `entries`. Did you mean `entries` -> `properties.entries`?' ...; tolerant+BAG success=true; strict+FLAT same refusal at ['entries']; strict+BAG success=true. The probe file was deleted before the commit (git status clean, the PR file list is the README alone). No ablation or reverse-validation: the diff is prose, so there is nothing to mutate; the probe was a read-only measurement of the unchanged tree. Gates at final commit 17ed7dc: see `gates`. No unit suite or typecheck was run: the diff has no executable or type content, and the dispatch said none is owed for a prose-only diff unless a gate names one. Gates NOT MEASURED: check:readme-exports (exit 1), check:doc-snippets (exit 2), check:doc-examples (exit 2). Reason: each needs dist/ builds that this unbuilt worktree lacks (readme-exports prints 'its type entry ./dist/index.d.ts is not on disk -- run `pnpm build` first' for the whole population; the other two print the scoped-build prerequisite), so those exits are missing-prerequisite, not verdicts on the diff. Bounded by a mechanical check: the README's 10 fenced blocks are byte-identical between f1c9379 and 17ed7dc, as are its heading and link lines, and these three gates judge fenced code and its imports. CI builds and runs them.", "mcp_calls": "0 - no MCP tool was called; every read went through `gh api` GET (card, comments, PR read-back) and local git.", "api_writes": "3 relay strokes through scripts/pm (each is one POST /repos/objectstack-ai/objectstack/dispatches executed by the fleet-write workflow as objectstack-fleet[bot], read back and confirmed): (1) pr_create, POST /repos/objectstack-ai/objectui/pulls, draft, objectui#11584, 6631 bytes sent / 6631 stored identical, run 37165623953; (2) label-write --assign os-zhuang, assignees POST on objectui#11584, labels unchanged (the labeler's `documentation` and `plugin` were already there, none written by me), run 37165661394, read-back MATCHES; (3) this os-dev-report comment via post-stamped.mjs. Plus 2 git pushes of the branch (the empty-branch probe, then 17ed7dc), which are not REST writes. No card assignee, claim, label or body written on objectui#10872.", "open_questions": [], "out_of_scope_findings": [ "carrier: none, noted not filed · the runtime renderers still read the flat spelling: `record-reference-rail.tsx` reads `schema.entries` before `schema.properties.entries` (its docblock says 'The rail accepts a node either flattened ... or enveloped'), and `record-history.tsx` has the same two-way read. This is a consumer-side tolerance of the kind AGENTS.md #0.1 warns about, but the card's own text scopes the fix to the README sentence ('The runtime does read both spellings, so the fix is the README sentence only') and ruling A is on the README, so I did not touch either file or file a card. No `reach:` measured, so it is not a class a/b/c finding; it is a read-only observation. Dedupe words if a seat wants it filed: `record:reference_rail schema.entries flat read` · `record:history schema.entries flat read` · `renderer tolerance flat properties`" ], "files_changed": [ "packages/plugin-detail/README.md (+3 / -2)" ], "gates": [ { "command": "pnpm check:control-bytes", "exit": 0, "verdict": "check-control-bytes: OK (scanned 10205 tracked text file(s); skipped 85 binary)." }, { "command": "pnpm check:new-line-citations", "exit": 0, "verdict": "VERDICT new-cross-file-line-citations: 0 new citation(s), enforcement report-only -> exit 0" }, { "command": "pnpm check:changeset-claims", "exit": 0, "verdict": "report-only: 2 pending changesets name this README (.changeset/7997-detail-view-related-retired.md on the retired `related` array, .changeset/plugin-detail-8937-parent-scope-residue.md on the `filter` arity text); I read both paragraphs, neither concerns reference_rail entries, so neither is falsified" }, { "command": "pnpm check:pending-changeset-literals", "exit": 0, "verdict": "No test source names a pending changeset." }, { "command": "pnpm check:doc-types", "exit": 0, "verdict": "Every documented component type is registered." }, { "command": "pnpm check:doc-fences", "exit": 0, "verdict": "every TypeScript block in 227 document(s) is fenced ts/tsx/typescript (2 declared files, SHRINK-ONLY)" }, { "command": "pnpm check:doc-example-ids", "exit": 0, "verdict": "415 real reference(s) all resolve in the catalog registry." }, { "command": "pnpm docs:check-links", "exit": 0, "verdict": "Links are valid across 17 scan roots." }, { "command": "node scripts/check-changeset-presence.mjs", "exit": 0, "verdict": "No source or published contract of a released package changed in this range, so no changeset is owed." }, { "command": "pnpm check:readme-exports", "exit": 1, "verdict": "NOT MEASURED: prerequisite not met (dist/ type entries not on disk, run pnpm build); not a verdict on the diff" }, { "command": "pnpm check:doc-snippets", "exit": 2, "verdict": "NOT MEASURED: prerequisite not met (scoped build of the covered packages needed); not a verdict on the diff" }, { "command": "pnpm check:doc-examples", "exit": 2, "verdict": "NOT MEASURED: prerequisite not met (same scoped build); not a verdict on the diff" } ], "gates_ran_at": "17ed7dc (the final commit; the same set also ran once on the uncommitted tree with identical verdicts, and the first-pass exits for the three NOT MEASURED gates were 1, 2, 2). The union was re-derived from objectui's own package.json scripts and .github/workflows (all doc and README gates are unfiltered workflows); objectstack's dispatch-gates.mjs was not used, as it answers objectstack's families.", "deviations": [ "No changeset added, and no `skip-changeset` label: objectui's check-changeset-presence exempts `*.md` from published source and printed 'no changeset is owed'; the dispatch said to follow the gate (hypothesis 4).", "Three doc/README gates are NOT MEASURED for the missing-build reason above, bounded by the byte-identical fenced-block check; no whole-tree or scoped build was run for a prose-only diff.", "The seat read of the card used `gh api` GET reads, not the payload channel; none is a write.", "Commits end with the model-free trailer pair (AGENTS.md), not the harness's model-named Co-Authored-By line; the PR body ends with the session-URL footer form named in my contract, not the harness's emoji line." ], "line_budget": "n/a - no skills/** touched", "cleanup": "Worktree /home/user/objectui-issue-10872: tree clean and local head 17ed7dc equalled the remote head, node_modules removed, then `git worktree remove` without --force, exit 0. The probe test file was deleted before the commit. No dev server, watcher or background process was started. Scratchpad files for this card live under issue-10872/ and are prefixed per card." }Generated by Claude Code
objectstack-fleet commentedon Oct 4, 2026
✅ ACCEPT: PR objectui#11584 at head
17ed7dc70(dev report5975083814); it lands through the merge queue when every check is greendomain:uiseat 1 ·session_01FjqrwXPfSMkSfkKYDSRkN2· 2026-10-04T00:43Z. Reviewed against GitHub, not the report.main. The first line isFixes #10872, with no other closing keyword. This is the card's last item: its earlier parts landed through PR objectui#11570 (8d0ca91) and the PRs before it.Clause-②: nois at line start. 1 file,packages/plugin-detail/README.md, +3 / −2.check-governed-merges: NOT governed. The PR assignee isos-zhuang.entriesfrom bothschema.entriesandschema.properties.entriesso either spec-style or flat authoring works." is gone. The new text says theentriesgo in the node'spropertiesbag, as the example above it shows; that the bag is the contract; and thatobjectui validaterefuses a flatentriesand namesproperties.entries. There is no "flat still renders" aside, following the PR objectui#11566 precedent.mainf1c9379before editing:safeValidateSchemaandStrictAnyComponentSchemaboth refuse the flat node with oneinvalid_typeat['entries']("Did you meanentries->properties.entries?"), and both accept the bag node. The probe file was deleted before the commit.record:related_listexample underproperties. This seat's own grep of the head finds no remaining "flat authoring works".check-changeset-presenceexempts*.mdfrom published source and printed "no changeset is owed". Accepted.control-bytes,new-line-citations,changeset-claims,doc-types,doc-fences,doc-example-ids,docs:check-links). The three that need a build (readme-exports,doc-snippets,doc-examples) were not measured in an unbuilt worktree. That gap is bounded: the README's ten fenced blocks are byte-identical to base, and CI runs those three.record-reference-rail.tsxandrecord-history.tsxstill read a flatentries): dropped. It carries no measuredreach:. The card scopes this fix to the README ("The runtime does read both spellings, so the fix is the README sentence only"), and ruling A judged the authoring contract, not the renderer.Generated by Claude Code
objectstack-fleet commentedon Oct 4, 2026
Landed and verified by content: closed
completedby PR objectui#11584, the card's last item ·domain:uiseat 1 ·session_01FjqrwXPfSMkSfkKYDSRkN2· 2026-10-04T01:11Z.The merge: PR objectui#11584 went through the merge queue to
mainas7a7660cat 2026-10-04T01:11Z (seat ACCEPT5975094499).Content check of
packages/plugin-detail/README.mdonmain7a7660cagainst its first parentf1c9379:mainpropertiesbag"entries"The diff is exactly that one file, +3 / −2.
No other card closed in that window.
The card is complete: the
record:line_itemsarm (PR objectui#11570,8d0ca91) and the parts before it are onmain, and this README sentence was the last item. Carried elsewhere, not on this card: objectui#11569 (the registration requireschildObject; p3) and objectui#11573 (AnyComponentSchemaat the TS7056 ceiling;domain:spec).pm:dispatchedis removed in the same act.domain:ui,area:devpath, the type and the priority stay.Generated by Claude Code
fix(types,cli): element:number validates, with the spec's dataSource …
fix(types): record:alert's flat body refusal names the channel the bl…
fix(types): the six held public blocks refuse the content channels no…
feat(types): the four page: containers take their child list in prope…
test(components): the four page: containers render their properties.c…
feat(types): declare node-level `responsiveStyles` on every public-bl…
feat(types): declare node-level `responsiveStyles` on `flex`, `object…
feat(types): a public block's prop written flat on the node is refuse…
feat(types): arm `record:line_items` from its @objectstack/spec 17.6.…
docs(plugin-detail): the reference-rail README says `entries` go in t…