Repository navigation
object-form:空的 initialData 会静默丢弃写满的 initialValues(整对象 ||,不是逐成员合并) #9760
Description
Activity
Ruling: batch #166 item 3 · 甲 (
initialDatamerges per member overinitialValues—{ ...initialValues, ...initialData }— exactly as its published description 「alternate spelling … read FIRST」 says; one shared helper replaces the whole-objectinitialData || initialValues || {}at all 13 sites across the 7 presentation arms in ONE change; the description is unchanged) · maintainer 「同意」 2026-09-18T14:45ZDirector seat, summon #24,
session_01Wj1HUjzyeiBQ8atRf1ZhaL. Presented in detail with the recommendation 甲; the maintainer agreed. Facts (this card; triage census 5730787177): both keys are declaredRecord<string, any>, so{}parses on both doors; the renderer picks the whole object with||, and{}is truthy — an emptyinitialDatahides a fullinitialValueswith no warning; the same spelling sits atObjectForm.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 controlinitialValues96 / 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||. TheseedCreateValues(...)branch and thesetFormData(... || {})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
initialDataleavesinitialValuesintact; a partialinitialDataoverrides only the members it names). - Changeset
@object-ui/plugin-formminor with the behaviour note: a page that used an empty or partialinitialDatato 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:p2stay. objectui#9886 closesduplicate_ofthis card (triage's evidence is here).Clause-②: no.
Generated by Claude Code
- One helper
Claim:thedomain:ui#2execution 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 ofbatch:3Declared 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/main00c4df509, read at 2026-09-18T19:22Z, printed ⛔ not counted: the whole-objectinitialData || initialValuesspelling 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 atindex.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:initialValueslines fire acrossapp-shell,plugin-designerand sixplugin-formfiles ⇒ 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 aboveTwo 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 secondClaim:was posted.
Generated by Claude Code
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-objectschema.initialData || schema.initialValuesat 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 buildpnpm --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 halftsc -p tsconfig.test.jsoncovers 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 viagit 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 HEADEMPTY, 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 2git 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 literalschema.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
Review verdict — objectui#9760 · PR objectui#9951 · branch
claude/issue-9760-initial-data-member-merge@4309ef173Implemented-by:os-dev subagent, dispatched by thedomain:ui#2execution seat (session_018HrVaotisyhgmot9o2MLRq)
Reviewed-by:thedomain:ui#2execution seat — ⛔ not a self-review of an authored diff; the seat writes no codeRe-taken at source by the seat, with a control in the SAME command
resolveInitialRecordis defined atpackages/plugin-form/src/initialRecord.ts:74and 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 increateDefaults.test.tsxand the helper's own docblock quoting the form it replaces. ⭐ Control, same probe onorigin/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.tsxis 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 itsparentSchemamemo and inherits the repair. The seventh file isindex.tsx, whose registration description is the ruling's thirteenth 「site」. - ⛔ The dispatch named only one pin to flip.
masterDetailInitialMembers-8071.test.tsxrows 3 and 4 record the same two facts one layer up and had to flip too — measured onmain, 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 addressMasterDetailForm.tsx:602, which the dev measured as already false (an unrelatedconsole.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:361andcontentLayout→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」, 「PreferinitialValuesin 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 emptygit diff HEAD,trapon 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 emptyinitialDatabeside a populatedinitialValues, 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
seedCreateValuesbranch and the directsetFormDatabranch are not semantically identical (the first layers the object schema's declareddefaultValuesunderneath the merge), and that difference is now pinned on both sides rather than assumed.domain:ui#2execution seat ·session_018HrVaotisyhgmot9o2MLRq· readings above taken in this act at 2026-09-18T19:46Z on branch4309ef173andorigin/main00c4df509
Generated by Claude Code
- ⛔
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 HEADEMPTY, 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 1git 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'stestsfield 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
⭐ 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/mainab856ed30at 2026-09-18T22:34Z — control lit on BOTH sidesOver
packages/plugin-form/src:probe pre-merge 8f37c4e90post-merge ab856ed30resolveInitialRecord(call sites0 29, across 10 files SUBJECT — residual executable initialData ||13 0 CONTROL — initialDatamentions of any kind83 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 wholesrctree 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-branchreturned 422, so it went back to the dev, which mergedorigin/mainin 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.tsfailing on the queue rebuild — a file this 13-file diff does not touch, green on this PR's own head, and red only against amainthat had just gained objectui#9957. The seat established it was not this PR's, said so in5736802463, 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 samemainand both merged clean, and this PR merged on the re-run. ⇒ the failure was a one-off,mainwas never broken, and ⛔ no card is owed for it.Card state
Closing
completed;pm:dispatchedand the assignee come off in the same write.
domain:ui#2execution 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
- added a commit that references this issue
on Sep 28, 2026
事实(实测于
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 分支)||测的是对象本身的真值,而{}为真。于是:initialValues: { customer: 'Alpha', note: 'X' }initialData: { customer: 'Beta' }+ 上面那份initialValuescustomer: 'Beta',note空 ——initialValues整份被丢弃initialData: {}+ 上面那份initialValues第三行是本卡要报的那一格:一个空的
initialData把一份写满的initialValues完全遮住,没有警告、没有降级、没有任何红。为什么这是陷阱而不是口味问题
两个键都注册为
{ type: 'object' },ObjectFormSchema把它们打成Record<string, any>—— 所以两侧声明都接受任何对象,{}在两侧都合法解析。initialData的 description 原话是「Alternate spelling ofinitialValuesthat 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 执行席立卡(sessionsession_01UanLVj6xvbS6puBCewLr8L)。待裁的那一问(留给分诊定级,本卡不代答)
现状(整对象
||)是不是要保的?三个方向,形状不同:||换成"有键才算数"的判据,initialData: {}退回initialValues。行为改动最小,但仍然不是合并。{ ...initialValues, ...initialData }—— 最贴近散文,但会改变已经在用两个键的既有元数据的行为。查重词:
initialData·initialValues·setInitialData·object-form 预填·whole-object ||Refs: objectui#8071 · objectui#9759 · objectui#8068
Generated by Claude Code