Skip to content

Reorganize plugin-object docs into subdirectory structure with component-specific pages - #166

Merged
hotlong merged 2 commits into
mainfrom
copilot/expand-subdirectory-introduction
Jan 23, 2026
Merged

hotlong merged 2 commits into
mainfrom
copilot/expand-subdirectory-introduction

Conversation

Copilot AI commented Jan 23, 2026 •

Copy link
Copy Markdown
Contributor

The plugin-object documentation was a single monolithic file. Restructured into subdirectory with dedicated pages for each component (ObjectTable, ObjectForm, ObjectView) for better discoverability and navigation.

Structure Changes

  • Created /content/docs/plugins/plugin-object/ subdirectory
  • Split monolithic plugin-object.mdx into:
    • index.mdx - Plugin overview with component links
    • object-table.mdx - ObjectTable component reference
    • object-form.mdx - ObjectForm component reference (create/edit modes)
    • object-view.mdx - ObjectView component reference (list/detail/edit views)
    • meta.json - Navigation metadata

Content Organization

Each component page includes:

  • Interactive demos
  • Usage examples (React + JSON schema)
  • Property reference tables
  • Advanced configuration patterns
  • Cross-component navigation links

Navigation now follows same pattern as /content/docs/components/ subdirectories (basic, form, layout, etc.)

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • fonts.googleapis.com
    • Triggering command: /usr/local/bin/node node /home/REDACTED/work/objectui/objectui/apps/site/node_modules/.bin/../next/dist/bin/next build git /next celain --ignore-submodules | head -n 10 credential.helper modules/.bin/node (dns block)

If you need me to access, download, or install something from one of these locations, you can either:

Original prompt

plugin-object 文档应展开子目录介绍每个控件


✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.

@vercel

vercel Bot commented Jan 23, 2026

Copy link
Copy Markdown

Deployment failed with the following error:

Resource is limited - try again in 3 hours (more than 100, code: "api-deployments-free-per-day").

Learn More: https://vercel.com/xuyushun441-sys-projects?upgradeToPro=build-rate-limit

Co-authored-by: hotlong <50353452+hotlong@users.noreply.github.com>
@vercel

vercel Bot commented Jan 23, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Review Updated (UTC)
objectui-site Ready Ready Preview, Comment Jan 23, 2026 2:06pm

Request Review

@vercel

vercel Bot commented Jan 23, 2026

Copy link
Copy Markdown

Deployment failed with the following error:

Resource is limited - try again in 2 hours (more than 100, code: "api-deployments-free-per-day").

Learn More: https://vercel.com/xuyushun441-sys-projects?upgradeToPro=build-rate-limit

Copilot AI changed the title [WIP] Add subdirectory documentation for each control in plugin-object Reorganize plugin-object docs into subdirectory structure with component-specific pages Jan 23, 2026
Copilot AI requested a review from hotlong January 23, 2026 14:09
@hotlong
hotlong marked this pull request as ready for review January 23, 2026 14:46
Copilot AI review requested due to automatic review settings January 23, 2026 14:47
@hotlong
hotlong merged commit 9c80f06 into main Jan 23, 2026
13 of 15 checks passed
@github-actions

Copy link
Copy Markdown
Contributor

✅ All checks passed!

  • ✅ Type check passed
  • ✅ Tests passed
  • ✅ Lint check completed

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Restructures the plugin-object documentation from a single MDX file into a dedicated subdirectory with an overview page and component-specific reference pages, improving navigation and discoverability.

Changes:

  • Replaced content/docs/plugins/plugin-object.mdx with a content/docs/plugins/plugin-object/ directory.
  • Added index.mdx plus dedicated docs pages for ObjectTable, ObjectForm, and ObjectView.
  • Introduced meta.json to define sidebar/navigation ordering within the new directory.

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 22 comments.

Show a summary per file
File Description
content/docs/plugins/plugin-object/index.mdx New plugin overview page linking to component pages; includes install/config/type examples.
content/docs/plugins/plugin-object/object-table.mdx New ObjectTable reference page with demo, examples, and API table.
content/docs/plugins/plugin-object/object-form.mdx New ObjectForm reference page with demo, examples (create/edit), and API table.
content/docs/plugins/plugin-object/object-view.mdx New ObjectView reference page with demo, examples, and API table.
content/docs/plugins/plugin-object/meta.json Adds navigation metadata for the new plugin-object subdirectory.
content/docs/plugins/plugin-object.mdx Removes the prior monolithic plugin-object documentation page.

Comment on lines +106 to +110
"onSuccess": {
"type": "navigate",
"path": "/contacts"
}
}

Copilot AI Jan 23, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same issue in the edit-mode JSON example: onSuccess is documented as a navigate action object, but ObjectForm expects a callback function. As written, this config will not work with the current implementation.

Copilot uses AI. Check for mistakes.
Comment on lines +230 to +236
"fields": ["email", "password", "confirm_password"],
"validation": {
"confirm_password": {
"match": "password",
"message": "Passwords must match"
}
}

Copilot AI Jan 23, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Top-level validation is not part of ObjectFormSchema. Validation is specified per field via FormField.validation (see packages/types/src/form.ts). Please update this example accordingly.

Suggested change
"fields": ["email", "password", "confirm_password"],
"validation": {
"confirm_password": {
"match": "password",
"message": "Passwords must match"
}
}
"customFields": [
{
"name": "email",
"type": "email",
"label": "Email",
"required": true
},
{
"name": "password",
"type": "password",
"label": "Password",
"required": true
},
{
"name": "confirm_password",
"type": "password",
"label": "Confirm Password",
"required": true,
"validation": {
"match": "password",
"message": "Passwords must match"
}
}
]

Copilot uses AI. Check for mistakes.
const tableSchema: ObjectTableSchema = {
type: 'object-table',
objectName: 'users',
columns: ['name', 'email', 'role'],

Copilot AI Jan 23, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In this TypeScript example, ObjectTableSchema doesn’t have columns: string[] for selecting which object fields to show. Use fields?: string[] for field selection, and reserve columns?: TableColumn[] for detailed column configs (with accessorKey) per packages/types/src/objectql.ts.

Suggested change
columns: ['name', 'email', 'role'],
fields: ['name', 'email', 'role'],

Copilot uses AI. Check for mistakes.
Comment on lines +112 to +114
- [ObjectQL Integration](/docs/ecosystem/objectql)
- [Data Sources](/docs/concepts/data-source)
- [Plugin System Overview](/docs/concepts/plugins)

Copilot AI Jan 23, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These “Related Documentation” links appear to be broken in this repo’s docs tree (there is no /content/docs/ecosystem or /content/docs/concepts). Consider updating them to the existing guide pages (e.g. /docs/guide/data-source and /docs/guide/plugins) or adding the missing pages.

Suggested change
- [ObjectQL Integration](/docs/ecosystem/objectql)
- [Data Sources](/docs/concepts/data-source)
- [Plugin System Overview](/docs/concepts/plugins)
- [ObjectQL Integration](/docs/guide/data-source)
- [Data Sources](/docs/guide/data-source)
- [Plugin System Overview](/docs/guide/plugins)

Copilot uses AI. Check for mistakes.
Comment on lines +80 to +84
| `columns` | string[] | All fields | Columns to display |
| `filters` | object | `{}` | Default filters to apply |
| `pageSize` | number | `10` | Rows per page |
| `sortBy` | string | `'id'` | Default sort field |
| `sortOrder` | 'asc' \| 'desc' | `'asc'` | Default sort order |

Copilot AI Jan 23, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The documented properties here (columns, filters, sortBy, sortOrder, searchable) don’t match ObjectTableSchema (fields, defaultFilters, defaultSort, showSearch, etc.). Align this table with packages/types/src/objectql.ts to avoid misleading API docs.

Copilot uses AI. Check for mistakes.
Comment on lines +212 to +217
"fields": ["name", "type", "price", "subscription_interval"],
"fieldVisibility": {
"subscription_interval": {
"condition": "${data.type === 'subscription'}"
}
}

Copilot AI Jan 23, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fieldVisibility is not part of ObjectFormSchema. Conditional rendering is modeled per-field via FormField.condition (see packages/types/src/form.ts) and implemented in the form renderer. Please update this example to use condition on the relevant field(s).

Suggested change
"fields": ["name", "type", "price", "subscription_interval"],
"fieldVisibility": {
"subscription_interval": {
"condition": "${data.type === 'subscription'}"
}
}
"fields": [
"name",
"type",
"price",
{
"name": "subscription_interval",
"condition": "${data.type === 'subscription'}"
}
]

Copilot uses AI. Check for mistakes.
Comment on lines +66 to +69
"filters": {
"status": "active"
},
"pageSize": 20,

Copilot AI Jan 23, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ObjectTableSchema uses defaultFilters (not filters) for the initial query filter (see packages/types/src/objectql.ts and ObjectTable’s fetchData implementation). Update this JSON accordingly.

Copilot uses AI. Check for mistakes.
Comment on lines +58 to +62
objectName: 'users',
view: 'list',
listColumns: ['name', 'email', 'role', 'status'],
detailFields: ['name', 'email', 'role', 'status', 'created_at', 'updated_at'],
editFields: ['name', 'email', 'role', 'status']

Copilot AI Jan 23, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ObjectViewSchema does not support view, listColumns, detailFields, or editFields. The current ObjectView API is centered around layout, table (partial ObjectTableSchema), form (partial ObjectFormSchema), and operations (see packages/types/src/objectql.ts). Update this Basic Usage snippet to match the real schema.

Copilot uses AI. Check for mistakes.
Comment on lines +70 to +71
"sortBy": "created_at",
"sortOrder": "desc"

Copilot AI Jan 23, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ObjectTableSchema uses defaultSort: { field, order } rather than sortBy/sortOrder (see packages/types/src/objectql.ts). The current JSON keys won’t be applied by ObjectTable.

Copilot uses AI. Check for mistakes.
Comment on lines +35 to +42
options: ["Admin", "User", "Guest"],
required: true
},
{
name: "status",
label: "Status",
type: "select",
options: ["Active", "Inactive"],

Copilot AI Jan 23, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For select fields, FormField.options is SelectOption[] with { label, value } (see packages/types/src/form.ts). Using options: ["Admin", "User", ...] here doesn’t match the expected shape and is unlikely to render correctly.

Suggested change
options: ["Admin", "User", "Guest"],
required: true
},
{
name: "status",
label: "Status",
type: "select",
options: ["Active", "Inactive"],
options: [
{ label: "Admin", value: "admin" },
{ label: "User", value: "user" },
{ label: "Guest", value: "guest" }
],
required: true
},
{
name: "status",
label: "Status",
type: "select",
options: [
{ label: "Active", value: "active" },
{ label: "Inactive", value: "inactive" }
],

Copilot uses AI. Check for mistakes.
akarma-synetal pushed a commit to akarma-synetal/objectui that referenced this pull request Sep 28, 2026
…objectstack-ai#9951)

Fixes objectstack-ai#9760

`Clause-②: no`

Maintainer ruling, batch objectstack-ai#166 item 3, letter 甲: one shared helper
replaces the
whole-object `schema.initialData || schema.initialValues` at every read
site, so
`initialData` merges PER MEMBER over `initialValues` — exactly what its
published
description ("alternate spelling … read FIRST") says. The description's
promise is
unchanged; the code now keeps it.

## The corpus, measured rather than inherited

Base ref `00c4df509c09634650932070d08f1f27e2fa2857` (`origin/main`,
re-read
2026-09-18T19:10:03Z — identical to the tip the dispatch named). Probe
run
2026-09-18T19:10:56Z, repo-wide, printing lines rather than a count:

```
git grep -nE "initialData\s*\|\|" -- .
```

⇒ **12 EXECUTABLE sites in 6 files**, every one of them in
`packages/plugin-form/src`:

| file | sites | shape |
|---|---|---|
| `DrawerForm.tsx` | 2 | `seedCreateValues(...)` + `setFormData(... \|\|
{})` |
| `ModalForm.tsx` | 2 | same pair |
| `ObjectForm.tsx` | 2 | `setInitialData(... \|\| {})` twice — no
`seedCreateValues` on this arm |
| `SplitForm.tsx` | 2 | same pair as Drawer/Modal |
| `TabbedForm.tsx` | 1 | `seedCreateValues(...)` only |
| `WizardForm.tsx` | 3 | `seedCreateValues(...)` ×3 |

Every other hit the probe returned is prose: two `.changeset/` bodies,
one
`CHANGELOG.md` paragraph, four test docblocks, three `pins` ledger
strings in
`apps/console`, and `packages/plugin-form/src/index.tsx`'s registration
**description**.

### ⚠️ Where my number differs from the ruling's, stated plainly

The ruling says **13 sites across 7 files**. I measure **12 executable
sites across
6 files**. The two reconcile only if the registration description at
`packages/plugin-form/src/index.tsx` is counted as the 13th site and
that file as
the 7th — which is how the dispatch's own enumeration read it. On that
reading the
ruling's count is right and nothing is missing; on a code-only reading
it is 12/6.

**`MasterDetailForm.tsx` is NOT a site**, and the dispatch's candidate
for the 7th
file is wrong in a way worth recording. It never spells the choice: its
`parentSchema` memo copies `initialValues` and `initialData` key by key
onto an
`object-form`-shaped object rendered through a directly imported
`ObjectForm`, so
it inherits the repair rather than needing one. It is, as the dispatch
suspected, a
**producer of the empty object** — its expanded-row form authors
`initialData: expandedRow ?? {}` — but that producer needed no edit
either: with no
`initialValues` beside it, `{ ...{}, ...expandedRow }` and `expandedRow
|| ...` agree.
It is left untouched and its behaviour is pinned through the flipped pin
below.

## What changed

- **`packages/plugin-form/src/initialRecord.ts` (new).**
`resolveInitialRecord(schema)`
returns `{ ...(schema.initialValues ?? {}), ...(schema.initialData ??
{}) }` — always
a fresh plain object, never nullish, never either authored object by
reference.
- **All 12 sites route through it.** ⛔ No arm keeps the `||`; the
residual probe over
`packages/plugin-form/src/*.ts{,x}` returns prose only, with the
helper's own 12 call
  sites + 6 imports firing as the same-command control.
- **Both read shapes are routed AND measured.** The ruling said triage
had not verified
they are semantically identical. They are **not**, and the difference is
not the merge:
- the create branches spell `seedCreateValues(objectSchema,
resolveInitialRecord(schema), ctx)`,
which keeps the object schema's declared `defaultValue`s UNDERNEATH the
merge (objectui#4047);
- the direct installs spell `setFormData(resolveInitialRecord(schema))`
with nothing underneath.
`seedCreateValues` is `{ ...schemaDefaultValues(...), ...(initial ?? {})
}`, so handing it
`{}` where it used to get `undefined` is a no-op by construction — but
the DEFAULTS LAYER
is a real behavioural difference between the two shapes, and it is now
pinned on both sides
(rows 3 and 6 of the new file) so that "unifying" the arms by dropping
`seedCreateValues`
  goes red instead of silently un-fixing objectui#4047.
- **`objectui#9759`'s pin flips, ⛔ nothing deleted.** Rows 3 and 4 of
`objectFormInitialMembers-8071.test.tsx` now assert the merge, with the
reason written into
the file: they were written deliberately against the old behaviour by a
pins-only card.
- **⚠️ A SECOND pin flips, which this dispatch did not name.**
`masterDetailInitialMembers-8071.test.tsx` rows 3 and 4 record the same
two facts one layer
up, inherited through the `parentSchema` memo. They are flipped the same
way, with the same
reason recorded. Had they been left alone this branch would simply have
gone red.
- **Changeset** `@object-ui/plugin-form` **minor**, carrying the
behaviour note the ruling
  dictates.

### Two edits that go slightly beyond the ruling's letter — flagged, ⛔
not slipped in

1. **`index.tsx`'s two registration descriptions.** The ruling says the
description is
unchanged, and its PROMISE is: "alternate spelling … read FIRST" and
"prefer `initialValues`
in new schemas" are untouched. But both strings also QUOTED the
expression this change
deletes — `object-form.initialData` carried `` (`schema.initialData ||
schema.initialValues`) ``
and `object-master-detail-form.initialData` carried the cross-file line
address
`(MasterDetailForm.tsx:602)`. Shipping either would put authoring-facing
metadata in front of
users citing code that no longer exists. Only those two citations are
replaced, by the
per-member statement and by a content citation respectively. ⭐ The line
address was also
already false on its own terms: that address is a `console.warn` about
child-schema loading,
unrelated to either key — the AGENTS.md rule against cross-file line
addresses, repaired
opportunistically in a file this change touches anyway. If the seat
reads the ruling more
literally, reverting these two strings is a one-line revert each and
nothing else depends on them.
2. **`apps/console`'s member-pin ledger prose.** Three `pins` strings in
`registry-inputs-spec-parity.test.ts` describe the pin files this change
flips, and each says
the behaviour was "recorded … and handed back as a finding rather than
fixed". This change
makes those sentences false about the very files they cite, so they are
updated to describe
what is pinned now, naming the flip. Nothing mechanical reads that prose
— which is exactly
   why a stale one would never go red.

## Ablation — the fix's own pin proved able to fail

Mutation: `resolveInitialRecord`'s body swapped back to
`return schema?.initialData || schema?.initialValues || {};`, cast back
to the module's declared
return type (angle brackets are spelled out here because this body's
sanitizer eats tag-shaped fragments)
Anchored replacement with a hit-count assertion in both directions,
`trap ... EXIT INT TERM`
with absolute paths, restore via `git checkout HEAD -- ABSOLUTE_PATH`.
Run against commit
`4309ef173`.

```
HEAD blob for packages/plugin-form/src/initialRecord.ts = 67dc03f
pre-mutation working blob    = 67dc03f
BEFORE  merge-line hits: 1   whole-object-line hits: 0
AFTER   merge-line hits: 0   whole-object-line hits: 1
post-mutation working blob   = 6b1408750465e57271ce8c14fb49facc1bb34dd2
mutated-leg vitest exit = 1
 Test Files  3 failed (3)
      Tests  23 failed | 15 passed (38)
post-restore working blob    = 67dc03f
git diff HEAD after restore  = []
RESTORED merge-line hits: 1   whole-object-line hits: 0
restored-leg vitest exit = 0
 Test Files  3 passed (3)
      Tests  38 passed (38)
```

The restore leg is proved twice over — blob hash equality with the HEAD
blob AND an empty
`git diff HEAD` — and by the hit counts, not by the exit code of a step
that exits 0 when it
does nothing.

**The inputs the two implementations disagree about** are the only ones
the behavioural rows use:
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 controls — the
single-key rows, the no-keys rows, and the master-detail block's own
batch/edit rows — which is
what keeps the 23 reds from being a file that simply broke.

## Verification

Run through the shared seat lock (`OS_VERIFY_LOCK_SLOT=1`), from the
repo root.

| what | command | result |
|---|---|---|
| dependency closure | `pnpm --filter '@object-ui/plugin-form^...'
--filter '@object-ui/console^...' build` | exit 0 |
| plugin-form, whole package | `pnpm exec vitest run
packages/plugin-form/` | `Test Files 101 passed (101)` · `Tests 965
passed \| 1 skipped (966)` |
| console parity ledger | `pnpm exec vitest run
apps/console/src/__tests__/registry-inputs-spec-parity.test.ts` | `Test
Files 1 passed (1)` · `Tests 199 passed (199)` |
| typecheck | `pnpm --filter @object-ui/plugin-form --filter
@object-ui/console type-check` | exit 0 (plugin-form's `tsc -p
tsconfig.test.json` half covers the test files) |

Gates, each read from its own verdict line with the exit code captured
before any pipe:
`check:new-line-citations` · `check:control-bytes` ·
`check:unreferenced-sources` ·
`check:component-surface-parity` · `check:changeset-claims` ·
`check:pending-changeset-literals` ·
`check:test-path-roots` · `check:entry-guard` ·
`check:comment-mask-corpus` · `check:vi-mock-specifiers` ·
`check:vi-mock-inherit` · `check:vi-mock-override-shape` ·
`check:lint-rule-coverage` ·
`check:registry-bare-names` · `check:doc-types` · `check:prompt-keys` ·
`check:element-data-source-declaration` · `check:action-ref-convention`
· `check:shell-escape-residue` ·
`check:changeset-presence` — all exit 0.

`check:sdui-registration-pins` and `check:readme-exports` first returned
exit 2 and exit 1 with
PREREQUISITE-NOT-MET verdicts ("No console build to weigh", "type entry
not on disk"). Both were
re-run after building `@object-ui/console`, `@object-ui/cli` and
`@object-ui/plugin-ai` and both
then exit 0 — recorded because the first readings are ⛔ not failures and
⛔ not passes.

`check:governed-queue-guard --test` over all 13 changed paths: **NOT
GOVERNED**, 0 of 5 surfaces matched.

### Lint — a DECLARED narrowing, with the three things that make it a
measurement

Run at final head (`git rev-parse --short HEAD`: `4309ef173`), over
every `.ts`/`.tsx` file in the
diff: **0 errors, 190 warnings** (all
`@typescript-eslint/no-explicit-any` and
`react-refresh/only-export-components`, matching the surrounding code —
`ObjectFormSchema` itself
types both keys as a string-keyed record of `any`).

1. **The population is read from eslint's own config**, not guessed:
`eslint.config.js` applies its
TS block to `files: ['**/*.{ts,tsx}']` under one repo-root `ignores`
list.
2. **The file count is read from `--format json`**: 12 files linted —
every `.ts`/`.tsx` path in the diff.
3. **Invariance for untouched files**: no type-aware linting is
configured (no `projectService`, no
`project:`, no TS program in `languageOptions`), and no rule in
`eslint-rules/` reads the
filesystem (`grep -rnE "require\('fs'\)|from
'fs'|readFileSync|readdirSync|globSync"` over that
directory returns nothing, with a live control on the same directory in
the same command). Every
file's verdict is therefore computed from that file's own source alone ⇒
this diff cannot move the
verdict of a file it does not contain. The repo-wide run remains CI's.

## Acceptance notes — out of scope, 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 above,
but on unrelated keys — repairing them here would be the sweep the rule
forbids. Successor: the next
  PR that edits either description.
- `object-form.initialData`'s description still says "the drawer/modal
presentations read FIRST". Every
presentation reads it, including the flat `ObjectForm` — a pre-existing
narrowing this change neither
created nor widened, left alone because the ruling holds the
description's wording. Successor: the
  next card that re-words that description.

---
_Generated by [Claude
Code](https://claude.ai/code/session_018HrVaotisyhgmot9o2MLRq)_

---

## Seat correction, appended after the merge-queue ejection and the
rework

Written by the `domain:ui#2` execution seat at **2026-09-18T21:02Z**
(clock read by this write). A dev writes its PR body once and ⛔ never
PATCHes it, so the two repairs it named in its second report are made
here.

**(a) One load-bearing sentence in this body is FALSE and is replaced.**
Where it says the two read shapes differ because the direct installs
「have no defaults layer」, read instead:

> 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`.

⭐ The dev found this **itself**, and the way it found it is worth
keeping: after merging `origin/main` in, **three rows of its own new pin
went RED**. The 「no defaults layer」 reading had been an **artefact of
the probe** — the inline-customFields path used to install a
members-only `{ name, fields: {} }` schema and never fetch the object's,
so `schemaDefaultValues` returned `{}` by construction. objectui#9778
(merged into main after this branch was cut) made that path MERGE over
the generated set, the real metadata arrives, and the declared default
duly appeared. ⛔ No row was skipped, disabled or deleted; the pin and
the changeset now say what is measured.

**(b) Every number in this body's Verification and Ablation tables was
taken at the PRE-MERGE head `4309ef173`.** They are superseded by the
merged-head re-runs at `427528f15`, recorded in the second
`os-dev-report` on objectui#9760 (`5736125661`): `packages/plugin-form/`
967 passed | 1 skipped; the ablation 24 red / 15 green under mutation,
39 green restored; eslint 191 warnings, 0 errors.

⚠️ **A correction the seat owes on its own ejection dispatch:** it named
the colliding file and the colliding commit correctly and was
**incomplete about the cost** — the textual conflict was one small hunk,
and 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 round that
stopped at 「no markers left, it compiles」 would have pushed a red
branch.

---
_Generated by [Claude Code](https://claude.ai/code)_

---------

Co-authored-by: Claude <noreply@anthropic.com>

This branch was successfully deployed

1 active deployment
Preview – objectui-site — b3d86687 Deployed Jan 23, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants