Skip to content

feat(studio): draw the nav entries, fields and flows other packages contribute to a base greyed, with the package - #29847

Merged
objectstack-fleet[bot] merged 4 commits into
mainfrom
claude/project-thread-n8giqs
Nov 3, 2026
Merged

objectstack-fleet[bot] merged 4 commits into
mainfrom
claude/project-thread-n8giqs

Conversation

@objectstack-fleet

Copy link
Copy Markdown
Contributor

Fixes #29786

Clause-②: no
Metadata-protocol: none

维护者速读

  • 改了什么:在只读的基础包上,Studio 现在会画出其他已安装包贡献给它的导航项、字段和流程:灰色、只读,并标注"来自 某包"。导航项放在它声明的分组下,分组未声明时放在顶层;字段在表单布局中原位标记(不再画第二份);流程放进其对象的分组。
  • 为什么改:此前 Studio 一项都不画,而运行中的应用全部显示;一个只被其他包填充的分组会显示"此包中没有项目",管理员在定制或卸载被扩展的基础包时看不到谁依赖它。
  • 风险与回滚:只改 Studio 绘制,不改 spec、服务端或任何请求(仍是同一个 customizations 读取)。可写包、没有贡献的基础包、贡献方自身的页面画法不变。回滚即还原本 PR。
  • 先看:ui/packages/app-shell/src/views/studio-design/contributionRows.ts(放置规则,纯函数),再看 StudioDesignSurface.tsx 三个 pillar 的接入。
  • 两分钟验证:pnpm --dir ui exec vitest run packages/app-shell/src/views/studio-design/contributionRows.test.ts packages/app-shell/src/views/studio-design/StudioDesignSurface.oneSurface-28572.test.tsx(27 项全绿);对照截图见下方 Verification。
  • 需要你做的:看一眼 Acceptance notes 里的三条后续候选(导航项只显示 id、Automations 计数、贡献方一侧文案),决定是否另开卡。

What changes

