Repository navigation
feat(studio): customize a read-only package's dataset in the All metadata area, see what uses it before publishing, and read a refused publish at the dataset - #30224
Merged
objectstack-fleet[bot] merged 5 commits intoNov 5, 2026
Conversation
…etadata area, with what uses it and its publish refusal at the item (#30064) Claude-Session: https://claude.ai/code/session_01QSeKYnE9YNkSZen7sijLA3 Co-authored-by: Claude <noreply@anthropic.com>
… used-by list, its publish refusal, and the references read (#30064) Claude-Session: https://claude.ai/code/session_01QSeKYnE9YNkSZen7sijLA3 Co-authored-by: Claude <noreply@anthropic.com>
…udio-dataset-customize
#30064) Claude-Session: https://claude.ai/code/session_01QSeKYnE9YNkSZen7sijLA3 Co-authored-by: Claude <noreply@anthropic.com>
…aReference fields and the references() narrowing (#30064) Claude-Session: https://claude.ai/code/session_01QSeKYnE9YNkSZen7sijLA3 Co-authored-by: Claude <noreply@anthropic.com>
Contributor
Author
|
domain:ui#2 · os-justin · session_01QSeKYnE9YNkSZen7sijLA3 维护者速读
席位意见:ACCEPT。dev 浏览器实测 710,000 → 177,500 → 恢复 710,000。 席位核对
|
objectstack-fleet
Bot
deleted the
claude/issue-30064-studio-dataset-customize
branch
November 5, 2026 03:14
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.
domain:ui#2 · os-justin · session_01QSeKYnE9YNkSZen7sijLA3
Fixes #30064
Clause-②: yes (widening)
Metadata-protocol: none
维护者速读
BASE.custom并声明overrides: { package, basedOn },顶栏「发布」生效,覆盖标记里的「恢复软件包原版」撤销。编辑器上方列出用到这个数据集的仪表盘、报表等(来自 引用关系 读取),发布被拒时原因按控制台语言显示在数据集编辑器里,并定位到具体度量和输入项。@object-ui/app-shell、@object-ui/data-objectstack、@object-ui/i18n),没有服务端或 spec 改动。可写包里的数据集仍走原来的通用条目页。顺带修了一个已发布缺陷:MetadataClient.references()读的是服务端从不返回的items键,Setup 的「引用关系」页和 Studio 条目工具对每个条目都显示「未找到引用,可以安全删除」;现在按声明的{ references: [...] }解析,读不懂的答复算读取失败。回滚 = revert 本 PR。ui/packages/data-objectstack/src/metadata-client.ts的references()(引用读取的修复,影响 Setup 引用页);②ui/packages/app-shell/src/views/studio-design/StudioBundleItemEditor.tsx的StudioBundleUsedBy与设计器挂载(Designer分支、blocking拦截自动保存);③metadataError.ts的datasetMemberLocator。pnpm --dir ui exec vitest run packages/app-shell/src/views/studio-design/StudioBundleItemEditor.customize-28569.test.tsx packages/data-objectstack/src/metadata-client.references-30064.test.ts,预期 16 例全绿(其中 10 例是本卡新增)。What changes
metadataArea.tsgainsAREA_CUSTOMIZE_EDITOR_TYPES(dataset): on a READ-ONLY package the All metadata area opens a dataset in its form editor (StudioBundleItemEditor), the same editor that customizes an email template or a translation.areaItemOpensFormEditortakes the area'sreadOnlygate; on a writable package a dataset still opens the generic item page, as on Setup's.datasetisoverridableinOVERRIDE_TYPE_CLASSIFICATION(dataset: listedre-checked on the base).DatasetDefaultInspector, beside its registeredDatasetPreview. Its shallow patch is applied to the buffer, and a blocking issue it reports (a dimension with no field) holds the autosave, as the generic page does. Email templates and translations register none, so they are unchanged.BASE.customdeclaringoverrides: { package, basedOn }(overrideDraftBody); the header's Publish publishes the pair; the override mark's popover offers "Restore package original". A note before the first save says the whole dataset is copied.client.references, the item tools' 引用关系). A failed read says it failed and offers Retry; it never reads as "nothing uses it". No new server read.GET /meta/:type/:name/referencesserves{ references: [{ type, name, label?, path, kind }] }bare (FindReferencesToMetaResponseSchema);MetadataClient.references()readdata.items, which the route never serves, so it returned[]for every item and both panels said "Safe to delete". It now parses the declared answer and maps each element toMetadataReference(fromType,fromName, new optionalfromLabelandkind); an answer the declaration refuses throws. Measured on the CRM example before the fix: the route answered the Pipeline Dashboard foropportunity_metrics, and the reader dropped it.publishLocatorgainsdatasetMemberLocator: an issue undermeasures.Nordimensions.Nis placed on that member by its label and on the designer's input (Not published. Check Aggregate of the measure "Total Amount": Details say what to change./ 「未发布。请检查度量「总金额」的「聚合方式」」). The surface hands the area its kept refusals (publishRefusalFor), and the editor shows the one for its item, as the Pending changes entry does. The server's text stays under Details, verbatim (Studio publish refusals: shown only as a ~4 s toast with engine-internal text; the Pending changes panel keeps no refusal; "Show me" does not focus the offending input and the dashboard/report refusal strip has no "Show me" #26730's rule).Why
field: expected_revenuewas refused:expected_revenueis aformulafield, and the authoring gate'smeasure-aggregate-field-type-refusedrefusessum/avgover a formula field (virtual, no stored column; its hint: store the value as a number field and aggregate that). Acceptance 6: no server or spec change was needed.Tests
StudioBundleItemEditor.customize-28569.test.tsx(the editor's shared harness), new describe "Customize a read-only base's dataset (objectstack#30064)", 6 cases: designer read-only before Customize, the whole-dataset note, the used-by list deduplicated per item; Customize + an edit write the whole dataset into the pair, declared, base untouched; a blocking report holds the edit unsent; a failed references read says so and Retry reads again; an empty answer says nothing uses it; a kept publish refusal shows at the item with Details.metadata-client.references-30064.test.ts(new, 4 cases): the fixture is the declared shape; mapping with and without a label; the honest empty answer; an off-contract answer throws.metadataError.publishRefusal-26730.test.ts, new describe (2 cases): the measured formula refusal placed on the measure's Aggregate in zh, engine text kept out of the sentence; a dimension named by its name; a path under no member left unplaced.metadataArea.test.ts, new describe (3 cases): dataset opens the editor only on a read-only package; the editor's exceptions kept; email template and translation unchanged.Test runs (head aefff1f unless noted)
pnpm --dir ui exec vitest run packages/app-shell/src/views/studio-design/→Test Files 324 passed (324)·Tests 2412 passed (2412); lockVERDICT command-exit 0.pnpm --dir ui exec vitest run packages/data-objectstack/ packages/i18n/ packages/app-shell/src/views/item-tools/ packages/app-shell/src/views/metadata-admin/ResourceEditPage.references packages/app-shell/src/views/metadata-admin/inspectors/DatasetDefaultInspectoron 66709ce → 1 red:studio-namespace.test.tsplaceholder parity (usedByOneen had no{count}); fixed in aefff1f, thenpnpm --dir ui exec vitest run packages/i18n/→Test Files 95 passed (95)·Tests 1443 passed | 13 skipped.pnpm --filter @object-ui/data-objectstack --filter @object-ui/i18n --filter @object-ui/app-shell run type-check→ all threeDone, lockVERDICT command-exit 0(after building the app-shell dependency closure with declarations).node scripts/ablation-replace.mjs, committed head):blocked: !editable || restoring || blocking > 0,→blocked: !editable || restoring,— anchor 1 → 0, blob 8500a768 → 53bc7c49; "holds an edit the designer reports as blocking"×,Tests 1 failed; restored blob == HEAD,git diff HEADempty.fromType: ref.type,→fromType: ref.kind,— anchor 1 → 0; "maps each served reference …"×,Tests 1 failed | 3 passed; restored blob == HEAD../metadata-client,./StudioBundleItemEditor), not a builtdist/.Acceptance notes
MetadataReference, exported from the@object-ui/data-objectstackentry, gains two optional fields:MetadataReference.fromLabel(the referring item's label, when served) andMetadataReference.kind(the served reference kind). The same diff narrows whatMetadataClient.references()accepts: a 200 answerFindReferencesToMetaResponseSchemarefuses now throws instead of resolving[](a non-2xx answer already threw). Every caller in this repository reads it throughuseReferencesScan(ui/packages/app-shell/src/views/item-tools/ReferencesPanel.tsx), whosecatchsets theerrorarm, and none calls it bare: Setup's item page (ResourceEditPage.tsx, the References sheet) and Studio's item tools (StudioItemTools.tsx, the References sheet) both renderReferencesPanel's error arm on the throw, therefsErrorTitle/refsErrorDescsentences (the check did not finish, nothing said about deleting), the cause, and Retry, with no count badge; the new used-by list (StudioBundleItemEditor.tsx,StudioBundleUsedBy) showsusedByErrorwith Retry. Callers in other repositories were not read.[]. Evidence: the route's answer foropportunity_metricson the CRM example was{"references":[{"type":"dashboard","name":"pipeline_dashboard","label":"Pipeline Dashboard","path":"widgets[].dataset","kind":"dashboard dataset"}]}, and the reader tookdata?.items ?? []. The same fix changes what Setup's References tab and Studio's item tools show for every type.useDatasetUsage); the new list is the references read. Two reads of one fact sit on the page; they agreed in the browser check. Not changed here.Verification
Browser check on the CRM example (
objectstack dev --fresh, own port) with the Console's Vite dev server on its own port, Chromium, locale zh-CN. Screenshots are in the dev's scratchpad, not uploaded.Steps and readings
/studio/com.example.crm/metadata/dataset/opportunity_metrics: designer read-only, 定制 in the header, the whole-dataset note, 「发布后,这里的修改会影响基于此数据集的 1 项:Pipeline Dashboard 仪表板」.total_amount) 聚合方式 求和 → 平均值: status 未发布草稿, mark 覆盖 CRM (minimal example); the pair's draft read back withoverrides: {"package":"com.example.crm","basedOn":"4.0.0"}and all three measures.GET /packages/com.example.crm/customizationslists{"type":"dataset","name":"opportunity_metrics","basedOn":"4.0.0"}. Dashboard 在途商机总额 710,000 → ¥177,500.expected_revenue, formula), 发布: Pending changes entry and the dataset editor both read 「未发布。请检查度量「总金额」的「聚合方式」:详情中说明了需要修改的内容。」, Details holds the gate's line.Gates (local, head aefff1f)
node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstackderived 35 commands; every one exited 0 (check-adr-0087-registration,check-changeset-no-major,check-closing-keyword-parity,check-comment-mask-corpus,check-empty-changeset,check-sdui-manifestand--self-test,check:nul-bytes,check:published-files,check:type-check-coverage,check:type-check-debt,check:undeclared-dep-imports,check:test-source-alias,check:cross-package-test-inputs,pnpm --dir ui exec vitest run scripts/(Test Files 170 passed | 2 skipped) and the rest).--ranreconciliation:35 derived famil(ies) accounted for — 35 run, 0 NOT-MEASURED (a DERIVED zero — all 35 recorded an exit code and none of them is 3).ui/scripts/check-new-cross-file-line-citations.mjs:0 new citation(s). The type-check lanes and the wide-population families are CI's.Generated by Claude Code