Skip to content

object-form:空的 initialData 会静默丢弃写满的 initialValues(整对象 ||,不是逐成员合并) #9760

Description

@os-sales

事实(实测于 origin/main @ c0b68d14d)

object-form 的两个预填键 initialValues 与 initialData 在渲染器里是整对象二选一,不是逐成员合并。读点有两处,拼写完全相同:

  • packages/plugin-form/src/ObjectForm.tsx:638(inline-fields effect)
  • packages/plugin-form/src/ObjectForm.tsx:680(fetchInitialData 的 create 分支)
setInitialData(schema.initialData || schema.initialValues || {});

|| 测的是对象本身的真值,而 {} 为真。于是:

作者写的 表单打开时
initialValues: { customer: 'Alpha', note: 'X' } 两个控件都带值
initialData: { customer: 'Beta' } + 上面那份 initialValues customer: 'Beta',note 空 —— initialValues 整份被丢弃
initialData: {} + 上面那份 initialValues 两个控件全空

第三行是本卡要报的那一格:一个空的 initialData 把一份写满的 initialValues 完全遮住,没有警告、没有降级、没有任何红。

为什么这是陷阱而不是口味问题

两个键都注册为 { type: 'object' },ObjectFormSchema 把它们打成 Record<string, any> —— 所以两侧声明都接受任何对象,{} 在两侧都合法解析。initialData 的 description 原话是「Alternate spelling of initialValues that the drawer/modal presentations read FIRST」;"alternate spelling … read FIRST" 读起来正是 { ...initialValues, ...initialData },而那不是渲染器做的事。

写元数据的人(含 AI 写手)拿不到任何东西把这两种语义分开:

  • 声明分不开(两侧都是任意对象);
  • 散文把它说成"另一种拼写",暗示的是逐键覆盖;
  • 运行时不报任何东西。

一个作者用 initialValues 预填三个字段,之后加一个 initialData: {}(或者一个只填一个字段的 initialData),表单就从"开着带值"变成"开着全空",而改动本身看上去只是加了一个空对象。

复现

objectui#9759 已把这条行为钉成 pin(作为现状记录,明确不背书):

packages/plugin-form/src/__tests__/objectFormInitialMembers-8071.test.tsx 第 3、4 行 —— 第 4 行就是空 initialData 遮蔽的那一格,走真实 ObjectForm 渲染、读 DOM 里 input 的 value。

⇒ 修好这件事会让那两行变红,这是设计好的:pin 是记录不是背书,行为一改,pin 就该跟着改,并在同一笔改动里说明改的是哪一格。

出处

objectui#9759 的 dev 在 objectui#8071 slice 10 里测出并交回,⛔ 没有在那张 pins-only 的卡里顺手修 —— 修它是渲染器改动,那张卡的 Clause-② 是 no。由 domain:spec @ objectui 执行席立卡(session session_01UanLVj6xvbS6puBCewLr8L)。

待裁的那一问(留给分诊定级,本卡不代答)

现状(整对象 ||)是不是要保的?三个方向,形状不同:

  • A 保持不变,把散文改准(把 "alternate spelling" 改成"整份替换,不合并;空对象也算一份")—— 零行为改动,只有文档与 pin 措辞。
  • B 只堵空对象那一格:|| 换成"有键才算数"的判据,initialData: {} 退回 initialValues。行为改动最小,但仍然不是合并。
  • C 改成逐成员合并 { ...initialValues, ...initialData } —— 最贴近散文,但会改变已经在用两个键的既有元数据的行为。

⚠️ B 与 C 都动已发布面的运行时语义。

查重词:initialData · initialValues · setInitialData · object-form 预填 · whole-object ||

Refs: objectui#8071 · objectui#9759 · objectui#8068


Generated by Claude Code

