Skip to content

Commit 3c888c6

Browse files
revert(app-shell): roll back objectui#11931 and objectui#11932 so the console's eager closure is under its ceiling again (objectui#11937) (#11956)
Fixes #11937 Part of #11861 Rolls back objectui#11932 (objectui#11823, seat `domain:ui#3`) as well: measured necessary, see the report Clause-②: no `main` is red on `Bundle Analysis`: the console's eager closure is over its 3,386,364-byte gzip ceiling. This PR rolls back the two Studio changes whose strings pushed it over, so `main` returns to the tree of f1781be, which measured under the ceiling. The route is the seat's ruling A, under the maintainer's ruling 6056819248 step 1: `main` turns green by rollback or plugging, and the ceiling is not raised. Implemented by the os-dev agent of session `https://claude.ai/code/session_01MgfduSkFrfM3eorB3UGfAU` (seat `domain:ui#2`, claim comment 6056334737). ## What changed - `git revert -m 1 19a7348` (objectui#11931: Studio's validation "New" menu presets) and `git revert -m 1 f3a0488` (objectui#11932: Studio Interfaces' page create step), one commit each. - `.changeset/11937-eager-budget-rollback.md`, a patch for `@object-ui/app-shell`. The two rolled-back PRs' unreleased changesets are removed with them, so the next release does not announce what is not in it. - `git diff f1781be HEAD --stat` prints only `.changeset/11937-eager-budget-rollback.md | 5 +++++`. - Not touched: `MAX_EAGER_CLOSURE_GZIP_BYTES` and every other ceiling, `apps/console/vite.config.ts`, `.github/**`. ## Measurement These are local console builds (`CI=1 pnpm exec vite build` in `apps/console`, under the container's verify lock), read from `apps/console/dist/eager-closure.json`. The ceiling is 3,386,364 B. | tree | eager gzip bytes | vs ceiling | eager `i18n` chunk | |:--|--:|--:|--:| | f1781be (objectui#11929) | 3,385,951 | −413 | 104,156 | | 19a7348 (+ objectui#11931) | 3,386,368 | +4 | 104,569 | | f3a0488 (+ objectui#11932, `main`) | 3,386,819 | +455 | 105,029 | | f3a0488 − objectui#11931 only | 3,386,430 | +66 | 104,635 | | this PR (tree = f1781be + changeset) | 3,385,951 | −413 | 104,156 | - The 19a7348 and f3a0488 rows match CI's push runs to the 0.1 KB: 3307.0 KB, "0.0 KB over"; and 3307.4 KB, 0.4 KB over. - Almost all of the growth is in one eager chunk, `i18n-*.js`: +413 B from 11931 and +460 B from 11932. Every other eager chunk moved by 7 B or less, which is minifier and hash churn. - `chunk-membership.json` puts exactly one workspace module in that chunk: app-shell's designer string table, `views/metadata-admin/i18n.ts`. - 11931's code (the preset table and the panel) is only in the lazy `studioBuilder` chunk. Only its 12 table rows are eager. **Why rolling back 11931 alone is not enough, and why there is no leak to plug.** - objectui#11932 added its own rows to the same table. - The table's chunk is an automatic chunk. No `advancedChunks` group matches its path, so it is not a chunk-group leak. - 8 eager chunks import it statically: - the register-builtins inspector path, eager by design (ruling A 6054102412, objectui#6795's order): `apps/console/src/main.tsx` → `@object-ui/app-shell` → `views/metadata-admin/register-builtins.ts` → `inspectors/index.ts` → `inspectors/ObjectFieldInspector.tsx` → `metadata-admin/i18n.ts`; - runtime surfaces: `views/ViewConfigPanel.tsx` and `views/ReportConfigPanel.tsx` → `views/RuntimeDraftBar.tsx` → `metadata-admin/i18n.ts`. - Moving Studio-only rows out of that table is the lazy-loading step objectui#6795 orders second. That is objectui#11942, not this PR. ## Verification (head `b1e82226c`) - **Tests**, run under the lock with repo-root `pnpm exec vitest run --maxWorkers=2 FILES`. The set is 179 files: every test file that 11932's revert touches or that imports a module either revert changes (`interfaceCreate`, `StudioDesignSurface`, the metadata-admin i18n table), plus the remaining `ObjectValidationsPanel*` suites and `packages/core/src/utils/__tests__/column-identity.ratchet.test.ts`. batch 00: 'Test Files 44 passed (44)', 'Tests 489 passed (489)'; batch 01: 'Test Files 45 passed (45)', 'Tests 631 passed (631)'; batch 02: 'Test Files 45 passed (45)', 'Tests 221 passed (221)'; batch 03: 'Test Files 45 passed (45)', 'Tests 641 passed (641)'. Total 179 files and 1982 tests passed. - **Type-check:** `pnpm --filter @object-ui/app-shell run type-check` (`tsc --noEmit && tsc -p tsconfig.test.json`) exited 0. The dependency closure was built first (`--filter '@object-ui/app-shell^...' run build`, exit 0). - **Gates, all exit 0:** `check:i18n-keys`, `check:i18n-designer-parity`, `check:i18n-drift`, `check:unreferenced-sources`, `check-changeset-presence` ("this change declares 1 changeset(s)"), `check-changeset-no-major`, `check:changeset-claims`, `check:pending-changeset-literals`, `check-changeset-fixed`, `check:control-bytes`, `check:new-line-citations`. - **`check-changeset-overwrite`** is report-only. It lists the two removed changesets as its case 3, superseded in the same change. - **`pnpm exec eslint`** on the 8 touched source and test files: 0 errors and 19 react-hooks warnings. All 8 files are byte-identical to their f1781be blobs. - **No console build on this head**, as the PM directed: the tree is f1781be's. CI's `Bundle Analysis` on this PR re-measures. ## os-dev report ```json { "issue": 11937, "status": "done", "branch": "claude/issue-11937-eager-closure-main-red", "pr": "this pull request (draft; the relay forces draft)", "session": "session_01MgfduSkFrfM3eorB3UGfAU", "premise_still_valid": true, "summary": "Route A, as the seat ruled under the maintainer's ruling 6056819248 step 1. objectui#11931 (19a7348) and objectui#11932 (f3a0488) are rolled back with git revert -m 1, one commit each, and an app-shell patch changeset is added. The tree equals f1781be's except for that changeset, and f1781be's tree measured 3,385,951 eager gzip bytes, 413 under the 3,386,364 ceiling. Reverting 11931 alone measured 66 B over, because 11932 added its own rows to the same eager designer table. No ceiling, chunk config or workflow is touched.", "route": "(2) widened to A: reverting 11931 alone is insufficient (+66 B on f3a0488), and there is no leak for route (1). The designer table views/metadata-admin/i18n.ts is the only module in the automatic eager i18n chunk, and 8 eager chunks import it statically: the register-builtins inspector path (eager by design, ruling A 6054102412) and runtime surfaces (RuntimeDraftBar, RecordDetailView).", "tests": "Head b1e8222. Union of the test files that 11932's revert touches or that import a module either revert changes (git grep of interfaceCreate, StudioDesignSurface and the metadata-admin i18n table), plus the remaining ObjectValidationsPanel suites and packages/core/src/utils/__tests__/column-identity.ratchet.test.ts: 179 files, run in 4 batches under the lock with repo-root `pnpm exec vitest run --maxWorkers=2 FILES`: batch 00: 'Test Files 44 passed (44)', 'Tests 489 passed (489)'; batch 01: 'Test Files 45 passed (45)', 'Tests 631 passed (631)'; batch 02: 'Test Files 45 passed (45)', 'Tests 221 passed (221)'; batch 03: 'Test Files 45 passed (45)', 'Tests 641 passed (641)'. Total 179 files and 1982 tests passed. No ablation applies: the change is two reverts.", "gates": [ "app-shell type-check, `pnpm --filter @object-ui/app-shell run type-check` (echoes `tsc --noEmit && tsc -p tsconfig.test.json`) under the lock, after `pnpm --filter '@object-ui/app-shell^...' run build` (lock VERDICT command-exit 0): VERDICT command-exit 0.", "check:i18n-keys exit 0: 'Every in-scope call-site key resolves against the en pack (3304 keys), …'", "check:i18n-designer-parity exit 0: 'Every en row has a zh row, and every shared row carries the same placeholders.'", "check:i18n-drift exit 0: 'Every changed designer-table en value was followed by its zh row.'", "check:unreferenced-sources exit 0: 'OK Every shipped source file in every covered package is reachable.'", "check-changeset-presence exit 0: '11 source file(s) of 1 released package(s) changed, and this change declares 1 changeset(s): .changeset/11937-eager-budget-rollback.md.'", "check-changeset-no-major exit 0: 'No changeset declares a `major` bump.'", "check:changeset-claims exit 0: 'No pending changeset names a file this change touches.'", "check:pending-changeset-literals exit 0: 'No test source names a pending changeset.'", "check-changeset-fixed exit 0: 'privatePackages declared: version=true, tag=false.'", "check-changeset-overwrite exit 0, report-only: it lists the deletion of the two rolled-back PRs' unreleased changesets (11823-page-create.md, 11861-validation-presets.md). That is its case 3, superseded in the same change, and intended: the next release must not announce features that are not in it.", "check:control-bytes exit 0; check:new-line-citations exit 0 ('0 new citation(s)').", "eslint (`pnpm exec eslint --format json`) on the 8 touched .ts/.tsx files: exit 0, 0 errors, 19 warnings (react-hooks rules). Every file is byte-identical to its f1781be blob, so this PR adds none of them.", "Eager closure: no console build on this head, as the PM directed. The tree equals f1781be's (git diff f1781be HEAD --stat shows only the changeset), and f1781be's build measured 3,385,951 B (local `check:eager-closure` inputs, emit-eager-closure-report line '3385951 bytes gzipped (3306.6 KB)'). CI's Bundle Analysis on this PR re-measures.", "head: b1e8222 (git rev-parse --short HEAD after the last commit)." ], "files_changed": [ ".changeset/11937-eager-budget-rollback.md (added)", ".changeset/11861-validation-presets.md, .changeset/11823-page-create.md (deleted, the rolled-back PRs' unreleased changesets)", "content/docs/guide/console.md", "packages/app-shell/src/views/metadata-admin/i18n.ts", "packages/app-shell/src/views/studio-design/ObjectValidationsPanel.tsx, validationPresets.ts (deleted), ObjectValidationsPanel.presets-11861.test.tsx (deleted), ObjectValidationsPanel.test.tsx, ObjectValidationsPanel.newRuleWaits-11820.test.tsx, ObjectValidationsPanel.whenKey.test.tsx", "packages/app-shell/src/views/studio-design/StudioDesignSurface.tsx, interfaceCreate.tsx, interfaceCreate.test.tsx, StudioDesignSurface.interfacesCreatePage-11823.test.tsx (deleted)" ], "deviations": [ "The PR is a draft. The PM's correction says so, and the relay forces draft anyway.", "objectui#11932's files are outside the claim's file surface. The PM's message assigns recording that amendment to the seat.", "The two reverts are separate commits made with `git revert -m 1 --no-commit` and then `git commit -F -`, so that each carries the model-free trailer pair. Each tree is the plain revert's.", "There is no os-dev-report comment this round, because of the PM's write-budget instruction. The report is in this body and in the hand-back.", "Round 1, for the record: the blocked report comment 6056966795 on the card holds the full four-build measurement." ], "mcp_calls": "0", "api_writes": "this round: 1 pr_create (relay) + 1 label-write for the PR assignee, after the PR exists, recorded in the hand-back. Round 1: 1 comment (6056966795). Git pushes are not REST writes.", "open_questions": [], "out_of_scope_findings": [ "carrier: objectui#11942 (the seat's objectui#6795-order follow-up) · the eager designer-table chunk i18n-*.js weighs 105,029 B gz on f3a0488, about 3.1% of the eager closure, and every Studio-only row added to views/metadata-admin/i18n.ts lands in it eagerly · noted, not filed" ] } ``` --- _Generated by [Claude Code](https://claude.ai/code/session_01MgfduSkFrfM3eorB3UGfAU)_ --------- Co-authored-by: Claude <noreply@anthropic.com>
1 parent f3a0488 commit 3c888c6

15 files changed

Lines changed: 67 additions & 1396 deletions

‎.changeset/11823-page-create.md‎

Lines changed: 0 additions & 26 deletions
This file was deleted.

‎.changeset/11861-validation-presets.md‎

Lines changed: 0 additions & 19 deletions
This file was deleted.
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@object-ui/app-shell': patch
3+
---
4+
5+
The console is back under its first-load budget. Two recent Studio changes are rolled back to get there: the common-rule starting points in an object's Validations "New" menu (objectui#11931), and the Interfaces pillar's step that creates a page and opens it on its source with a live preview (objectui#11932). Their labels sat in a string table every console page loads, which pushed that first load over its limit. Studio behaves as it did before those two changes, and nothing else changes. Both come back once the first-load allowance tracked in objectui#11942 is in place.

‎content/docs/guide/console.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ entries — no code round-trip required:
4747

4848
| Tab | Edits | Panel |
4949
|-----|-------|-------|
50-
| **Validations** | the object's inline `validations[]` (spec `ValidationRuleSchema`) | Master-detail covering **every** rule type — `script`, `cross_field`, `state_machine`, `format`, `json_schema`, `conditional`. The **New** menu opens on common rules in plain words (*End date on or after start date*, *Number can't be negative*, *Reject the save when…*); each writes a working rule, or waits for the condition the author gives. Every rule type is under **Advanced**. A new rule whose type carries a condition (`script`, `cross_field`, `conditional`) is saved only once it has one; a rule's type can still be switched in place. CEL predicates reuse the shared `ConditionBuilder`, fed the object's draft fields. |
50+
| **Validations** | the object's inline `validations[]` (spec `ValidationRuleSchema`) | Master-detail covering **every** rule type — `script`, `cross_field`, `state_machine`, `format`, `json_schema`, `conditional`. The **New** menu adds any type (seeded with a valid, never-firing skeleton); a rule's type can be switched in place. CEL predicates reuse the shared `ConditionBuilder`, fed the object's draft fields. |
5151
| **Hooks** | the separate `hook` metadata type targeting this object | Master-detail whose editor is the platform `SchemaForm` **driven by the live `hook` JSONSchema from `/meta/types`**, so its fields and enums always match the running server's contract. |
5252
| **Actions** | the object's inline `actions[]` (spec `ActionSchema`) | Master-detail using the type-aware `ActionDefaultInspector`; anything not curated falls through to a **"More fields"** form fed the live `action` JSONSchema, so no spec property is un-editable. |
5353

‎packages/app-shell/src/views/metadata-admin/i18n.ts‎

Lines changed: 3 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -3088,19 +3088,6 @@ const ENGINE_STRINGS_EN: Record<string, string> = {
30883088
'engine.studio.rules.event.update': 'Update',
30893089
'engine.studio.rules.event.delete': 'Delete',
30903090
'engine.studio.rules.priority': 'Priority',
3091-
// objectui#11861 — the New menu's starting points, and the type list under Advanced.
3092-
'engine.studio.rules.presets': 'Common rules',
3093-
'engine.studio.rules.advanced': 'Advanced',
3094-
'engine.studio.rules.preset.endAfterStart': 'End date on or after start date',
3095-
'engine.studio.rules.preset.endAfterStartNeeds': 'Needs two date fields on this object.',
3096-
'engine.studio.rules.preset.endAfterStartMessage': '{end} must be on or after {start}.',
3097-
'engine.studio.rules.preset.notNegative': 'Number can’t be negative',
3098-
'engine.studio.rules.preset.notNegativeNeeds': 'Needs a number field on this object.',
3099-
'engine.studio.rules.preset.notNegativeMessage': '{field} can’t be negative.',
3100-
'engine.studio.rules.preset.rejectWhen': 'Reject the save when…',
3101-
'engine.studio.rules.preset.rejectWhenHint': 'Build your own condition, no code needed.',
3102-
'engine.studio.rules.preset.usesOne': 'Uses “{field}”.',
3103-
'engine.studio.rules.preset.usesTwo': 'Uses “{start}” and “{end}”.',
31043091
'engine.studio.settings.basics': 'Basics',
31053092
'engine.studio.settings.noInspector': 'No default object inspector registered.',
31063093
'engine.studio.settings.semanticRoles': 'Semantic roles',
@@ -3241,8 +3228,8 @@ const ENGINE_STRINGS_EN: Record<string, string> = {
32413228
'engine.studio.inspector.listView.addSort': '+ Add sort…',
32423229
'engine.studio.inspector.listView.sortAsc': '{field} ascending',
32433230
'engine.studio.inspector.listView.sortDesc': '{field} descending',
3244-
// objectui#11823 (steps 2 and 3) — the Interfaces pillar's New dashboard / New report / New page.
3245-
'engine.studio.interfaces.create.menuTitle': 'Create a dashboard, a report or a page in this package',
3231+
// objectui#11823 (step 2) — the Interfaces pillar's New dashboard / New report.
3232+
'engine.studio.interfaces.create.menuTitle': 'Create a dashboard or a report in this package',
32463233
'engine.studio.interfaces.create.dashboard': 'New dashboard',
32473234
'engine.studio.interfaces.create.report': 'New report',
32483235
'engine.studio.interfaces.create.description':
@@ -3269,20 +3256,6 @@ const ENGINE_STRINGS_EN: Record<string, string> = {
32693256
'engine.studio.interfaces.create.datasetsFailed': 'The datasets could not be loaded: {error}',
32703257
'engine.studio.interfaces.create.noMeasures': 'This dataset declares no measures, so a report cannot show it.',
32713258
'engine.studio.interfaces.create.needsBinding': 'Choose the dataset this report reads, and one of its measures.',
3272-
'engine.studio.interfaces.create.page': 'New page',
3273-
'engine.studio.interfaces.create.pageNameLabel': 'Page name',
3274-
'engine.studio.interfaces.create.pageNamePlaceholder': 'Page name (e.g. Team handbook)',
3275-
'engine.studio.interfaces.create.pageIdPlaceholder': 'Identifier (e.g. team_handbook)',
3276-
'engine.studio.interfaces.create.pageTaken':
3277-
'A page with the identifier “{name}” already exists. Choose another identifier.',
3278-
'engine.studio.interfaces.create.pageKind': 'Written in',
3279-
'engine.studio.interfaces.create.pageKindHtml': 'HTML',
3280-
'engine.studio.interfaces.create.pageKindReact': 'React',
3281-
'engine.studio.interfaces.create.pageKindHtmlHint':
3282-
'Built from the platform’s components and HTML tags, parsed and never run. The page opens on its source beside a live preview.',
3283-
'engine.studio.interfaces.create.pageKindReactHint':
3284-
'Real React code, run when the page renders, for state, effects and event handlers. The page opens on its source beside a live preview.',
3285-
'engine.studio.interfaces.create.pageStarter': 'A new page. Write its content in the source editor.',
32863259
'engine.studio.inspector.designersMissing':
32873260
'No metadata designers are registered in this session, so there is nothing to edit here.',
32883261
'engine.studio.inspector.noPageSchema': 'Page settings are unavailable — the page schema could not be loaded.',
@@ -6247,18 +6220,6 @@ const ENGINE_STRINGS_ZH: Record<string, string> = {
62476220
'engine.studio.rules.event.update': '更新',
62486221
'engine.studio.rules.event.delete': '删除',
62496222
'engine.studio.rules.priority': '优先级',
6250-
'engine.studio.rules.presets': '常用规则',
6251-
'engine.studio.rules.advanced': '高级',
6252-
'engine.studio.rules.preset.endAfterStart': '结束日期不早于开始日期',
6253-
'engine.studio.rules.preset.endAfterStartNeeds': '需要该对象有两个日期字段。',
6254-
'engine.studio.rules.preset.endAfterStartMessage': '{end}不能早于{start}。',
6255-
'engine.studio.rules.preset.notNegative': '数值不能为负',
6256-
'engine.studio.rules.preset.notNegativeNeeds': '需要该对象有一个数值字段。',
6257-
'engine.studio.rules.preset.notNegativeMessage': '{field}不能为负数。',
6258-
'engine.studio.rules.preset.rejectWhen': '满足条件时拒绝保存…',
6259-
'engine.studio.rules.preset.rejectWhenHint': '自行搭建条件,无需写代码。',
6260-
'engine.studio.rules.preset.usesOne': '使用「{field}」。',
6261-
'engine.studio.rules.preset.usesTwo': '使用「{start}」和「{end}」。',
62626223
'engine.studio.settings.basics': '基础信息',
62636224
'engine.studio.settings.noInspector': '未注册对象默认检查器。',
62646225
'engine.studio.settings.semanticRoles': '语义角色',
@@ -6369,7 +6330,7 @@ const ENGINE_STRINGS_ZH: Record<string, string> = {
63696330
'engine.studio.inspector.listView.sortAsc': '{field} 升序',
63706331
'engine.studio.inspector.listView.sortDesc': '{field} 降序',
63716332
// objectui#11823 (step 2) — the Interfaces pillar's New dashboard / New report.
6372-
'engine.studio.interfaces.create.menuTitle': '在本包中新建仪表盘、报表或页面',
6333+
'engine.studio.interfaces.create.menuTitle': '在本包中新建仪表盘或报表',
63736334
'engine.studio.interfaces.create.dashboard': '新建仪表盘',
63746335
'engine.studio.interfaces.create.report': '新建报表',
63756336
'engine.studio.interfaces.create.description': '存为本包的草稿,加入 {app} 的导航,并在画布上打开。',
@@ -6391,17 +6352,6 @@ const ENGINE_STRINGS_ZH: Record<string, string> = {
63916352
'engine.studio.interfaces.create.datasetsFailed': '无法加载数据集:{error}',
63926353
'engine.studio.interfaces.create.noMeasures': '这个数据集没有声明度量,报表无法展示它。',
63936354
'engine.studio.interfaces.create.needsBinding': '请选择这个报表读取的数据集,以及其中的一个度量。',
6394-
'engine.studio.interfaces.create.page': '新建页面',
6395-
'engine.studio.interfaces.create.pageNameLabel': '页面名称',
6396-
'engine.studio.interfaces.create.pageNamePlaceholder': '页面名称(如:团队手册)',
6397-
'engine.studio.interfaces.create.pageIdPlaceholder': '标识符(如:team_handbook)',
6398-
'engine.studio.interfaces.create.pageTaken': '已有标识为「{name}」的页面,请换一个标识。',
6399-
'engine.studio.interfaces.create.pageKind': '编写方式',
6400-
'engine.studio.interfaces.create.pageKindHtml': 'HTML',
6401-
'engine.studio.interfaces.create.pageKindReact': 'React',
6402-
'engine.studio.interfaces.create.pageKindHtmlHint': '由平台组件与 HTML 标签组成,只解析、不执行。页面打开时,源码与实时预览并排显示。',
6403-
'engine.studio.interfaces.create.pageKindReactHint': '真正的 React 代码,在页面渲染时运行,可使用状态、副作用与事件处理。页面打开时,源码与实时预览并排显示。',
6404-
'engine.studio.interfaces.create.pageStarter': '新页面。请在源码编辑器中编写它的内容。',
64056355
'engine.studio.inspector.designersMissing': '本次会话没有注册任何元数据设计器,这里没有可编辑的内容。',
64066356
'engine.studio.inspector.noPageSchema': '页面设置不可用——无法加载页面 schema。',
64076357
'engine.studio.inspector.sourcePageLine1': '这个页面是 {kind} 源码,不是积木树 ——',

‎packages/app-shell/src/views/studio-design/ObjectValidationsPanel.newRuleWaits-11820.test.tsx‎

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,8 +68,6 @@ function Harness({ onPatch, initial = baseDraft }: { onPatch: (p: Record<string,
6868

6969
function addFromMenu(label: string) {
7070
fireEvent.click(screen.getByText('New'));
71-
// The per-type list sits under Advanced since objectui#11861.
72-
fireEvent.click(screen.getByRole('button', { name: 'Advanced' }));
7371
fireEvent.click(screen.getByRole('button', { name: label }));
7472
}
7573

0 commit comments

Comments
 (0)