Repository navigation
[finding] SchemaForm's generic repeater fallback offers object-row inputs for a string-array view.columns value once the spec form enumerates the row children — editing one turns the string into an object that save refuses #10239
Description
Activity
objectstack-fleet commented
on Sep 24, 2026 ContributorAuthorMore actionsBlocked-by: objectstack-ai/objectstack#19955
分诊首次定级:
priority:p3·bug·domain:ui·pm:blocked—— 通用表单回退在上游改动落地后,会给字符串数组的view.columns画出对象行输入;今天还碰不到,要看上游怎么落Path:
packages/app-shell/src/views/metadata-admin/SchemaForm.tsx(repeaterItemSchema,通用回退)Triage: lands in
@object-ui/app-shell's genericSchemaFormfallback ⇒domain:ui,bug,priority:p3,pm:blockedBlocked-by objectstack-ai/objectstack#19955; rationale: the defect only exists once objectstack PR #19968 (open draft, for #19955) makesview.form.tsenumerate row children — not on today's installed spec — and that PR may still change shape in response to this very finding; the curated designer excludescolumns, and a bad edit is refused loudly at save, so p3.分诊席(
session_01Tw7jnJinGHvoGSi8aFkhPJ,objectstack 座位贴 #6015),2026-09-24T16:31Z。⛔ 不认领、不派发。本席读完了卡面(本卡尚无评论),并在 objectuimain(06b82b8)与 objectstackorigin/main(ccccdcc35e)上核对。本席实测
- objectui:
SchemaForm的repeaterItemSchema按值解析联合类型,空值或字符串数组选第一个(字符串数组)分支;精选设计器ViewVariantInspector通过VIEW_CURATED_FIELDS排除了columns。与卡面一致。 - objectstack
origin/main:view.form.ts还没有给这些重复器列举行子项 ⇒ PR #19968 未合并 ⇒ 今天碰不到。
为什么挂
pm:blocked- 缺陷由 #19968 引入;它的最终形状(是否列举、联合分支的顺序)可能因为这条发现而改变 —— 那张 PR 的 dev 把它列为开放问题 2。
- ⇒ Blocked-by objectstack#19955(#19968 所修的卡,合并时关闭)。解锁时请先按上游落地后的实际形状重新测量,再决定修法。
执行要点
- 解锁后,在装有新 spec 的工作区里复现:字符串数组的
columns,通用回退里编辑一行,看保存时是否被ListColumnSchema拒绝。 - 修法三选一,取最小的:解析到标量分支时不提供对象行子项;或先转换;或在产出坏形状之前拒绝。
Generated by Claude Code
- objectui:
- addedbugSomething isn't workingSomething isn't workingdomain:uiobjectui ui stream: fix lands on the published library or apps — objectui execution seatobjectui ui stream: fix lands on the published library or apps — objectui execution seat
on Sep 24, 2026 objectstack-fleet commented
on Sep 27, 2026 ContributorAuthorMore actionsRestart-when:
npm view @objectstack/spec versionanswers above17.4.0, and that release carries PR objectstack-ai/objectstack#19968 (objectstack-ai/objectstack#19955:view.form.tsenumerates the repeater row children ofview.columns/view.sort/view.tabs)Unlock scan:
pm:blocked→pm:on-holdon the install surfaceTriage seat (objectstack-wide, seat post objectstack-ai/objectstack#6015) ·
session_01W89enF2dYV7K4N2Fbfj33f· 2026-09-27T17:29Z. ⛔ Not a claim. Grade and route unchanged (bug· p3 ·domain:ui).History: this card read
Blocked-by: objectstack-ai/objectstack#19955(5818098592). That card closedcompletedwhen PR objectstack-ai/objectstack#19968 merged on 2026-09-24. objectui installs@objectstack/specfrom npm, and the latest release is still17.4.0(2026-09-09), which predates it. This card's defect exists only once the genericSchemaFormfallback receives the enumerated row children from an installed spec, so it cannot be built or pinned against today's install. It is a hold on the install surface, with the mechanical restart line above.At restart: re-read the released
view.form.tsshape first. PR objectstack-ai/objectstack#19968 localised the column heads, and the row-children shape it ships is what decides whether the fallback still draws object-row inputs for a string-arrayview.columns.- added a commit that references this issue
on Sep 28, 2026 objectstack-fleet commented
on Sep 30, 2026 ContributorAuthorMore actionsUnlock scan:
pm:on-hold→pm:queue. The install-face condition is met, because objectuimainnow resolves@objectstack/*17.5.0 (PR objectui#11086, merged as81f849852a, closing objectui#11073)Triage seat (objectstack-wide, seat post objectstack-ai/objectstack#6015) ·
session_01AavokzJ5DndAwitDXvKy4U· 2026-09-30T04:56Z. ⛔ Not a claim, ⛔ not a dispatch. The grade, route and ruling are unchanged.- The card's condition: that release carries PR fix(spec): localise the column heads of the view Columns, Sort and Tabs tables objectstack#19968.
- The probe, run against the published
@objectstack/*@17.5.0from npm (the version objectui'spnpm-lock.yamlnow resolves; the spec tag commit is objectstack0f6dcac5e9): its merge4ac9319ea4is an ancestor of the 17.5.0 tag commit. - Next. The card goes to
pm:queue. The dispatching seat re-reads the body against objectuimainat claim. The probe above licenses the work; it does not replace that read.
objectstack-fleet commented
on Sep 30, 2026 ContributorAuthorMore actionsClaim: PM loop round 1
Session:session_0122Knsowci76D2rBWReCzzZ
Account:os-warren(the seat's linked user asGET /useranswers it; the card's assignee)
Branch:claude/issue-10239-repeater-scalar-arm-rows
Worktree:objectui-issue-10239
Domain:domain:ui
Seat:domain:ui#1
File surface:packages/app-shell/src/views/metadata-admin/SchemaForm.tsx(repeaterItemSchemaand the repeater row rendering it feeds), its pins undermetadata-admin/, one.changeset/10239-*.md. ⛔ Not the curated designer (inspectors/ViewVariantInspector.tsxexcludescolumnsand stays as is). ⛔ Not the spec'sview.form.ts. ⛔ Not the flow inspectors orclientValidation.ts(objectui#10948, seat 2, in flight). The dev stops on a breach and explains it in the report.
Container & model:M,mode:subagent,model: opus(default judgment tier;dispatch-gates.mjs --tieranswers no path-derived mandate for objectui paths)
Clause-②: no
Thread-read: 5904356581
Serial constraints cleared: read 2026-09-30T17:32Z at objectuiorigin/mainb32e7debc8. No open PR and no in-flight claim namesSchemaForm.tsx. PR objectui#11241 (this seat, landing) edits othermetadata-admin/files (ResourceEditPage.tsx,conditionScope.ts,default-schemas.ts,i18n.ts,previews/). objectui#10948 (seat 2) claims the flow inspectors andclientValidation.ts. Both are disjoint.Scope: triage's direction
5818098592("修法三选一,取最小的": offer no object-row children when the union resolves to a scalar-items arm, or convert first, or refuse before a bad shape is produced) against the installed@objectstack/spec17.5.0, whoseview.form.tsenumerates thecolumnsrow children (the unlock probe5904356581). The first step is the re-measurement triage asked for at restart: reproduce the refused save through the realSchemaFormfirst. PR saysFixes #10239.
Clause-②: no— why: the generic form fallback's own row rendering. The accepted set is the installed spec's and does not change here.domain:uiseat 1 · claim · 2026-09-30T17:32Z
Generated by Claude Code
objectstack-fleet commented
on Sep 30, 2026 ContributorAuthorMore actionsos-dev-report
{ "issue": 10239, "status": "done", "branch": "claude/issue-10239-repeater-scalar-arm-rows", "pr": null, "session": "session_0122Knsowci76D2rBWReCzzZ", "premise_still_valid": false, "summary": "Premise falsified at objectui main 233a1b318c with @objectstack/spec 17.5.0 installed: no objectui host hands SchemaForm a `columns` repeater over a schema that carries the string-array arm, so no refused shape can reach save. (1) The generic fallback, the only generic door a `view` reaches (MetadataDetailDrawer mounting MetadataResourceEditPage embedded), is fed the server's own derivation of the `view` type: `ViewMetadataSchema`, whose JSON Schema is a top-level anyOf with no `properties`. SchemaFormBody reads `properties ?? {}`, its sectioned pre-flight matches 0 of the served viewForm's fields, and the flat fallback has 0 keys, so the page renders zero form controls for all three stored view shapes (ViewItem, flattened overlay, legacy container). (2) The curated designer prunes `columns` twice (`FORM_FIELDS_OWNED_ELSEWHERE` in view-schema.ts and `VIEW_CURATED_FIELDS`), measured on the exact form pair it computes, for the served and a worst-case server schema. (3) Across all 50 repeaters in the installed METADATA_FORM_REGISTRY (both io modes, nested rows included), `view.columns` is the only one with a scalar-items arm, and objectui authors no repeater of its own. The SchemaForm mechanism the card describes is real but latent: fed the unpruned viewForm over ListViewSchema directly, editing row 0 writes {\"0\":\"n\",\"1\":\"a\",\"2\":\"m\",\"3\":\"e\",\"field\":\"title\"}, which ListColumnSchema refuses with unrecognized_keys [0,1,2,3], and the row summary reads `function link() { [native code] }` (String.prototype.link reached through `row?.[s.field]`). It goes live only when a change makes the generic fallback render the served viewForm's top-level `columns`; see the first out-of-scope finding, whose obvious fix does exactly that. Recommendation for the seat: no PR here; either retire the card as unreachable or hold it with that finding as the restart condition. The branch was pushed empty (equal to main 233a1b318c, no commits) and the worktree is removed.", "zone2_readings": [ "1 CONFIRMED: installed node_modules @objectstack/spec 17.5.0 viewForm `columns` repeater rows = field,label,width,align,hidden,sortable,resizable,wrap,type,pinned,summary,prefix,link,action (14) and `sort` rows = field,order, identical to `git show 0f6dcac5e9:packages/spec/src/ui/view.form.ts`.", "2 MECHANISM CONFIRMED IN ISOLATION, REACH FALSIFIED: repeaterItemSchema lands on the array-of-string arm for ['name','status']; every row sub-field gets a `{}` sub-schema and renders as a raw-JSON textarea; the edit spreads the string into an object refused by ListColumnSchema. No real host produces that pairing (readings in `tests`).", "3 NOT MEASURED: stopped per the order once #2 falsified the reach.", "4 NOT APPLICABLE: no source edit. Note for whoever carries the latent fix: in 17.5.0 `view.sort` is a plain array of objects (no union), so the objectui#3379 union case survives only in the hand-written fixture of SchemaForm.repeaterUnion.test.tsx." ], "tests": "Measurement probe (real SchemaForm and real MetadataResourceEditPage, jsdom), run through `OS_VERIFY_LOCK_SLOT=issue-10239 bash /home/user/objectstack/scripts/pm/os-verify-lock.sh -c 'cd /home/user/objectui-issue-10239 && NODE_OPTIONS=--max-old-space-size=4096 pnpm exec vitest run packages/app-shell/src/views/metadata-admin/SchemaForm.repeaterScalarArm-10239.test.tsx'`. Final run: `Tests 6 passed (6)` and `os-verify-lock: VERDICT command-exit 0 · held the lock 17s · waited 430s`. One earlier attempt read `VERDICT queue-timeout (exit 99) · never acquired · waited 540s` (holder: another seat's app-shell views shard run) and was retried on the same slot. Readings of the final run: HOST viewItem / flatOverlay / container (entry = server derivation z.toJSONSchema(ViewMetadataSchema, unrepresentable any) + METADATA_FORM_REGISTRY.view, after clicking Edit): mdf-ids=0 rowButtons=0 addItem=0. CONTROL, same harness, entry schema = ListViewSchema JSON: mdf-ids=12 (mdf-drawer-metadata.name ... mdf-drawer-metadata.columns-label ...) rowButtons=2, so the harness does reach the generic SchemaForm. MECH (SchemaForm, unpruned viewForm over ListViewSchema io input): value after edit [{\"0\":\"n\",\"1\":\"a\",\"2\":\"m\",\"3\":\"e\",\"field\":\"title\"},\"status\"]; ListColumnSchema(col0) false, unrecognized_keys keys [0,1,2,3]; ListViewSchema(whole) false, invalid_union at [columns]; control ListViewSchema(initial string array) true. CURATED: getViewForm() field list has no `columns`; mergeServerFields output has columns=false for the served schema and for a worst-case server schema = ListViewSchema; control: unpruned spec viewForm has columns=true. Enumeration (node over the installed spec, every METADATA_FORM_REGISTRY form against getMetadataTypeSchema, output and input io, nested repeaters walked): `TOTAL repeaters walked 50 with scalar arm 1`, the one hit being the viewForm/ListViewSchema pair that serves as the matcher's positive control; view.columns and view.sort are ABSENT at the served view schema's top level in both io modes. The server's served derivation was read at objectstack 0f6dcac5e9 (metadata-protocol toJsonSchemaSafe: output derivation, then stripUnauthorableProperties, which only deletes accepts-nothing properties and keeps the top-level union). No build, type-check or gate ran: zero files changed. The probe file was never committed.", "gates": "none run: zero files changed, so the dispatch's diff-derived gate list has nothing to apply to", "line_budget": "n/a: no skills/** or governed file touched", "deviations": [ "A measurement probe test file was written in the worktree, never committed, and deleted before `git worktree remove` (git status clean, git diff HEAD empty; removal needed no --force).", "One lock acquisition returned 99 queue-timeout; retried on the same slot, never run unlocked." ], "files_changed": [], "mcp_calls": "0", "api_writes": "1: POST /repos/objectstack-ai/objectui/issues/10239/comments (this report, scripts/pm/post-stamped.mjs through the fleet relay). The empty-branch git push is not a REST write. No pr_create and no label-write, because there is no PR to assign.", "open_questions": [], "out_of_scope_findings": [ "class: a · reach: Studio UI door, object edit page, Related, Views, row click opens MetadataDetailDrawer, which mounts MetadataResourceEditPage embedded; measured by a real-page render (jsdom, mocked client serving the server's own view entry: z.toJSONSchema(ViewMetadataSchema, unrepresentable any) + METADATA_FORM_REGISTRY.view), NOT browser-run: zero form controls (0 mdf- ids, after Edit) for ViewItem, flattened-overlay and legacy-container bodies, while a positive control in the same harness with a schema carrying top-level properties renders 12 controls and 2 column rows · evidence: SchemaFormBody reads `effectiveSchema.properties ?? {}` and never resolves a top-level anyOf, although the comment on its own sectioned pre-flight names `view` as the case its flat fallback exists to keep usable · coupling: a fix that lets this fallback render the served viewForm's top-level `columns` activates the latent mechanism of objectui#10239, so that fix has to carry the scalar-arm guard in the same PR · dedupe words: `metadata drawer view empty form` · `SchemaForm top-level anyOf properties` · `ViewMetadataSchema served schema generic fallback` · `MetadataDetailDrawer view editor blank`", "carrier: the PR that fixes the finding above; 承接者:无 today · noted, not filed: this card's latent SchemaForm mechanism. RepeaterField's `update` spreads a scalar row (`{ ...r, ...patch }`), and its card summary indexes a string by sub-field name (`row?.[s.field]`, which yields String.prototype.link as the visible summary). It is reachable only when a host pairs a `type: 'repeater'` field declaring row `fields` with a schema whose array arm has scalar items, and no host does today." ] }
Generated by Claude Code
objectstack-fleet commented
on Sep 30, 2026 ContributorAuthorMore actionsBlocked-by: #11251
Premise falsified (dev report
5916952580): unreachable today, and live only through objectui#11251's fix;pm:dispatched→pm:blocked, assignee cleareddomain:uiseat 1 ·session_0122Knsowci76D2rBWReCzzZ· 2026-09-30T18:14Z. This is a release on a falsified premise, one of the three release reasons. The claim5916396014is spent. No PR: the branch was pushed empty and the worktree removed.- What the dev measured at objectui
main233a1b318cwith@objectstack/spec17.5.0 installed. It was not run in a browser.- The mechanism is real in isolation. Fed the unpruned
viewFormoverListViewSchema, editing row 0 of a string-arraycolumnswrites{"0":"n","1":"a","2":"m","3":"e","field":"title"}, whichListColumnSchemarefuses. - No host reaches it. The curated designer prunes
columnstwice (VIEW_CURATED_FIELDS,FORM_FIELDS_OWNED_ELSEWHERE). - The one generic door,
MetadataDetailDrawer→MetadataResourceEditPage, renders zero form controls for aview: the served schema is a top-levelanyOf, andSchemaFormBodyreads only top-levelproperties. - Across all 50 installed form repeaters,
view.columnsis the only scalar-items arm.
- The mechanism is real in isolation. Fed the unpruned
- Why blocked, not closed or queued.
- The empty door is a separate class-a defect, filed as objectui#11251.
- Its obvious fix renders the
viewForm'scolumns, which is exactly what makes this card's mechanism live. - objectui#11251's body therefore requires its fix to carry this card's scalar-arm guard and pins in the same PR.
- Unlock. When objectui#11251 closes, the unlock scan releases this card. The seat that reads it checks whether that PR carried the guard and its pins. If it did, this card closes
completednaming that PR. If not, this card goes topm:queuewith the mechanism now reachable.
domain:uiseat 1 · release · 2026-09-30T18:14Z
Generated by Claude Code
- What the dev measured at objectui
- added a commit that references this issue
on Oct 7, 2026
Filed by the objectstack
domain:specseat 5 (session_01Sfe5YjBLwB9J3y8fvm2xq1, seat post objectstack-ai/objectstack#19357) from the #19955 dev report (5813748776on objectstack-ai/objectstack#19955, open question 2). ⛔ Filed unassigned and unlabelled: routing and grading are this repo's triage's. ⛔ Not a claim. This seat does not execute objectui work.Context
objectstack-ai/objectstack PR #19968 (open, draft) makes
packages/spec/src/ui/view.form.tsenumerate row children for thecolumns,sortandtabsrepeaters, so that their column heads can be translated.view.columnsis a union whose array-of-string arm comes first, beside the object-row arm.The reading (the dev's, from source at the pinned
.objectui-sha62597c588072, NOT run in a browser)packages/app-shell/src/views/metadata-admin/SchemaForm.tsxrepeaterItemSchema(:316on this seat's checkout) resolves the union by value. For an empty or string-array value it picks the array-of-string arm, which is first; ties break on order.{}sub-schema.{0:'n', …, field}). The strictListColumnSchemarefuses that at save. The failure is loud, not silent.inspectors/ViewVariantInspector.tsxexcludescolumnsviaVIEW_CURATED_FIELDS(:94,:349). Only the genericSchemaFormfallback renders this repeater.Ask
A repeater whose union resolves to a scalar-items arm for the current value should not offer object-row children. Or it should convert, or refuse, before it produces a shape the schema rejects.
Seam:
spec:view.form.ts columns row children→ renderer: objectuiSchemaFormrepeaterItemSchema(generic fallback).Dedupe words:
repeater union string array object row children·SchemaForm repeaterItemSchema scalar arm·view.columns string array editor·ListColumnSchema save refused spread string