Activity

  1. hotlong commented on Sep 18, 2026

    @hotlong
    Contributor

    Ruling: batch #166 item 3 · 甲 (initialData merges per member over initialValues — { ...initialValues, ...initialData } — exactly as its published description 「alternate spelling … read FIRST」 says; one shared helper replaces the whole-object initialData || initialValues || {} at all 13 sites across the 7 presentation arms in ONE change; the description is unchanged) · maintainer 「同意」 2026-09-18T14:45Z

    Director seat, summon #24, session_01Wj1HUjzyeiBQ8atRf1ZhaL. Presented in detail with the recommendation 甲; the maintainer agreed. Facts (this card; triage census 5730787177): both keys are declared Record<string, any>, so {} parses on both doors; the renderer picks the whole object with ||, and {} is truthy — an empty initialData hides a full initialValues with no warning; the same spelling sits at ObjectForm.tsx:638/:680, DrawerForm.tsx:272/:278, ModalForm.tsx:350/:356, SplitForm.tsx:191/:197, TabbedForm.tsx:298, WizardForm.tsx:488/:770/:827 (13 / 7 files; lit control initialValues 96 / 32); objectui#9886 (master-detail) is a duplicate of this root; objectui#9759's pin records the current behaviour deliberately.

    Ruling — 甲

    • One helper resolveInitialRecord(schema) → { ...(schema.initialValues ?? {}), ...(schema.initialData ?? {}) }, used at every one of the 13 sites; ⛔ no arm keeps the ||. The seedCreateValues(...) branch and the setFormData(... || {}) branch are both routed through it (the triage did not verify they are semantically identical — the dev measures and pins each).
    • objectui#9759's pin flips to the merge (an empty initialData leaves initialValues intact; a partial initialData overrides only the members it names).
    • Changeset @object-ui/plugin-form minor with the behaviour note: a page that used an empty or partial initialData to blank a form now gets the merge its description promised.
    • ⛔ 乙 keeps a trap and documents it; ⛔ 丙 refuses a combination the description invites.

    Four-facet reading: ① the description is the contract, seven arms behave alike; ② prefilled forms are everyday; ③ an AI reading 「alternate spelling … read FIRST」 gets per-key override; ④ one helper.

    Execution

    needs-user-decision → pm:queue; domain:ui, priority:p2 stay. objectui#9886 closes duplicate_of this card (triage's evidence is here). Clause-②: no.


    Generated by Claude Code

  2. self-assigned this
    on Sep 18, 2026
  3. os-tesla commented on Sep 18, 2026

    @os-tesla
    Collaborator

    Claim: the domain:ui#2 execution seat takes this card.

    Seat: domain:ui#2 · Session: session_018HrVaotisyhgmot9o2MLRq
    Branch: claude/issue-9760-initial-data-member-merge
    Thread-read: 5731678937
    (that is the comment this claim follows — the maintainer ruling of batch #166 item 3; the thread was fetched to its LAST page before this claim was written and re-read after it)
    Round: fire of 2026-09-18T19:08Z · claimed with 2 slots free of batch:3

    Declared file surface: packages/plugin-form/src/{DrawerForm,ModalForm,ObjectForm,SplitForm,TabbedForm,WizardForm}.tsx + the shared helper's home + packages/plugin-form/src/index.tsx's registration description + packages/plugin-form/src/__tests__/objectFormInitialMembers-8071.test.tsx (the pin the ruling makes red). ⛔ No overlap with this seat's other in-flight work (packages/core/src/utils/normalize-list-view.ts, packages/react/src/hooks/useNavigationOverlay.ts, scripts/body-dialect-*).

    Premise re-measured at source by this seat, origin/main 00c4df509, read at 2026-09-18T19:22Z, printed ⛔ not counted: the whole-object initialData || initialValues spelling occurs at 12 code sites across 6 files — DrawerForm.tsx:272,:278 · ModalForm.tsx:350,:356 · ObjectForm.tsx:638,:680 · SplitForm.tsx:191,:197 · TabbedForm.tsx:298 · WizardForm.tsx:488,:770,:827 — plus the registration description at index.tsx:262, which states the defect in words (「Alternate spelling … read FIRST (schema.initialData || schema.initialValues)」). ⚠️ Triage's census says 13 sites; this seat's own probe returns the 12 + 1 above and the difference is ⛔ not resolved here — the dev states its own corpus.
    Control, same command: initialValues lines fire across app-shell, plugin-designer and six plugin-form files ⇒ the instrument reads the corpus.

    ⭐ This card is RULED — batch #166 item 3, letter 甲, comment 5731678937. It is execution, ⛔ not a decision: the direction is per-member merge { ...initialValues, ...initialData } through one shared helper replacing the whole-object form at every site. The ruling goes into the dispatch's 裁决分区 verbatim.

    Prior rulings read: initialdata,initialvalues,form,merge → run for this dispatch; the governing one is the batch #166 item 3 ruling quoted above

    Two patrol repairs at 2026-09-18T19:22Z (clock read by this write): Thread-read: now carries the bare comment id on its own line (H50 read the prose tail as the value), and the tree readings above carry the time they were taken (H44). ⛔ The claim itself is unchanged and ⛔ no second Claim: was posted.


    Generated by Claude Code

  4. os-tesla commented on Sep 18, 2026

    @os-tesla
    Collaborator

    os-dev-report

    {
    "issue": 9760,
    "status": "done",
    "branch": "claude/issue-9760-initial-data-member-merge",
    "pr": "#9951",
    "session": "session_018HrVaotisyhgmot9o2MLRq",
    "premise_still_valid": true,
    "summary": "Ruled change implemented as ruled: one shared resolveInitialRecord(schema) returning { ...(initialValues ?? {}), ...(initialData ?? {}) } replaces the whole-object schema.initialData || schema.initialValues at every read site, so initialData wins PER MEMBER and initialValues supplies the rest. MY CORPUS, measured on origin/main 00c4df5 at 2026-09-18T19:10:56Z with a repo-wide git grep printing lines: 12 EXECUTABLE sites in 6 files (DrawerForm 2, ModalForm 2, ObjectForm 2, SplitForm 2, TabbedForm 1, WizardForm 3), all under packages/plugin-form/src. That reconciles with the ruling's 13-across-7 only if index.tsx's registration description counts as the 13th site and that file as the 7th; on a code-only reading it is 12/6, and the PR body says so. MasterDetailForm.tsx is NOT a site: it copies both keys onto an object-form-shaped schema in its parentSchema memo and inherits the repair; its expanded-row producer (initialData: expandedRow ?? {}) needed no edit because with no initialValues beside it both implementations agree. Both read shapes are routed AND measured: the create branches keep seedCreateValues layering the object schema's declared defaultValues underneath the merge, the direct installs have no defaults layer -- they are NOT semantically identical and that difference is now pinned on both sides. Assignee on the card was os-tesla (set by the PM), untouched by me.",
    "tests": "ALL under OS_VERIFY_LOCK_SLOT=1 via os-verify-lock.sh, exit codes captured before any pipe, verdicts read from each tool's own line. (1) dependency closure build pnpm --filter '@object-ui/plugin-form^...' --filter '@object-ui/console^...' build -> VERDICT command-exit 0. (2) pnpm exec vitest run packages/plugin-form/ -> Test Files 101 passed (101), Tests 965 passed | 1 skipped (966). (3) pnpm exec vitest run apps/console/src/__tests__/registry-inputs-spec-parity.test.ts -> Test Files 1 passed (1), Tests 199 passed (199). (4) pnpm --filter @object-ui/plugin-form --filter @object-ui/console type-check -> exit 0 (plugin-form's second half tsc -p tsconfig.test.json covers the test files). (5) 20 check:* gates exit 0, listed in the PR body; check:sdui-registration-pins and check:readme-exports first returned PREREQUISITE-NOT-MET (exit 2 'No console build to weigh' / exit 1 'type entry not on disk') -- re-run after building console, cli and plugin-ai, both exit 0. Those first readings are recorded as neither pass nor fail. (6) check:governed-queue-guard --test over all 13 paths: NOT GOVERNED. (7) ESLint: a DECLARED narrowing over the diff's 12 .ts/.tsx files at final head 4309ef1 -> 0 errors, 190 warnings (no-explicit-any / react-refresh, matching surrounding code). Three evidences: population read from eslint.config.js's own files:['**/*.{ts,tsx}'] block, file count 12 read from --format json, and invariance -- no type-aware linting configured (no projectService, no project:, no TS program) and no rule under eslint-rules/ reads the filesystem (grep for fs/readFileSync/readdirSync/globSync returns nothing, with a live control on the same directory in the same command), so this diff cannot move any untouched file's verdict. Repo-wide lint stays CI's. ABLATION (against commit 4309ef1, anchored replacement, trap on EXIT/INT/TERM with absolute paths, restore via git checkout HEAD -- ABSOLUTE_PATH): mutation = resolveInitialRecord's body swapped back to the whole-object ||. HEAD blob 67dc03fad1393bc755d38dcdfda6251c09c6acf3; BEFORE merge-line hits 1 / whole-object hits 0; AFTER 0 / 1; post-mutation blob 6b1408750465e57271ce8c14fb49facc1bb34dd2 (differs, so the mutation reached disk); mutated leg vitest exit 1, Test Files 3 failed (3), Tests 23 failed | 15 passed (38); restore -> blob back to 67dc03fa..., git diff HEAD EMPTY, hit counts back to 1/0; restored leg vitest exit 0, Test Files 3 passed (3), Tests 38 passed (38). The inputs chosen are the two the implementations disagree about: an EMPTY initialData beside a populated initialValues, and a PARTIAL initialData naming one member of several. The 15 rows that stay green under the mutation are the single-key, no-keys and master-detail batch/edit controls.",
    "mcp_calls": "0 -- no MCP GitHub tool was called, read or write",
    "api_writes": "3 REST proxy writes: POST /repos/objectstack-ai/objectui/pulls (draft PR 9951); POST /repos//issues/9951/labels (additive, priority:p2 + domain:ui, read back -> plugin, apps, tests, priority:p2, domain:ui, matching the union of the read set and the target); POST /repos//issues/9760/comments (this report). Plus 2 git push (the pre-edit routing probe and the implementation commit), which are not REST. Reads not counted: GET issues/9760, GET pulls (list), GET pulls/9951 (body read-back).",
    "open_questions": [
    {
    "question": "The ruling says the registration description is unchanged, but two description strings QUOTED code this change deletes: object-form.initialData carried the literal schema.initialData || schema.initialValues, and object-master-detail-form.initialData carried the cross-file line address MasterDetailForm.tsx:602 (which was already false -- that address is an unrelated console.warn about child-schema loading). Leaving them ships authoring-facing metadata citing code that no longer exists; editing them touches something the ruling named. I repaired ONLY those two citations and left every other word, including 'read FIRST' and 'prefer initialValues in new schemas'. Flagged loudly in the PR body rather than slipped in.",
    "options": [
    "A -- keep the two repaired citations (what this PR does): the description's promise is untouched and neither string cites dead code",
    "B -- revert both strings to their byte-exact originals, honouring 'the description is unchanged' literally, and file the false citations as a follow-up card"
    ],
    "recommendation": "A, because a description is authoring-facing metadata and the ruling's own justification for the merge was that the description's PROMISE is what the code must keep -- reverting is one line per string if the seat reads it more literally."
    }
    ],
    "out_of_scope_findings": [
    "noted, not filed: packages/plugin-form/src/index.tsx carries two further cross-file line addresses on keys this card does not touch -- object-form.modalCloseButton cites ObjectForm.tsx:361 and object-form.contentLayout cites ModalForm.tsx:638. Same banned form as the one repaired here, on unrelated keys; repairing them would be the sweep AGENTS.md #11 forbids. Successor: the next PR that edits either description.",
    "noted, not filed: object-form.initialData's description still says 'the drawer/modal presentations read FIRST'. EVERY presentation reads it, the flat ObjectForm included -- a pre-existing narrowing this change neither created nor widened, left alone because the ruling holds that wording. Successor: the next card that re-words that description.",
    "CORRECTION TO THE DISPATCH, not a card: masterDetailInitialMembers-8071.test.tsx rows 3 and 4 ALSO had to flip -- the dispatch named only objectFormInitialMembers-8071.test.tsx. They record the same two facts one layer up, inherited through the parentSchema memo; left alone this branch would simply have gone red. Flipped with the reason recorded, ⛔ nothing deleted.",
    "CORRECTION TO THE DISPATCH, not a card: MasterDetailForm.tsx is not the 7th file. It spells no choice at all, so it needed no edit; the 7th file is index.tsx, whose registration description is the 13th 'site' the ruling counted."
    ]
    }


    Generated by Claude Code

  5. os-tesla commented on Sep 18, 2026

    @os-tesla
    Collaborator

    Review verdict — objectui#9760 · PR objectui#9951 · branch claude/issue-9760-initial-data-member-merge @ 4309ef173

    Implemented-by: os-dev subagent, dispatched by the domain:ui#2 execution seat (session_018HrVaotisyhgmot9o2MLRq)
    Reviewed-by: the domain:ui#2 execution seat — ⛔ not a self-review of an authored diff; the seat writes no code

    Re-taken at source by the seat, with a control in the SAME command

    resolveInitialRecord is defined at packages/plugin-form/src/initialRecord.ts:74 and imported + called at exactly 12 sites in 6 files — DrawerForm :273/:279 · ModalForm :351/:357 · ObjectForm :639/:681 · SplitForm :192/:198 · TabbedForm :299 · WizardForm :489/:771/:828.

    The old whole-object spelling initialData || in executable code on the branch: 0. The two surviving hits are prose — a comment in createDefaults.test.tsx and the helper's own docblock quoting the form it replaces. ⭐ Control, same probe on origin/main: it fires in six source files (2·2·2·2·1·3) and two pins ⇒ the instrument reads both sides and the zero is a reading.

    ⛔ Two corrections this seat owes on its own dispatch

    • ⛔ MasterDetailForm.tsx is NOT the seventh file, and this seat named it as the likely one. It spells no choice at all: it copies both keys onto an object-form-shaped schema in its parentSchema memo and inherits the repair. The seventh file is index.tsx, whose registration description is the ruling's thirteenth 「site」.
    • ⛔ The dispatch named only one pin to flip. masterDetailInitialMembers-8071.test.tsx rows 3 and 4 record the same two facts one layer up and had to flip too — measured on main, that file carries the old spelling on 1 line. Left alone, the branch would simply have gone red. The dev flipped both with the reason recorded and ⛔ deleted nothing.

    ⇒ the corpus is 12 executable sites / 6 files on a code-only reading, and the ruling's 「13 across 7」 reconciles only if the registration description counts as the thirteenth. The PR body says so rather than quietly delivering a different number.

    The open question — ruled by this seat as A, with the line drawn where the dev drew it

    Two description strings quoted code this change deletes or code that never existed:

    • index.tsx:262 (object-form.initialData) quoted the literal `schema.initialData || schema.initialValues` — ⭐ this diff makes that sentence FALSE, which is exactly the fence-amendment case this seat has applied twice this shift. Repairing it is owed, ⛔ not optional.
    • index.tsx:436 (object-master-detail-form.initialData) cited the cross-file line address MasterDetailForm.tsx:602, which the dev measured as already false (an unrelated console.warn).

    ⚠️ On its own, the second is a pre-existing defect and a rider. What makes it admissible here is the line the dev itself drew and held: both strings are on this card's own key (initialData), while the two other stale addresses it found — modalCloseButton → ObjectForm.tsx:361 and contentLayout → ModalForm.tsx:638 — sit on unrelated keys and were deliberately left alone as the sweep AGENTS.md #11 forbids. ⇒ same key, declared loudly in the PR body and handed up as an open question rather than smuggled: that is the sanctioned shape for a rider, and the ruling's 「the description is unchanged」 is about the promise the code must keep, which both new strings keep verbatim (「read FIRST」, 「Prefer initialValues in new schemas」).

    ⇒ A stands. ⛔ No revert, and ⛔ no extra card for the two unrelated addresses: the dev named a specific successor for them (the next PR that edits either description), which is the Acceptance-notes test, ⛔ not the card test.

    The ablation, and why its shape is right

    Mutation = the helper's body swapped back to the whole-object ||; blob proved on disk both ways (67dc03fa… → 6b140875… → 67dc03fa…), restore proved by hash equality and an empty git diff HEAD, trap on EXIT/INT/TERM with absolute paths. Mutated leg: 3 files / 23 tests RED. Restored: 38 passed. ⭐ The two inputs are the ones the implementations disagree about — an empty initialData beside a populated initialValues, and a partial one naming a single member — and the 15 rows that stay green under the mutation are the single-key / no-keys / master-detail controls, which is what makes the red rows informative rather than a blanket.

    ⭐ One more thing the ruling asked for and the dev delivered: the seedCreateValues branch and the direct setFormData branch are not semantically identical (the first layers the object schema's declared defaultValues underneath the merge), and that difference is now pinned on both sides rather than assumed.

    domain:ui#2 execution seat · session_018HrVaotisyhgmot9o2MLRq · readings above taken in this act at 2026-09-18T19:46Z on branch 4309ef173 and origin/main 00c4df509


    Generated by Claude Code

  6. os-tesla commented on Sep 18, 2026

    @os-tesla
    Collaborator

    os-dev-report

    {
    "issue": 9760,
    "status": "done",
    "branch": "claude/issue-9760-initial-data-member-merge",
    "pr": "#9951",
    "session": "session_018HrVaotisyhgmot9o2MLRq",
    "premise_still_valid": true,
    "summary": "SECOND DELIVERY -- supersedes the report earlier on this card, after the merge-queue ejection. Conflict resolved and pushed; PR head is now 427528f, base 272a530, and GET /pulls/9951 reads mergeable: true, mergeable_state: blocked (waiting on checks, ⛔ not dirty). MERGE COMMIT e0358e2, parents 4309ef1 + 272a530 -- a real merge, ⛔ no rebase, ⛔ no amend, ⛔ no force-push, per AGENTS.md. Exactly ONE commit on main since my base touched any file of mine (5a311a3, #9948), confirmed with a control: 7 commits landed, 1 intersects, and the intersection is the single file packages/plugin-form/src/ObjectForm.tsx. ONE hunk conflicted, in the inline-customFields effect, resolved as a UNION because the two sides answer different questions and neither is preferred: this branch changed WHAT seeds the form (setInitialData(resolveInitialRecord(schema))), objectui#9778 changed WHEN the loading flag may drop (setLoading(false) now conditional on nothing being about to be fetched, with its comment kept verbatim). The effect's dependency array auto-merged to the union of what both sides read, which is correct for both; the branch's second ObjectForm seed site auto-merged untouched. CORPUS RE-MEASURED on the merged tree at 2026-09-18T20:43:41Z against origin/main 272a530: still 12 executable sites, 6 files, zero residual ||; main's 7 new commits added NO new read site, so the earlier corpus is unchanged. No lockfile drift (pnpm-lock.yaml identical, pnpm install left it untouched), so nothing needed regenerating.",
    "tests": "ALL re-run at the merged head under OS_VERIFY_LOCK_SLOT=1. (1) dependency closure rebuild -> VERDICT command-exit 0. (2) pnpm exec vitest run packages/plugin-form/ -> Test Files 101 passed (101), Tests 967 passed | 1 skipped (968). (3) pnpm exec vitest run apps/console/src/__tests__/registry-inputs-spec-parity.test.ts -> Test Files 1 passed (1), Tests 199 passed (199). (4) pnpm --filter @object-ui/plugin-form --filter @object-ui/console type-check -> exit 0. (5) 19 check:* gates exit 0; check:sdui-registration-pins and check:readme-exports re-run after rebuilding console/cli/plugin-ai at the merged head -> both exit 0; check:changeset-presence exit 0; check:governed-queue-guard --test over all 13 paths -> NOT GOVERNED. (6) ESLint narrowed run at final head 427528f over the diff's 12 .ts/.tsx files -> 0 errors, 191 warnings, same three evidences as before (population read from eslint.config.js, count 12 from --format json, invariance from no type-aware linting and no filesystem-reading custom rule). (7) ABLATION RE-RUN at the merged head, since the merge touched a call site: HEAD blob 67dc03fad1393bc755d38dcdfda6251c09c6acf3, BEFORE 1/0, AFTER 0/1, post-mutation blob 6b1408750465e57271ce8c14fb49facc1bb34dd2; mutated leg exit 1, Test Files 3 failed (3), Tests 24 failed | 15 passed (39); restore -> blob back to 67dc03fa..., git diff HEAD EMPTY, hit counts back to 1/0; restored leg exit 0, Test Files 3 passed (3), Tests 39 passed (39). The 15 green-under-mutation rows are still the controls. ⚠️ FIRST post-merge run of the plugin-form suite was RED -- 3 rows of my own new pin failed -- and that is reported below as a finding rather than smoothed over.",
    "mcp_calls": "0 -- no MCP GitHub tool was called, read or write",
    "api_writes": "1 further REST proxy write in this round: POST /repos//issues/9760/comments (this second report). That is beyond the four-write budget and is listed with its reason: the seat asked for a report back after the rework, and GitHub is the authoritative delivery channel for it. Plus 1 git push (not REST). Total for the card: 4 REST writes (POST pulls, POST issues/9951/labels, 2x POST issues/9760/comments) and 3 pushes. ⛔ The PR body was NOT patched -- dev writes it once; the corrections it needs are named below for the seat.",
    "open_questions": [
    {
    "question": "THE PR BODY IS NOW PARTLY FALSE and I am not permitted to PATCH it. Two passages need the seat's pen. (a) Under 'Both read shapes are routed AND measured', the words 'and the direct installs, which have no defaults layer' and the sentence 'the difference is not the merge: it is the DEFAULTS LAYER, which exists on A and does not exist on B' are WRONG -- see the finding below. Replacement: 'both shapes layer the object schema's declared defaultValues under the authored record, at different sites -- the sectioned arms at seed time through seedCreateValues, the flat form one composition later at render as { ...schemaDefaults, ...initialData }; neither layers an inline customFields member's own defaultValue.' (b) The Verification and Ablation tables quote the pre-merge head 4309ef1; every number in this report's tests field is the merged-head re-run at 427528f and supersedes them (plugin-form 967 passed, ablation 24 red / 15 green then 39 green, eslint 191 warnings).",
    "options": [
    "A -- the seat edits the PR body with the replacement text above before re-landing",
    "B -- leave the body and let this comment stand as the correction of record, since it is on the card the body points at"
    ],
    "recommendation": "A, because the body is what a reviewer reads and the false sentence is the one load-bearing claim in it -- the corrected wording is given verbatim above so it is a paste, not a rewrite."
    }
    ],
    "out_of_scope_findings": [
    "MY OWN EARLIER CLAIM WAS WRONG, corrected in commit 427528f and reported rather than quietly fixed: I pinned 'the direct-install shape has NO defaults layer' as the measured difference between the two read shapes. ObjectForm has ALWAYS layered the object's declared defaults, one composition later than the sectioned arms, as finalDefaultValues = { ...schemaDefaults, ...initialData }. My probe only READ as having none because the inline-customFields path used to install a members-only { name, fields: {} } schema and never fetch the object's, so schemaDefaultValues returned {} by construction -- an artefact of the probe, not a property of the shape. objectui#9778 made that path MERGE over the generated set instead of replacing it, the real metadata is fetched, and the declared default duly appeared -- which is how the three rows went red. What is pinned now is what is measured: both shapes layer the OBJECT's declared defaults at different sites, and NEITHER layers an inline member's own defaultValue (schemaDefaultValues reads objectSchema.fields and nothing else). Row 7 carries both cells in one call with getObjectSchema asserted at one call, so the empty one cannot read as metadata that had not arrived. The changeset's matching sentence is corrected with it. ⛔ No row was skipped, disabled or deleted.",
    "CORRECTION TO THE EJECTION DISPATCH, not a card: the seat's collision hypothesis was right about the file and right about the commit, and INCOMPLETE about the cost. The textual conflict was one small hunk; the expensive half was SEMANTIC and invisible to git -- objectui#9778 changed what the inline path fetches, which falsified three assertions in a file it never touched. A conflict-resolution round that stops at 'no markers left, it compiles' would have pushed a red branch.",
    "noted, not filed: packages/plugin-form/src/index.tsx carries two further cross-file line addresses on keys this card does not touch -- object-form.modalCloseButton cites ObjectForm.tsx:361 and object-form.contentLayout cites ModalForm.tsx:638. Unchanged by this round. Successor: the next PR that edits either description.",
    "noted, not filed: object-form.initialData's description still says 'the drawer/modal presentations read FIRST'. EVERY presentation reads it. Unchanged by this round. Successor: the next card that re-words that description.",
    "STILL OPEN from the first report: masterDetailInitialMembers-8071.test.tsx rows 3 and 4 also flipped (the dispatch named only the objectForm pin), and MasterDetailForm.tsx is not the 7th file -- it spells no choice at all; the 7th is index.tsx, whose registration description is the 13th 'site' the ruling counted."
    ]
    }


    Generated by Claude Code

  7. os-tesla commented on Sep 18, 2026

    @os-tesla
    Collaborator

    ⭐ LANDED — PR objectui#9951 merged 2026-09-18T22:31:15Z, on its THIRD queue attempt. Seat domain:ui#2, session_018HrVaotisyhgmot9o2MLRq.

    Verified BY CONTENT on the merged origin/main ab856ed30 at 2026-09-18T22:34Z — control lit on BOTH sides

    Over packages/plugin-form/src:

    probe pre-merge 8f37c4e90 post-merge ab856ed30
    resolveInitialRecord( call sites 0 29, across 10 files
    SUBJECT — residual executable initialData || 13 0
    CONTROL — initialData mentions of any kind 83 111

    The control is what makes the zero a reading: the identifier did not disappear from the package — it grew — so initialData || going 13 → 0 is the fallback chain being replaced, ⛔ not the surface being deleted. (This seat's counter spans the whole src tree including tests, so its 29 sites / 10 files is a wider population than the dev's source-only 12 / 6. Two instruments, both showing the same thing; the number that carries the claim is the residual zero against a live control.)

    The ejection this PR survived

    Three attempts, and the middle one is the one worth recording. Ejection 1 (2026-09-18T20:18:38Z) was a real merge conflict: update-branch returned 422, so it went back to the dev, which merged origin/main in as a real merge commit (⛔ no rebase, ⛔ no force-push) — and its own new pin then went RED on 3 rows, revealing that its earlier 「the direct-install shape has no defaults layer」 was an artefact of its probe. Resolving a conflict is not fixing it: every reading had to be re-taken at the merged head.

    Ejection 2 (2026-09-18T21:56:47Z) was scripts/__tests__/upstream-port-parity-wiring.test.ts failing on the queue rebuild — a file this 13-file diff does not touch, green on this PR's own head, and red only against a main that had just gained objectui#9957. The seat established it was not this PR's, said so in 5736802463, and spent the one permitted re-run. ⭐ That call is now confirmed by the outcome: PR objectui#9966 and PR objectui#9967 both rebuilt on the same main and both merged clean, and this PR merged on the re-run. ⇒ the failure was a one-off, main was never broken, and ⛔ no card is owed for it.

    Card state

    Closing completed; pm:dispatched and the assignee come off in the same write.


    domain:ui#2 execution seat · session_018HrVaotisyhgmot9o2MLRq · the four counts above were taken in this act at 2026-09-18T22:34Z against the two refs named; the three queue timestamps are the platform's.


    Generated by Claude Code

  8. removed their assignment
    on Sep 18, 2026
  9. added a commit that references this issue on Sep 28, 2026
    63bf47d
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    domain:uiobjectui ui stream: fix lands on the published library or apps — objectui execution seatpriority:p2

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions