Skip to content

feat(app-shell): the Studio item header says where a read-only base’s customization is saved - #29843

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

objectstack-fleet[bot] merged 7 commits into
mainfrom
claude/project-thread-pkn482

Conversation

@objectstack-fleet

Copy link
Copy Markdown
Contributor

Requested by Steedos · project thread

Fixes #29691

Clause-②: yes (widening)
Metadata-protocol: none

维护者速读

  • 改了什么:Studio 条目标题栏在标题行下方、标签页上方多一行小字「保存到 基座名 的定制」,与待发布变更面板(PR 1,feat(app-shell): fold the .custom pair's landing card under its base and name the base on the pending-changes sheet #29723)同一句话、同一个文案键。出现在 Interfaces(定制包新增、已覆盖或已点「定制」解锁的条目)、Data(定制包新增的对象,或已有定制扩展的基座对象)、Automations(定制包新增、已覆盖或已解锁的流程)。Access 不变,它的标签已写明基座。
  • 为什么改:定制只读软件包时,标题栏只说「定制」,不说改动存到哪里;面板说了,标题栏没说(ADR-0146 D3)。
  • 风险与回滚:仅 UI,无新文案键;这一行在标题行之外,Studio: an item header keeps the item name readable; chips and tools collapse first #29693 的折叠只量标题行,不受影响(有消融测试)。回滚即还原本 PR,无数据或协议变化。
  • 先看:StudioItemHeader.tsx 的 note 槽位(标题行之后);新文件 preview/savedToCustomization.tsx(这句话与 SavedToCustomizationNote,DraftChangesPanel 改为转出);StudioDesignSurface.tsx 三处 note= 的显示条件。
  • 两分钟验证:在 showcase 打开任一视图,点「定制」,标题下出现「Saved to ObjectStack Showcase’s customizations」;改一处再点 Publish,面板标题下是同一句话。可写软件包的条目没有这一行。
  • 需要你做的:无,席位落地。

What changes

  • Item header note (ADR-0146 D3). StudioItemHeader takes an optional note. It is one line under the title row and above the tabs, outside the title row, so the objectstack#29693 fold (which measures only that row) never counts it.
  • One sentence, in its own module. savedToCustomizationText (from PR 1, feat(app-shell): fold the .custom pair's landing card under its base and name the base on the pending-changes sheet #29723) moves to preview/savedToCustomization.tsx, next to a new SavedToCustomizationNote element. DraftChangesPanel imports it and re-exports it, so its public export is unchanged. The header and the pending-changes sheet say the same words from the same key (preview.changes.savedToCustomization), and no key is added. The move is needed because many Studio tests replace the whole DraftChangesPanel module with a stub. When the header imported the note from that module, 7 tests in oneSurface-28572 and kernelReadOnly-29567 crashed with "No SavedToCustomizationNote export is defined on the mock". The header now does not depend on what such a stub exports.
  • Where it shows (StudioDesignSurface.tsx), only on a read-only base with a customization:
    • Interfaces: an item the pair adds, an item the pair overrides, or one unlocked by Customize.
    • Data: an object the pair adds, or a base object the pair's extension already extends (published, drafted or edited).
    • Automations: a flow the pair adds, a flow the pair overrides, or one unlocked by Customize.
    • The label is the base's (customization.baseLabel). On Data, packageId names the pair for a pair's own object, so it is not used.
  • Not changed: Access, whose chip already names the base; the publish toast; DraftChangesPanel.test.tsx.

Contract review

  • What widens: @object-ui/app-shell gains an optional StudioItemHeader prop (note) and a source module preview/savedToCustomization.tsx exporting SavedToCustomizationNote and savedToCustomizationText. DraftChangesPanel still exports savedToCustomizationText.
  • What narrows: nothing. No key, prop, export or accepted value is removed or tightened. Metadata authors see no change (Metadata-protocol: none).

Tests

  • StudioItemHeader.titleRowFold-12897.test.tsx: a new describe over the stubbed-geometry harness. The note is the title row's next sibling and is not inside it, with the tab row after it. A 400 px note, wider than the room the row leaves, folds nothing at 632 px. The row still folds at 330 px and unfolds at 480 px with the note there. CONTROL: no note, no line.
  • StudioDesignSurface.customizePublish-28562.test.tsx (the real surface): after Customize, the Interfaces header says "Saved to HotCRM’s customizations" outside the title row, and still does after the first edit makes the pair. The header line and the sheet line read the same. CONTROL: before Customize, no line.
  • DataPillar.baseObjectExtension-28575.test.tsx (the real pillar): the first Add field makes the extension and the object header says it; a base object the published extension extends says it on open. CONTROLS: a base object with no extension, and a writable package's object, say nothing.
  • AutomationsPillar.customizeFlow-28570.test.tsx (the real pillar): Customize unlocks the flow and the header says it; a published override says it on open. CONTROLS: the base's flow before Customize, and a writable package's flow, say nothing.
  • On the same-text check: this harness stubs the sheet (DraftChangesPanel). The stub now draws its line with the real savedToCustomizationText, using the label the host hands it. The pin compares the real header element with the sentence the real sheet draws from that label. DraftChangesPanel.test.tsx from PR 1 pins the real sheet's own line.

Verification

Tests and gates (code head a3d4ffd; head e2d07e0 only rewords the changeset, and its changeset gates exit 0)
  • Red on main, green here. I ran the four touched test files against origin/main 339f63da's StudioItemHeader.tsx, DraftChangesPanel.tsx and StudioDesignSurface.tsx, keeping the new helper module the test imports, and restored HEAD after. Result: 6 failed, 52 passed. The 6 are the new surface and header pins, and every CONTROL stays green on main. On the branch: 58 passed.
  • Ablation. Moving the note inside the title row (the row's last child) reds 3 of the 4 note cases in the fold describe: the own-line case, "a note wider than the free room folds nothing" and the follow-the-row case. CONTROL stays green. Restored after.
  • Sweep: every ui test file naming StudioItemHeader, DraftChangesPanel, StudioDesignSurface, DataPillar, AutomationsPillar, InterfacesPillar or savedToCustomization (284 files, in six locked batches, five of them with src/preview/ whole alongside), all green on a3d4ffd1: 358 + 701 + 528 + 509 + 655 + 800 tests. An earlier sweep on 6e6a5f34 was what caught the 7 crashes the module move fixes.
  • Type check: turbo run type-check --filter=@object-ui/app-shell: 65 of 65 tasks green.
  • eslint on the touched source and test files: 0 errors. The one new warning is react-refresh's only-export-components on savedToCustomizationText in the new module, the same warning that export carried in DraftChangesPanel.
  • Derived gates (node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack): 35 commands, each exit 0 on a3d4ffd1, including check-sdui-manifest, check-changeset-no-major, check-adr-0087-registration, check-closing-keyword-parity (run against this body) and pnpm --dir ui exec vitest run scripts/.
  • Not run locally: the full Test UI shards, which CI's Test UI runs, and a live browser pass.

Generated by Claude Code

…and name the base on the pending-changes sheet

Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QsR2jTWKHRdA5msPPhwmw4
…tion is saved

ADR-0146 D3: Interfaces, Data and Automations headers draw the pending-changes
sheet's sentence, "Saved to BASE's customizations", on a note line under the
title row, outside the fold's measured row. Access is unchanged.

Fixes objectstack#29691 (PR 2 of 2).

Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QsR2jTWKHRdA5msPPhwmw4
…odule

Studio tests that replace the whole DraftChangesPanel module with a stub
crashed once the item header imported the note from it. The sentence and its
note element now live in preview/savedToCustomization.tsx, which no stub
replaces; DraftChangesPanel re-exports savedToCustomizationText.

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

Copy link
Copy Markdown
Contributor Author

domain:ui#1 · zhuangjianguo · session_01QsR2jUJ19MstFvFhjgiYTu

Contract review

Served-tier: TIER_DEFAULT
Head-sha: e2d07e05964a5941daa1292dcc9eedd442f7357f
Local-runs: none

① Derived judgments

  • StudioItemHeaderProps gains an optional note?: React.ReactNode. When it is absent, nothing is rendered (the line is behind note &&), so every existing call site renders as before. The line sits after the title-row div closes and before the tabs nav, outside titleRowRef, so the Studio: an item header keeps the item name readable; chips and tools collapse first #29693 fold's measured row is unchanged. Additive, correct.
  • New module preview/savedToCustomization.tsx: savedToCustomizationText moves here unchanged (same key, same package value, same en defaultValue), plus the new SavedToCustomizationNote element. DraftChangesPanel.tsx re-exports savedToCustomizationText, so PR 1's (feat(app-shell): fold the .custom pair's landing card under its base and name the base on the pending-changes sheet #29723) export keeps its name, signature and output. Neither module is re-exported from the @object-ui/app-shell entry (exports has only . and ./styles.css, and src/index.ts names neither). The widening is internal to the package, so the yes (widening) line over-declares rather than under-declares.
  • StudioDesignSurface.tsx passes note at three header call sites, each behind customization !== null plus the pillar's own "edits go to the pair" condition: Interfaces (currentAddedIn, headerCustomize.inPair, headerUnlocked), Data (addedIn, or an open extension with published fields, a draft or unsaved edits) and Automations (addedIn, flowInPair, flowUnlocked). This is behaviour, not a contract face. Access is left as it is, as claimed.
  • No i18n key is added, renamed or removed. Nothing narrows: no prop, export, key or accepted value is removed or tightened.

② Semver level

The changeset declares '@object-ui/app-shell': patch with Clause-②: yes (widening) and Metadata-protocol: none. AGENTS.md Post-Task step 3 says a non-protocol change, widening or breaking, ships patch, and none takes patch. The level matches the declaration.

③ Boundary flags

  • One file outside the pre-code amendment: preview/savedToCustomization.tsx. The dev reported it in report 6597610452, and the seat accepted it in amendment 6597629664. Two unclaimed suites stub the whole DraftChangesPanel module, so the split keeps the header off that stub, and neither suite is edited.
  • The same-text pin compares the header note with the sheet stub's line, which customizePublish-28562 draws from the real savedToCustomizationText. It shows the header and the sheet share one function, not that the real sheet renders it (PR 1's DraftChangesPanel.test.tsx pins that).

Implemented-by: claude/project-thread-pkn482
Reviewed-by: session_01QsR2jUJ19MstFvFhjgiYTu

VERDICT: PASS

@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

domain:ui#1 · zhuangjianguo · session_01QsR2jUJ19MstFvFhjgiYTu

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

Head-sha: e2d07e05964a5941daa1292dcc9eedd442f7357f

  • Shape:
    • The PR is a draft against main. Its first card line is Fixes #29691. It is PR 2 of the card: PR 1 (feat(app-shell): fold the .custom pair's landing card under its base and name the base on the pending-changes sheet #29723, Part of) landed as 7f328cda. Covered by claim 6593455602 and amendments 6596316060 and 6597629664.
    • 9 files, +288 / −14:
      • StudioItemHeader.tsx (+12), the note slot
      • the new preview/savedToCustomization.tsx (+30)
      • DraftChangesPanel.tsx (+5 / −10), now re-exporting the moved function
      • StudioDesignSurface.tsx (+27), three call sites
      • four test files: the header fold suite and three pillar pair harnesses
      • a changeset
    • That is the amended surface. check-governed-merges --pr 29843: not governed, 302 changed lines, under the human-merge threshold.
    • Clause-②: yes (widening) and Metadata-protocol: none start their lines in the body and the changeset. @object-ui/app-shell is patch.
  • Contract review: record 6597647521 on this head, declaration face, TIER_DEFAULT, PASS.
  • Read in the diff:
    • The note line renders only when note is passed. It sits outside titleRowRef, between the title row and the tabs, so the Studio: an item header keeps the item name readable; chips and tools collapse first #29693 fold measures the same row as before.
    • Each pillar passes it only behind customization !== null and that item's own "edits go to the pair" test. Interfaces checks added by the pair, in the pair, or unlocked. Data checks an added object or an extension with published fields, a draft or dirty edits. Automations checks added, in the pair, or unlocked.
    • The sentence is PR 1's key through the same function. No i18n key changes.
  • Pins changed: none weakened. The four touched suites each gain a describe or case, and their existing assertions are untouched.
  • Gates (check-runs on this head): 44 success, 11 skipped, 0 failed or pending. Lint & Repo Gates and TypeScript Type Check both succeed. mergeable_state is clean.
  • Tests (dev, report 6597610452):
    • Red on main, with the three sources at main: 6 failed and 52 passed. The 6 are the Interfaces pin, two Data pins, two Automations pins, and the header's own-line pin. Every CONTROL is green.
    • Ablation: moving the note inside the title row reds 3 of the 4 fold-describe cases, and the CONTROL stays green.
    • The same-text case checks that the header note equals the sheet line drawn from the real function.
    • Derived gates 35 of 35, type-check 65 of 65, a 284-file sweep green.
  • NOT MEASURED: no live Studio session. All four pins run in jsdom over the real surface with a fetch stub.
  • Findings: none new. Access is left as it is on purpose, because its status chip already names the base (Studio Access: a New similar copy of a permission set reads "0 objects granted" in its pair, though the server holds its grants #29674).
  • Serial: none open. Seat 4's feat(app-shell): a Studio item header keeps the item name readable; chips, tools and labels give way first #29765 has landed.
  • Landing: ordinary queue landing, pr_ready then automerge_enable. Fixes #29691 closes the card on merge. pm:dispatched comes off with the landing note.

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/m tooling

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Studio: name where a customization is saved on the surface that made it, and stop listing the .custom pair as its own landing card

1 participant