Repository navigation
fix(app-shell): a create draft shows the spec seed's structural defaults before the first save (objectui#12866) - #12886
Merged
objectstack-fleet[bot] merged 3 commits intoOct 17, 2026
Conversation
…aults (objectui#12866) A new dataset's designer read Measures 0 before the first save while the save wrote the seed's `count` measure. The create page now folds the seed's structural defaults into its draft once the `/meta/types` entry arrives, only for keys the draft does not hold; the placeholder identity stays out through the same `seedStructuralDefaults` the save body uses. Co-authored-by: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XVp19E1MYUTFM3dnkwz8gB
…#12866) Co-authored-by: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XVp19E1MYUTFM3dnkwz8gB
…has one too (objectui#12866) The create draft now carries the seed's `count` measure from the start, so a new dataset's designer renders a measure row with its own Name textbox; the two page-level pins read the first one, the dataset's. Co-authored-by: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XVp19E1MYUTFM3dnkwz8gB
Contributor
✅ Console Performance Budget
The eager closure is every chunk the entry reaches through static imports — what the browser fetches and parses before the app renders. The entry chunk on its own is a small fraction of it. 📦 Bundle Size Report
Size Limits
|
This was referenced Oct 17, 2026
objectstack-fleet
Bot
deleted the
claude/issue-12866-create-draft-seed
branch
October 17, 2026 13:35
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #12866
Clause-②: no
What changed
A new dataset's designer read Measures 0 before the first save, while the save wrote the spec create seed's
countmeasure. The create page now puts the seed's STRUCTURAL defaults into its draft, so the designer shows before the first save what the save writes.createBody.ts: new exportedseedStructuralDefaults(seed), the seed minus its placeholder identity (seedPlaceholderKeys, objectui#12810).buildCreateModeBodynow calls it for its base instead of repeating the copy-and-delete inline. The save body is byte-for-byte what it was: same keys removed, same{ ...base, ...draft }spread, samecreateDefaultsfallback when the server sends no seed.ResourceEditPage.tsx: one effect in create mode. When the/meta/typesentry carries acreateSeed, it adds the seed's structural keys to the draft, once, and only for keys the draft does not hold yet. A type withcreateBuildBody(view) is not seeded. The values are copied (structuredClone), so the designer never patches the registry entry's own arrays.Where the seed becomes available (mechanism assumption A1, measured)
Async.
useMetadataTypesstarts withentries: []and fills them fromclient.listTypes()inside auseEffect, so the draft'suseStateinitializer always runs before the entry exists. The seeding is therefore on arrival, not at init. The effect also covers an entry that is already present at mount, which is how the existing page tests serve it.Why "keys the draft does not hold" is the rule:
buildCreateModeBodyspreads the draft over the seed, so a key the draft holds is saved from the draft, and an absent key is exactly the one the save fills from the seed. Adding only absent keys keeps the before-save view equal to the save body, and never overwrites anything the author (orcreateDefaults) set first.Tests
New:
ResourceEditPage.createDraftSeed-12866.test.tsx, through the realMetadataResourceEditPagewith the real dataset designer, over a realMetadataClienton an in-memory server. The type-registry hook can hold the entry back and release it, the way the live one arrives.countis shown before save; after naming the dataset and picking a base object, the saved body'smeasuresequals the seed's.labelis not displayed anywhere, and the seed's placeholder object appears nowhere on the page.countoverwrite).Two existing page-level pins (
ResourceEditPage.seedPlaceholder-12810.test.tsx,inspectors/DatasetDefaultInspector.firstPickKeepsCount-12848.test.tsx) queried the single textbox named Name. The seededcountrow now has a Name textbox of its own, so both now read the first one, which is the dataset's. Nothing they assert changed.Ablation, run with the fix committed, through
ablation-replace.mjs(anchor must hit, restore proven by blob hash):return): blob8f81c0af5620to7ef7355f8dc8, both (a) tests and (b) red, (c) green (it cannot fail when nothing is seeded). Restored: blob equals HEAD8f81c0af5620,git diff HEADempty.Gates (at
7e7a0b67fb)pnpm --workspace-concurrency=2 --filter '@object-ui/app-shell^...' build: exit 0.pnpm --filter @object-ui/app-shell type-check(tsc --noEmitandtsc -p tsconfig.test.json): exit 0.--listFilesOnlyconfirms the new test file is in the test project.packages/app-shell/src/views/metadata-admin/directory: 544 files, 6130 passed, 1 skipped, exit 0. A whole-packagepackages/app-shell/run was stopped after about 29 minutes with no output under--maxWorkers=1. It is declared to CI, not measured here.eslint --no-inline-configon the five changed files:ResourceEditPage.tsxhas 3 errors and 57 warnings, the same count as that file at the base commit (react-hooks/static-components, on lines this PR does not touch). The other four files have 0 errors and 0 warnings. The eslint config enables no type-aware linting, so this diff cannot change the verdict on any untouched file.check:phantom-deps,self-import,unreferenced-sources,doc-example-readers,handler-key-reads,side-effects-array,element-data-source-declaration,spec-symbols,action-forward-parity,designer-field-key-parity,icon-record-names,i18n-keys,i18n-drift,i18n-designer-parity,control-bytes,check-hand-rolled-comment-mask.mjs,check-changeset-fixed.mjs,check-changeset-presence.mjsandcheck:new-line-citationsall exit 0.check:spec-floors: exit 1, NOT MEASURED. Its five findings are allno-artifact(packages with no build output in this worktree, app-shell among them), not a floor verdict.Acceptance notes
createBuildBodynow shows its structural seed keys in the create draft. In each case the save already wrote these values. Examples: objectpluralLabel: New Objects(the label-to-plural derivation still replaces it as the author types a label), agentroleandinstructions, email templatesubjectandbodyHtml, tooldescription, mapping's samplefieldMappingrow, actiontypeandbody. Whether some of these are placeholders rather than structure is a question aboutseedPlaceholderKeys(objectui#12810), which this PR shares and does not change.ResourceEditPage.seedPlaceholder-12810.test.tsxstill says the object picker resetsmeasureson the first change. That has been out of date since objectui#12848 and is left as it is.The session URL is
https://claude.ai/code/session_01XVp19E1MYUTFM3dnkwz8gB.Generated by Claude Code