On a read-only base, Studio draws the items other installed packages contribute to it, from the contributions of the base's one customization read (GET /api/v1/packages/:id/customizations). That is the read the rails' marks already make, so no request is added and nothing is joined on names in the browser. Each item is greyed, read-only, labelled "from PACKAGE", and a click opens the contributing package (through the shell's unsaved-edits seam).

  • One reader. usePackageCustomizations now also names each contributing package from the package list, by id, as it already names the base. contributionRows.ts (new, pure) splits the read by kind and holds the placement rules.
  • Interfaces. A nav entry for the open app draws under the group it names when the app declares a type: 'group' item of that id at any depth (the question the server's navigation fold asks), and at the top level otherwise. An entry naming an undeclared group says so in its tooltip. A declared group holding only contributed rows no longer says "No items in this package". The row reads the item's id (the served entry carries no label). The row is never in the nav edit buffer, so it cannot be dragged, renamed or deleted.
  • Data. A contributed field is already served on the base's object (the engine merges every extension), so it was drawn before, unmarked. The Form layout now marks that same card ("from PACKAGE", greyed, title) instead of drawing a second copy. It takes no drag listener and opens read-only in the inspector, even where the pair could write a base field's display properties.
  • Automations. A contributed flow draws in its object's rail group. An object with no flow of the base's gets a group of its own, before "No object".
  • Strings. Five keys in the studio namespace, en and zh (engine.studio.contributed.*).

Tests

  • contributionRows.test.ts (new, 9): split by kind and package naming, declared group at depth, top level and undeclared group, other app left out, a non-group item sharing the id is no container, fields per object, flow groups joined or added before "No object".
  • StudioDesignSurface.oneSurface-28572.test.tsx (+6): Interfaces group, top-level and undeclared placement; a nav row opens the contributor; CONTROL: an empty declared group still says "No items" when nothing is contributed; Data card marked once, not aria-disabled, inspector read-only while the base's own field is not; Automations group placement, a new group, no empty message, opens the contributor; no request to the contributing package.
  • Ablations, each red then restored (blob equals HEAD): group rows, top-level rows, findDeclaredNavGroup, the contributedFields prop, the rail read-only, flow rows, and useSortable disabled on a contributed card.

Acceptance notes

  • Nav rows show the id, not a label (seat ruling). The customization read's nav entry carries no label. Measured: the app list read the pillar already makes (GET /meta/app?package=) carries the folded navigation with labels. Using it would need a ruling on reading the fold, so no label is joined here.
  • Automations heading count stays the base's own (0 on the fixture), and the main pane still says "No automations in this package yet." A contributed flow is not the base's.
  • Contributor side: the contributing package's Interfaces pillar still reads "This package has no app yet." Its package-list row carries the raw manifest.navigationContributions (a declaration, not the fold). Left as is and reported (seat ruling).
  • Grid column headers on the Records tab are not marked: that grid is plugin-grid, outside this surface.
  • Strings are en and zh only. The studio namespace lives in ui/packages/i18n/src/namespaces/studio/, not in the ten locale packs the claim names; other languages fall back to en as the whole namespace does.
  • Screenshots came from examples/app-multi-package plus a temporary third package (a nav entry under an undeclared group, a field and a flow on crm_account). That package was never committed; the pins carry their own fixtures.

Verification

  • Pins: 27/27 on the final head. Type-check (turbo type-check app-shell + i18n), eslint on touched files: 0 errors.
  • Derived gates (dispatch-gates --commands): all exit 0; see the os-dev-report on the card.
  • Live, objectstack dev on app-multi-package plus the temporary package, Console via Vite. The base read lists 4 contributions (field acme_score, flow crm_acme_account_sync, nav nav_acme_portal under undeclared ghost_group, nav nav_orders under sales_group from the orders package). After: nav_orders under SALES and nav_acme_portal at the top level with the undeclared-group tooltip; the Acme score card marked once with the inspector read-only; crm_acme_account_sync in the ACCOUNT group. Before (601832b): none of the nav or flow rows, and the field card unmarked.
  • Before/after screenshots (Interfaces, Data form, Automations, plus rail crops, the field inspector and a phone-width Automations, and three side-by-side comparisons) are handed to the seat with this PR for attaching to the card.

🤖 Generated with Claude Code

https://claude.ai/code/session_01QsR2jQkUExPHsEsPoX99Uf


Generated by Claude Code

…ed, with the contributing package

Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QsR2jQkUExPHsEsPoX99Uf
A contributed field card drops only its drag listener, so it is not
announced as disabled while a click still selects it. A contributed rail
row draws the id over the package label, so a narrow rail shows both.

Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QsR2jQkUExPHsEsPoX99Uf
@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

domain:ui#4 · zhuangjianguo · session_01QsR2jR7ZFkpqmm4U8S1f9y

席位核对 · ACCEPT · 2026-11-03T07:40Z

Head-sha: ef7ae80600575b3e904156e76f7b124f3c32101e

  • Shape: draft → main, Fixes #29786 in the body only. 10 files, +905 / −35 (940 lines ≤ 3000; non-test +551 / −29). No governed path (check-governed-merges --pr 29847 on the final file list: 0 of 10 hit the register). Clause-②: no and Metadata-protocol: none are line-initial in the body and the changeset, so no review face applies and no contract review is owed. The PR reads a member the spec already serves (PR feat(runtime): the customizations read serves the nav contributions other packages add to a base's apps #29742).

  • Premise, measured: it holds. At 601832b1, no file under ui/ read contributions. The before screenshots show the base's Interfaces tree with only its own entry. The Data form showed the contributed field Acme score unmarked, because the served object already merges extensions. The Automations rail showed no contributed flow.

  • File surface: as claimed and ruled in amendment 6595791720. That covers the rails and their helpers (contributionRows.ts is new and pure), ObjectFormDesigner.tsx (the Data pillar's field cards), CustomizationMark.tsx, and the studio en and zh packs.

  • Read in the diff:

    • There is one read: the base's customization read, already in hand through the pillars' marks. Contributor names come from the listed packages by id. There is no second request and no join on names.
    • nav: entries draw under their declared group at any depth, otherwise at the top level with an undeclared-group tooltip. Each row shows its id and its package.
    • field: the field card the server already draws is marked once ("from PKG"). It takes no drag listener, and its inspector is read-only on the base.
    • flow: contributed flows draw in their object group, or in a new group placed before "No object".
  • Measured (screenshots under /mnt/project-files/issue-29786/shots/: 6 before at 601832b1, 7 after, 3 side by side):

    • app-multi-package was measured, plus a temporary third package that was never committed.
    • The seat read the Interfaces comparison: nav_orders from Multi-Package Orders and nav_acme_portal from Acme Add-on now draw greyed under Sales.
    • The seat read the Data form: Acme score is marked "from Acme Add-on" and greyed.
  • Accepted deviations: none beyond the plan's rulings. The nav row shows its id because the served entry has no label (ruled on the plan).

  • Out of scope (from the report, comment 6597892264):

    1. The nav label is available on the folded app list read, and needs a ruling → filed Studio: a contributed navigation entry shows its id, not its label, and a package that only contributes navigation reads "no app yet" #29851 (p3), together with item 2.
    2. A package that only contributes reads "This package has no app yet" → filed Studio: a contributed navigation entry shows its id, not its label, and a package that only contributes navigation reads "no app yet" #29851.
    3. The Automations heading count counts the base's own flows only → Acceptance notes. This is by design: the count is of the base's flows.
    4. The Records tab grid column headers do not mark contributed fields → dropped. The Records tab is the data grid (plugin-grid), not a design surface. The card scopes the Data pillar's field list, which is marked.

    Skills-docs: is not owed (Metadata-protocol: none, no narrowing arm).

  • Tests: 27 of 27 pins pass. The related sweep passes 353 files and 3,288 tests on the final head. 7 ablations went red and were restored. 35 of 35 derived gates exit 0; --ran reconciles with 0 NOT-MEASURED and 0 UNRUN. sdui-manifest, the PR-body gates and the ui i18n checks exit 0.

  • Gates (check-runs on this head): 44 success, 11 skipped (opt-in, path-filtered or matrix placeholders), 0 failed or pending, including all 16 Test UI shards and Live E2E UI. Every required context succeeded or was skipped by its path filter.

  • Landing: ordinary queue landing, pr_ready then automerge_enable. Fixes #29786 closes the card on merge.


Generated by Claude Code

@objectstack-fleet
objectstack-fleet Bot marked this pull request as ready for review November 3, 2026 07:42
@objectstack-fleet
objectstack-fleet Bot enabled auto-merge November 3, 2026 07:42
@objectstack-fleet
objectstack-fleet Bot added this pull request to the merge queue Nov 3, 2026
Merged via the queue into main with commit 2a0f0b7 Nov 3, 2026
56 checks passed
@objectstack-fleet
objectstack-fleet Bot deleted the claude/project-thread-n8giqs branch November 3, 2026 07:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation size/l tests tooling

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Studio: draw the items other packages contribute to a base (nav entries, fields, flows) greyed, with the contributing package

1 participant