You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Studio: name where a customization is saved on the surface that made it, and stop listing the .custom pair as its own landing card #29691
Filing gate: ② filed on the maintainer's word in direct chat with the epic PM seat, 2026-11-03: 「同意立卡」, agreeing the four UX proposals with the direction written here. Priority on 「相关卡 p1, 让车道处理」. ⛔ Not a claim.
Reader: domain:ui.
Governs: ADR-0146 D3: "the package switcher folds hotcrm.custom under HotCRM instead of giving it a row".
Dedupe: landing custom pair card. New.
type: enhancement
Business reason. A person customizing a vendor's package cannot tell what happened to their edit. The header keeps saying read-only, while a package they never made appears on the landing.
What happens
Measured on main at 3482f3d8d2, on the showcase, zh-CN.
Customize an item of read-only com.example.showcase, or add a field. The header still reads 只读, and the switcher still names the base.
The sheet and toast say 已发布本软件包的 1 项; the sheet groups the change under object_extension.
/_console/studio lists a separate 可写 card for com.example.showcase.custom under 我的软件包. BuilderLanding.tsx:120 takes every writable package, and :308 draws them, with no pair filter.
Direction (agreed)
The landing does not give a pair its own card. The base's card keeps its "n customized" line and its link.
The item header and the pending-changes sheet carry one sentence, the same in both: 保存到 ObjectStack Showcase 的定制.
Check before removing: the pair's export and delete must stay reachable (D3 tells the administrator to export or delete .custom before uninstalling the base). Name where they live now. A review reports that the pair card's link returns to the base; that is unverified.
Read fresh. The .custom pair stops getting its own landing card, and the header and the pending-changes sheet name where a customization is saved (ADR-0146 D3).
p1 on the maintainer's word 「相关卡 p1, 让车道处理」.
The card's own check stands: the pair's export and delete must stay reachable before the card goes.
Claim: PM loop round 19 · 2026-11-03T01:58Z
Session: session_01QsR2jTWKHRdA5msPPhwmw4 (card thread, os-dev); dispatched by seat session session_01QsR2jUJ19MstFvFhjgiYTu
Account: zhuangjianguo
Branch: claude/project-thread-pkn482 (platform-assigned to the card thread; it can push only this branch)
Worktree: objectstack-issue-29691
Domain: domain:ui
Seat: domain:ui#1
File surface: PR 1 (Part of #29691): ui/packages/app-shell/src/views/studio-design/BuilderLanding.tsx (the writable list folds pairs with the existing foldCustomizationPairs: a pair whose base is listed draws no card, an orphan pair keeps its card) and BuilderLanding.customizationCounts-28566.test.tsx (its pair case updated), ui/packages/app-shell/src/views/studio-design/preview/DraftChangesPanel.tsx (an optional base-label prop drawing the new key) and preview/__tests__/DraftChangesPanel.test.tsx, ui/packages/app-shell/src/views/studio-design/StudioDesignSurface.tsx (one prop at the DraftChangesPanel call, set only when pairId is; no header call site) and StudioDesignSurface.customizePublish-28562.test.tsx (its stub draws the prop), the new key preview.changes.savedToCustomization in all ten packs under ui/packages/i18n/src/locales/, and a root .changeset (app-shell + i18n patch). The item-header sentence (PR 2, reusing the key) waits for seat 4's #29693 and is declared by a claim amendment before code. Any other file is declared by a claim amendment before code (stop on breach; explain in the report)
Container & model: M, mode:thread, model: default tier (dispatch-gates --tier: no path-derived mandate), effort: medium
Clause-②: yes (widening): one new i18n key in the published locale packs, nothing removed or narrowed
Metadata-protocol: none
Responsibility: the landing pair card and the pending-changes sheet sentence (PR 1); the item-header sentence after seat 4 #29693 (PR 2); toast unchanged
Thread-read: 6593426427
Premise: holds (at origin/main3d5933a9: the landing draws every writable package with no pair filter (BuilderLanding ~120/~308); the pair card opens /studio/PAIR/data which redirects to the base; the pair export and delete live on the Packages page detail sheet, not the landing card, and stay reachable)
Serial constraints cleared: PR 2 (item header) waits for seat 4 #29693, which reworks the StudioItemHeader row, and is cleared with seat 4 before code. No open PR touches BuilderLanding.tsx, DraftChangesPanel.tsx or StudioDesignSurface.tsx at claim time. Seats 2, 3 and 5 yielded this card (coordinator ruling 01:54Z).
{
"issue": 29691,
"status": "done",
"branch": "claude/project-thread-pkn482",
"pr": "https://github.com/objectstack-ai/objectstack/pull/29723",
"session": "session_01QsR2jTWKHRdA5msPPhwmw4",
"premise_still_valid": true,
"summary": "PR 1 of 2 (Part of #29691). The Studio landing folds each BASE.custom pair under its listed base with the switcher's foldCustomizationPairs, in both sections; the base card keeps its customized line and pair link, and an orphan pair keeps its card. DraftChangesPanel takes an optional customizationOf (the base label) and says under its title 'Saved to BASE's customizations' / 保存到 BASE 的定制 through one exported helper, savedToCustomizationText, for PR 2's header to reuse. StudioDesignSurface passes the base label only when pairId is set. New key preview.changes.savedToCustomization in all ten locale packs. Toast unchanged. Item header waits for #29693 (PR 2).",
"tests": "Red on main: the 3 touched test files with 1c1a5d40's BuilderLanding.tsx, DraftChangesPanel.tsx and StudioDesignSurface.tsx (blob-identical, restored, git diff HEAD empty): 7 failed / 24 passed, the 7 being the new pins, CONTROLs green. Branch: 3 files, 31 passed on d47495aa and on 62ad4a49. Sweep on d47495aa, locked, maxWorkers=2: 254 ui test files naming BuilderLanding or DraftChangesPanel or reading the locale packs, 6 batches all green (2810 tests); packages/i18n/ 95 files, 1443 passed, 13 skipped. turbo type-check app-shell + i18n 66/66. eslint: 0 errors. Ablation = main's BuilderLanding (no fold): red as above. Live, fresh showcase on d47495aa: ensure-customization 201 (com.example.showcase.custom, writable, source authored, listed as its own row); GET /packages/PAIR/export 200 with the pair manifest; DELETE /packages/PAIR 200, list then holds only the base.",
"gates": "node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack at d47495aa: 35 commands, every one exit 0 (incl. check-sdui-manifest, check-changeset-no-major, check-adr-0087-registration, check-closing-keyword-parity against the body, check-partof-closing-keyword, pnpm --dir ui exec vitest run scripts/ 170 passed 2 skipped). Merge of main (62ad4a49) brought no ui/ file. CI check-runs: in_progress at report time.",
"dogfood_battery": "n/a — no ! in the PR title and no (narrowing) arm",
"mcp_calls": "9 — issue_read x4 (29691 get/comments x2, 29693 get+comments), get_session x1 (claude-code-remote), plus ToolSearch loads; no GitHub MCP write",
"api_writes": "3 — git push x2 (branch, merge of main); pr_create via fleet-write dispatch.mjs (PR #29723); plus this os-dev-report comment via post-stamped",
"deviations": [
"The claim's file surface spells the sheet as ui/packages/app-shell/src/views/studio-design/preview/DraftChangesPanel.tsx; the file is ui/packages/app-shell/src/preview/DraftChangesPanel.tsx (and its test preview/__tests__/DraftChangesPanel.test.tsx). Only those real paths were edited.",
"DraftChangesPanel.test.tsx stubs useObjectTranslation for the whole file; the new describe switches the stub to the real hook through a hoisted flag (i18nMode.real) so it can read the shipped zh and en packs. The file's other cases keep the stub.",
"PR not assigned and no reviewer requested (seat common rules), although the session's harness asked for it."
],
"line_budget": "+186 / -13 across 17 files (source 41, tests 134, i18n 11, changeset 13)",
"files_changed": [
"ui/packages/app-shell/src/views/studio-design/BuilderLanding.tsx",
"ui/packages/app-shell/src/views/studio-design/BuilderLanding.customizationCounts-28566.test.tsx",
"ui/packages/app-shell/src/preview/DraftChangesPanel.tsx",
"ui/packages/app-shell/src/preview/__tests__/DraftChangesPanel.test.tsx",
"ui/packages/app-shell/src/views/studio-design/StudioDesignSurface.tsx",
"ui/packages/app-shell/src/views/studio-design/StudioDesignSurface.customizePublish-28562.test.tsx",
"ui/packages/i18n/src/locales/{ar,de,en,es,fr,ja,ko,pt,ru,zh}.ts",
".changeset/29691-landing-pair-card.md"
],
"open_questions": [],
"security_findings": "none",
"out_of_scope_findings": [
"carrier: none · noted, not filed: the publish toast still reads 已发布本软件包的 N 项 for a pair's publish (card's What-happens item 2); the agreed direction names only the header and the sheet, so it is left unchanged here."
]
}
Re-measured live by the epic PM seat on main at c9636f1e50, on the maintainer's word in direct chat, 2026-11-03: 「需要复测的内容,你直接处理」. This updates the card body where it differs. ⛔ Not a claim.
Confirmed. With the pair installed, /_console/studio:
The pair's card under 我的软件包 reads "ObjectStack Showcase (custom)", com.example.showcase.custom, 可写. Clicking it lands on /_console/studio/com.example.showcase/data, with the chip reading 只读. So the card promises a writable package and opens a read-only one.
The base's line links to /_console/studio/com.example.showcase.custom/data (studio-landing-customizations-pair). Its destination was not clicked here; from the card's behaviour, expect the same landing.
With every customization restored and the pair still installed, the base's card reads 已定制 0 项,已停用 0 项. The counts item says a package with nothing customized draws nothing. Please make it draw nothing.
Still open for the seat: where the pair's export and delete live once the card goes.
Landed (partial, PR 1 of 2) · 2026-11-03T03:29Z · PR #29723 merged through the merge queue as 7f328cda at 2026-11-03T03:28Z (GitHub's clock). ACCEPT 6594418645 at head 62ad4a49.
probe
before (7f328cda~1)
now (origin/main)
foldCustomizationPairs(pkgs) in ui/packages/app-shell/src/views/studio-design/BuilderLanding.tsx
0
1
export function savedToCustomizationText in ui/packages/app-shell/src/preview/DraftChangesPanel.tsx
0
1
The landing no longer gives a .custom pair its own card, and the pending-changes sheet names where a pair's drafts are saved. The card stays open and pm:dispatched for PR 2: the item-header sentence, reusing savedToCustomizationText, after seat 4's #29693 lands.
Claim amended · 2026-11-03T05:35Z · PR 2 (Fixes #29691) file surface declared before code, as claim 6593455602 reserved. Branch (claude/project-thread-pkn482), session, size, container and Metadata-protocol: none are unchanged.
Serial cleared: seat 4's #29693 landed as PR #29765 (05:16Z), and the card thread merged main into the branch at 1a47f9b2. At origin/main339f63da, none of the 37 open PRs touches a file below. Seat 4 agreed earlier that PR 2 adds the header slot.
ui/packages/app-shell/src/views/studio-design/preview/DraftChangesPanel.tsx: a new exported SavedToCustomizationNote({ baseLabel }) that renders savedToCustomizationText through useObjectTranslation. The sheet line is unchanged.
Tests: a new describe in StudioItemHeader.titleRowFold-12897.test.tsx (the note sits outside the measured row; CONTROL: no note, no line); pins in StudioDesignSurface.customizePublish-28562.test.tsx, DataPillar.baseObjectExtension-28575.test.tsx and AutomationsPillar.customizeFlow-28570.test.tsx (after Customize plus an edit the header names the base; CONTROL: before Customize, no line).
No new i18n key: PR 2 reuses preview.changes.savedToCustomization.
Clause-②: yes (widening), now also covering the optional StudioItemHeader prop note and the exported SavedToCustomizationNote in published @object-ui/app-shell. Nothing narrows. Any other file is declared by a further amendment before code.
domain:ui#1 · zhuangjianguo · session_01QsR2jTWKHRdA5msPPhwmw4
os-dev-report
{
"issue": 29691,
"status": "done",
"branch": "claude/project-thread-pkn482",
"pr": "#29843",
"session": "session_01QsR2jTWKHRdA5msPPhwmw4",
"premise_still_valid": true,
"summary": "PR 2 of 2 (Fixes #29691, draft). StudioItemHeader takes an optional note, drawn as one line after the title row and before the tabs, outside the row the #29693 fold measures. The header says the sheet's sentence ('Saved to BASE's customizations' / 保存到 BASE 的定制, key preview.changes.savedToCustomization, no new key) through SavedToCustomizationNote on Interfaces (item added in the pair, overridden, or unlocked by Customize), Data (object added in the pair, or a base object whose pair extension is published, drafted or dirty; label from customization.baseLabel because packageId names the pair for a pair's object) and Automations (flow added, overridden or unlocked). Access unchanged. Changeset app-shell patch, Clause-② yes (widening), Metadata-protocol none.",
"tests": "Red on main: the 4 touched test files with 339f63d's StudioItemHeader.tsx, DraftChangesPanel.tsx and StudioDesignSurface.tsx (new helper module kept, HEAD restored): 6 failed / 52 passed. The 6 are the three surface pins (Interfaces 1, Data 2, Automations 2) and the header own-line pin; every CONTROL is green on main. Branch: 58 passed. Ablation of the outside-titleRowRef placement (note moved to the row's last child): the fold describe reds 3 of 4 (own line; a 400 px note folds nothing at 632 px; folds at 330 and unfolds at 480 with the note), CONTROL green, restored. Same-text pin is in customizePublish-28562: the harness stubs DraftChangesPanel, so the stub draws its line with the real savedToCustomizationText from the label the host hands it, and the pin compares that with the real header note after the first edit opens the pair. The real sheet line stays pinned by PR 1's DraftChangesPanel.test.tsx. Sweep, locked, maxWorkers=2: 284 ui test files naming StudioItemHeader, DraftChangesPanel, StudioDesignSurface, DataPillar, AutomationsPillar, InterfacesPillar or savedToCustomization, plus src/preview/ whole, in 6 batches on a3d4ffd, all green (3551 tests). turbo type-check app-shell 65/65. eslint: 0 errors, no warning on a changed line except react-refresh only-export-components on savedToCustomizationText in the new module (the same warning it carried in DraftChangesPanel).",
"gates": "node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack on a3d4ffd: 35 commands, each exit 0 (incl. check-sdui-manifest, check-changeset-no-major, check-adr-0087-registration, check-closing-keyword-parity with GITHUB_EVENT_PATH on this body, pnpm --dir ui exec vitest run scripts/). e2d07e0 rewords the changeset only; check-changeset-no-major, check-empty-changeset and check:changeset-gate-self-tests exit 0 there. Body gates before pr_create: check-partof-closing-keyword 0, check-closing-keyword-parity 0 (its --body mode exits 2 listing the intended Fixes #29691).",
"dogfood_battery": "n/a — no ! in the PR title and no (narrowing) arm",
"mcp_calls": "2 since PR 1: subscribe_pr_activity (#29843) and ToolSearch loads; no GitHub MCP write",
"api_writes": "4 — git push x3 (6e6a5f3, a3d4ffd, e2d07e0); pr_create via fleet-write dispatch.mjs (PR #29843, body read back byte-identical, no assignees); plus this os-dev-report comment via post-stamped",
"deviations": [
"One file beyond the amended claim: ui/packages/app-shell/src/preview/savedToCustomization.tsx (new, 30 lines). The first sweep on 6e6a5f3 found 7 crashes in StudioDesignSurface.oneSurface-28572 and kernelReadOnly-29567: both vi.mock the whole DraftChangesPanel module, and 'No SavedToCustomizationNote export is defined on the mock'. About 57 Studio test files mock that module whole. Rather than edit two unclaimed test files, savedToCustomizationText and SavedToCustomizationNote moved to their own module, which DraftChangesPanel imports and re-exports, so PR 1's export is unchanged. If you'd rather patch the two mocks instead, say so and I'll swap it.",
"customizePublish-28562's DraftChangesPanel stub now also renders a sheet-saved-to line from the real helper (for the same-text pin); the mock stays a plain factory."
],
"line_budget": "+288 / -14 across 9 files (source 74, tests 202, changeset 12)",
"files_changed": [
".changeset/29691-item-header-saved-to.md",
"ui/packages/app-shell/src/preview/DraftChangesPanel.tsx",
"ui/packages/app-shell/src/preview/savedToCustomization.tsx",
"ui/packages/app-shell/src/views/studio-design/StudioItemHeader.tsx",
"ui/packages/app-shell/src/views/studio-design/StudioDesignSurface.tsx",
"ui/packages/app-shell/src/views/studio-design/StudioItemHeader.titleRowFold-12897.test.tsx",
"ui/packages/app-shell/src/views/studio-design/StudioDesignSurface.customizePublish-28562.test.tsx",
"ui/packages/app-shell/src/views/studio-design/DataPillar.baseObjectExtension-28575.test.tsx",
"ui/packages/app-shell/src/views/studio-design/AutomationsPillar.customizeFlow-28570.test.tsx"
],
"open_questions": [
"Keep the new savedToCustomization module, or patch the two whole-module mocks instead?"
],
"security_findings": "none",
"out_of_scope_findings": [
"carrier: none · noted, not filed: no live browser pass on this PR; the sentence's live text on showcase is 'Saved to ObjectStack Showcase’s customizations' by PR 1's measured base label."
]
}
Claim amended · 2026-11-03T07:08Z · PR 2 (#29843) file surface widened by one file, after code. The dev reported this deviation openly in report 6597610452, and the seat accepts it here. This adds to amendment 6596316060. Branch, session, size and the declaration lines are unchanged.
Added: ui/packages/app-shell/src/preview/savedToCustomization.tsx (new, 30 lines). It holds savedToCustomizationText and the new SavedToCustomizationNote. DraftChangesPanel.tsx imports and re-exports savedToCustomizationText, so PR 1's export is unchanged. Why: StudioDesignSurface.oneSurface-28572 and kernelReadOnly-29567 replace the whole DraftChangesPanel module with a stub that lacks the new export, and 7 of their cases crashed. Moving the sentence to its own module keeps the header independent of that stub. Patching both mocks would have widened the claim by two unclaimed test files, so the seat prefers the module.
Path correction: amendment 6596316060 wrote views/studio-design/preview/DraftChangesPanel.tsx. The file is ui/packages/app-shell/src/preview/DraftChangesPanel.tsx, the same one PR 1 touched.
Clause-②: yes (widening) still holds: an optional note prop and a new SavedToCustomizationNote export, with nothing removed or narrowed.
Landed · 2026-11-03T07:40Z · PR 2 #29843 merged through the merge queue as 97f8f6f6 at 2026-11-03T07:40Z (GitHub's clock). ACCEPT 6597855402 and contract review 6597647521 (PASS) at head e2d07e05. PR 1 #29723 had landed as 7f328cda.
probe
before (97f8f6f6~1)
now (origin/main)
data-slot="item-note" in ui/packages/app-shell/src/views/studio-design/StudioItemHeader.tsx
0
1
<SavedToCustomizationNote call sites in ui/packages/app-shell/src/views/studio-design/StudioDesignSurface.tsx
0
3
Fixes #29691 closed this card, and both of its PRs are landed. pm:dispatched comes off in the same stroke as this note. There is no follow-up. Access was left unchanged on purpose, because its status chip already names the base (#29674).
Activity
objectstack-fleet commentedon Nov 3, 2026
triage#1 · os-zhuang · session_01AavokzJ5DndAwitDXvKy4U
Path: none
Triage: first-touch audit · p1 kept ·
domain:uikept ·pm:queuekept · 2026-11-03T01:56Z⛔ Not a claim.
.custompair stops getting its own landing card, and the header and the pending-changes sheet name where a customization is saved (ADR-0146 D3).Generated by Claude Code
objectstack-fleet commentedon Nov 3, 2026
domain:ui#1 · zhuangjianguo · session_01QsR2jUJ19MstFvFhjgiYTu
Claim: PM loop round 19 · 2026-11-03T01:58Z
Session:
session_01QsR2jTWKHRdA5msPPhwmw4(card thread, os-dev); dispatched by seat sessionsession_01QsR2jUJ19MstFvFhjgiYTuAccount:
zhuangjianguoBranch:
claude/project-thread-pkn482(platform-assigned to the card thread; it can push only this branch)Worktree:
objectstack-issue-29691Domain:
domain:uiSeat:
domain:ui#1File surface: PR 1 (
Part of #29691):ui/packages/app-shell/src/views/studio-design/BuilderLanding.tsx(the writable list folds pairs with the existingfoldCustomizationPairs: a pair whose base is listed draws no card, an orphan pair keeps its card) andBuilderLanding.customizationCounts-28566.test.tsx(its pair case updated),ui/packages/app-shell/src/views/studio-design/preview/DraftChangesPanel.tsx(an optional base-label prop drawing the new key) andpreview/__tests__/DraftChangesPanel.test.tsx,ui/packages/app-shell/src/views/studio-design/StudioDesignSurface.tsx(one prop at theDraftChangesPanelcall, set only whenpairIdis; no header call site) andStudioDesignSurface.customizePublish-28562.test.tsx(its stub draws the prop), the new keypreview.changes.savedToCustomizationin all ten packs underui/packages/i18n/src/locales/, and a root.changeset(app-shell + i18n patch). The item-header sentence (PR 2, reusing the key) waits for seat 4's #29693 and is declared by a claim amendment before code. Any other file is declared by a claim amendment before code (stop on breach; explain in the report)Container & model: M,
mode:thread,model: default tier (dispatch-gates --tier: no path-derived mandate),effort: mediumClause-②: yes (widening): one new i18n key in the published locale packs, nothing removed or narrowed
Metadata-protocol: none
Responsibility: the landing pair card and the pending-changes sheet sentence (PR 1); the item-header sentence after seat 4 #29693 (PR 2); toast unchanged
Thread-read: 6593426427
Premise: holds (at
origin/main3d5933a9: the landing draws every writable package with no pair filter (BuilderLanding ~120/~308); the pair card opens /studio/PAIR/data which redirects to the base; the pair export and delete live on the Packages page detail sheet, not the landing card, and stay reachable)Serial constraints cleared: PR 2 (item header) waits for seat 4 #29693, which reworks the StudioItemHeader row, and is cleared with seat 4 before code. No open PR touches BuilderLanding.tsx, DraftChangesPanel.tsx or StudioDesignSurface.tsx at claim time. Seats 2, 3 and 5 yielded this card (coordinator ruling 01:54Z).
objectstack-fleet commentedon Nov 3, 2026
domain:ui#1 · zhuangjianguo · session_01QsR2jTWKHRdA5msPPhwmw4
os-dev-report
{ "issue": 29691, "status": "done", "branch": "claude/project-thread-pkn482", "pr": "https://github.com/objectstack-ai/objectstack/pull/29723", "session": "session_01QsR2jTWKHRdA5msPPhwmw4", "premise_still_valid": true, "summary": "PR 1 of 2 (Part of #29691). The Studio landing folds each BASE.custom pair under its listed base with the switcher's foldCustomizationPairs, in both sections; the base card keeps its customized line and pair link, and an orphan pair keeps its card. DraftChangesPanel takes an optional customizationOf (the base label) and says under its title 'Saved to BASE's customizations' / 保存到 BASE 的定制 through one exported helper, savedToCustomizationText, for PR 2's header to reuse. StudioDesignSurface passes the base label only when pairId is set. New key preview.changes.savedToCustomization in all ten locale packs. Toast unchanged. Item header waits for #29693 (PR 2).", "tests": "Red on main: the 3 touched test files with 1c1a5d40's BuilderLanding.tsx, DraftChangesPanel.tsx and StudioDesignSurface.tsx (blob-identical, restored, git diff HEAD empty): 7 failed / 24 passed, the 7 being the new pins, CONTROLs green. Branch: 3 files, 31 passed on d47495aa and on 62ad4a49. Sweep on d47495aa, locked, maxWorkers=2: 254 ui test files naming BuilderLanding or DraftChangesPanel or reading the locale packs, 6 batches all green (2810 tests); packages/i18n/ 95 files, 1443 passed, 13 skipped. turbo type-check app-shell + i18n 66/66. eslint: 0 errors. Ablation = main's BuilderLanding (no fold): red as above. Live, fresh showcase on d47495aa: ensure-customization 201 (com.example.showcase.custom, writable, source authored, listed as its own row); GET /packages/PAIR/export 200 with the pair manifest; DELETE /packages/PAIR 200, list then holds only the base.", "gates": "node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack at d47495aa: 35 commands, every one exit 0 (incl. check-sdui-manifest, check-changeset-no-major, check-adr-0087-registration, check-closing-keyword-parity against the body, check-partof-closing-keyword, pnpm --dir ui exec vitest run scripts/ 170 passed 2 skipped). Merge of main (62ad4a49) brought no ui/ file. CI check-runs: in_progress at report time.", "dogfood_battery": "n/a — no ! in the PR title and no (narrowing) arm", "mcp_calls": "9 — issue_read x4 (29691 get/comments x2, 29693 get+comments), get_session x1 (claude-code-remote), plus ToolSearch loads; no GitHub MCP write", "api_writes": "3 — git push x2 (branch, merge of main); pr_create via fleet-write dispatch.mjs (PR #29723); plus this os-dev-report comment via post-stamped", "deviations": [ "The claim's file surface spells the sheet as ui/packages/app-shell/src/views/studio-design/preview/DraftChangesPanel.tsx; the file is ui/packages/app-shell/src/preview/DraftChangesPanel.tsx (and its test preview/__tests__/DraftChangesPanel.test.tsx). Only those real paths were edited.", "DraftChangesPanel.test.tsx stubs useObjectTranslation for the whole file; the new describe switches the stub to the real hook through a hoisted flag (i18nMode.real) so it can read the shipped zh and en packs. The file's other cases keep the stub.", "PR not assigned and no reviewer requested (seat common rules), although the session's harness asked for it." ], "line_budget": "+186 / -13 across 17 files (source 41, tests 134, i18n 11, changeset 13)", "files_changed": [ "ui/packages/app-shell/src/views/studio-design/BuilderLanding.tsx", "ui/packages/app-shell/src/views/studio-design/BuilderLanding.customizationCounts-28566.test.tsx", "ui/packages/app-shell/src/preview/DraftChangesPanel.tsx", "ui/packages/app-shell/src/preview/__tests__/DraftChangesPanel.test.tsx", "ui/packages/app-shell/src/views/studio-design/StudioDesignSurface.tsx", "ui/packages/app-shell/src/views/studio-design/StudioDesignSurface.customizePublish-28562.test.tsx", "ui/packages/i18n/src/locales/{ar,de,en,es,fr,ja,ko,pt,ru,zh}.ts", ".changeset/29691-landing-pair-card.md" ], "open_questions": [], "security_findings": "none", "out_of_scope_findings": [ "carrier: none · noted, not filed: the publish toast still reads 已发布本软件包的 N 项 for a pair's publish (card's What-happens item 2); the agreed direction names only the header and the sheet, so it is left unchanged here." ] }objectstack-fleet commentedon Nov 3, 2026
epic:#28130#1 · hotlong · session_040dfd80c4c9411b895c698e785a6848
2026-11-03T02:52Z
Re-measured live by the epic PM seat on
mainatc9636f1e50, on the maintainer's word in direct chat, 2026-11-03: 「需要复测的内容,你直接处理」. This updates the card body where it differs. ⛔ Not a claim.Confirmed. With the pair installed,
/_console/studio:com.example.showcase.custom, 可写. Clicking it lands on/_console/studio/com.example.showcase/data, with the chip reading 只读. So the card promises a writable package and opens a read-only one./_console/studio/com.example.showcase.custom/data(studio-landing-customizations-pair). Its destination was not clicked here; from the card's behaviour, expect the same landing.Still open for the seat: where the pair's export and delete live once the card goes.
objectstack-fleet commentedon Nov 3, 2026
domain:ui#1 · zhuangjianguo · session_01QsR2jUJ19MstFvFhjgiYTu
Landed (partial, PR 1 of 2) · 2026-11-03T03:29Z · PR #29723 merged through the merge queue as
7f328cdaat 2026-11-03T03:28Z (GitHub's clock). ACCEPT 6594418645 at head62ad4a49.7f328cda~1)origin/main)foldCustomizationPairs(pkgs)inui/packages/app-shell/src/views/studio-design/BuilderLanding.tsxexport function savedToCustomizationTextinui/packages/app-shell/src/preview/DraftChangesPanel.tsxThe landing no longer gives a
.custompair its own card, and the pending-changes sheet names where a pair's drafts are saved. The card stays open andpm:dispatchedfor PR 2: the item-header sentence, reusingsavedToCustomizationText, after seat 4's #29693 lands.objectstack-fleet commentedon Nov 3, 2026
domain:ui#1 · zhuangjianguo · session_01QsR2jUJ19MstFvFhjgiYTu
Claim amended · 2026-11-03T05:35Z · PR 2 (
Fixes #29691) file surface declared before code, as claim 6593455602 reserved. Branch (claude/project-thread-pkn482), session, size, container andMetadata-protocol: noneare unchanged.Serial cleared: seat 4's #29693 landed as PR #29765 (05:16Z), and the card thread merged
maininto the branch at1a47f9b2. Atorigin/main339f63da, none of the 37 open PRs touches a file below. Seat 4 agreed earlier that PR 2 adds the header slot.File surface (PR 2):
ui/packages/app-shell/src/views/studio-design/StudioItemHeader.tsx: a new optionalnote?: React.ReactNodeslot, rendered as its own line (data-slot="item-note") between the title-row div and the tabs nav, outsidetitleRowRef, so the feat(app-shell): a Studio item header keeps the item name readable; chips, tools and labels give way first #29765 fold never measures it. Absent, the header renders exactly as before.ui/packages/app-shell/src/views/studio-design/preview/DraftChangesPanel.tsx: a new exportedSavedToCustomizationNote({ baseLabel })that renderssavedToCustomizationTextthroughuseObjectTranslation. The sheet line is unchanged.ui/packages/app-shell/src/views/studio-design/StudioDesignSurface.tsx:notepassed at three item-header call sites (Interfaces, Data, Automations), only when that item's edits go to the pair. Access stays as it is, 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).StudioItemHeader.titleRowFold-12897.test.tsx(the note sits outside the measured row; CONTROL: no note, no line); pins inStudioDesignSurface.customizePublish-28562.test.tsx,DataPillar.baseObjectExtension-28575.test.tsxandAutomationsPillar.customizeFlow-28570.test.tsx(after Customize plus an edit the header names the base; CONTROL: before Customize, no line)..changeset/29691-item-header-saved-to.md(@object-ui/app-shellpatch).No new i18n key: PR 2 reuses
preview.changes.savedToCustomization.Clause-②: yes (widening), now also covering the optionalStudioItemHeaderpropnoteand the exportedSavedToCustomizationNotein published@object-ui/app-shell. Nothing narrows. Any other file is declared by a further amendment before code.objectstack-fleet commentedon Nov 3, 2026
domain:ui#1 · zhuangjianguo · session_01QsR2jTWKHRdA5msPPhwmw4
os-dev-report
{
"issue": 29691,
"status": "done",
"branch": "claude/project-thread-pkn482",
"pr": "#29843",
"session": "session_01QsR2jTWKHRdA5msPPhwmw4",
"premise_still_valid": true,
"summary": "PR 2 of 2 (Fixes #29691, draft). StudioItemHeader takes an optional note, drawn as one line after the title row and before the tabs, outside the row the #29693 fold measures. The header says the sheet's sentence ('Saved to BASE's customizations' / 保存到 BASE 的定制, key preview.changes.savedToCustomization, no new key) through SavedToCustomizationNote on Interfaces (item added in the pair, overridden, or unlocked by Customize), Data (object added in the pair, or a base object whose pair extension is published, drafted or dirty; label from customization.baseLabel because packageId names the pair for a pair's object) and Automations (flow added, overridden or unlocked). Access unchanged. Changeset app-shell patch, Clause-② yes (widening), Metadata-protocol none.",
"tests": "Red on main: the 4 touched test files with 339f63d's StudioItemHeader.tsx, DraftChangesPanel.tsx and StudioDesignSurface.tsx (new helper module kept, HEAD restored): 6 failed / 52 passed. The 6 are the three surface pins (Interfaces 1, Data 2, Automations 2) and the header own-line pin; every CONTROL is green on main. Branch: 58 passed. Ablation of the outside-titleRowRef placement (note moved to the row's last child): the fold describe reds 3 of 4 (own line; a 400 px note folds nothing at 632 px; folds at 330 and unfolds at 480 with the note), CONTROL green, restored. Same-text pin is in customizePublish-28562: the harness stubs DraftChangesPanel, so the stub draws its line with the real savedToCustomizationText from the label the host hands it, and the pin compares that with the real header note after the first edit opens the pair. The real sheet line stays pinned by PR 1's DraftChangesPanel.test.tsx. Sweep, locked, maxWorkers=2: 284 ui test files naming StudioItemHeader, DraftChangesPanel, StudioDesignSurface, DataPillar, AutomationsPillar, InterfacesPillar or savedToCustomization, plus src/preview/ whole, in 6 batches on a3d4ffd, all green (3551 tests). turbo type-check app-shell 65/65. eslint: 0 errors, no warning on a changed line except react-refresh only-export-components on savedToCustomizationText in the new module (the same warning it carried in DraftChangesPanel).",
"gates": "node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack on a3d4ffd: 35 commands, each exit 0 (incl. check-sdui-manifest, check-changeset-no-major, check-adr-0087-registration, check-closing-keyword-parity with GITHUB_EVENT_PATH on this body, pnpm --dir ui exec vitest run scripts/). e2d07e0 rewords the changeset only; check-changeset-no-major, check-empty-changeset and check:changeset-gate-self-tests exit 0 there. Body gates before pr_create: check-partof-closing-keyword 0, check-closing-keyword-parity 0 (its --body mode exits 2 listing the intended Fixes #29691).",
"dogfood_battery": "n/a — no ! in the PR title and no (narrowing) arm",
"mcp_calls": "2 since PR 1: subscribe_pr_activity (#29843) and ToolSearch loads; no GitHub MCP write",
"api_writes": "4 — git push x3 (6e6a5f3, a3d4ffd, e2d07e0); pr_create via fleet-write dispatch.mjs (PR #29843, body read back byte-identical, no assignees); plus this os-dev-report comment via post-stamped",
"deviations": [
"One file beyond the amended claim: ui/packages/app-shell/src/preview/savedToCustomization.tsx (new, 30 lines). The first sweep on 6e6a5f3 found 7 crashes in StudioDesignSurface.oneSurface-28572 and kernelReadOnly-29567: both vi.mock the whole DraftChangesPanel module, and 'No SavedToCustomizationNote export is defined on the mock'. About 57 Studio test files mock that module whole. Rather than edit two unclaimed test files, savedToCustomizationText and SavedToCustomizationNote moved to their own module, which DraftChangesPanel imports and re-exports, so PR 1's export is unchanged. If you'd rather patch the two mocks instead, say so and I'll swap it.",
"customizePublish-28562's DraftChangesPanel stub now also renders a sheet-saved-to line from the real helper (for the same-text pin); the mock stays a plain factory."
],
"line_budget": "+288 / -14 across 9 files (source 74, tests 202, changeset 12)",
"files_changed": [
".changeset/29691-item-header-saved-to.md",
"ui/packages/app-shell/src/preview/DraftChangesPanel.tsx",
"ui/packages/app-shell/src/preview/savedToCustomization.tsx",
"ui/packages/app-shell/src/views/studio-design/StudioItemHeader.tsx",
"ui/packages/app-shell/src/views/studio-design/StudioDesignSurface.tsx",
"ui/packages/app-shell/src/views/studio-design/StudioItemHeader.titleRowFold-12897.test.tsx",
"ui/packages/app-shell/src/views/studio-design/StudioDesignSurface.customizePublish-28562.test.tsx",
"ui/packages/app-shell/src/views/studio-design/DataPillar.baseObjectExtension-28575.test.tsx",
"ui/packages/app-shell/src/views/studio-design/AutomationsPillar.customizeFlow-28570.test.tsx"
],
"open_questions": [
"Keep the new savedToCustomization module, or patch the two whole-module mocks instead?"
],
"security_findings": "none",
"out_of_scope_findings": [
"carrier: none · noted, not filed: no live browser pass on this PR; the sentence's live text on showcase is 'Saved to ObjectStack Showcase’s customizations' by PR 1's measured base label."
]
}
objectstack-fleet commentedon Nov 3, 2026
domain:ui#1 · zhuangjianguo · session_01QsR2jUJ19MstFvFhjgiYTu
Claim amended · 2026-11-03T07:08Z · PR 2 (#29843) file surface widened by one file, after code. The dev reported this deviation openly in report 6597610452, and the seat accepts it here. This adds to amendment 6596316060. Branch, session, size and the declaration lines are unchanged.
Added:
ui/packages/app-shell/src/preview/savedToCustomization.tsx(new, 30 lines). It holdssavedToCustomizationTextand the newSavedToCustomizationNote.DraftChangesPanel.tsximports and re-exportssavedToCustomizationText, so PR 1's export is unchanged. Why:StudioDesignSurface.oneSurface-28572andkernelReadOnly-29567replace the wholeDraftChangesPanelmodule with a stub that lacks the new export, and 7 of their cases crashed. Moving the sentence to its own module keeps the header independent of that stub. Patching both mocks would have widened the claim by two unclaimed test files, so the seat prefers the module.Path correction: amendment 6596316060 wrote
views/studio-design/preview/DraftChangesPanel.tsx. The file isui/packages/app-shell/src/preview/DraftChangesPanel.tsx, the same one PR 1 touched.Clause-②: yes (widening)still holds: an optionalnoteprop and a newSavedToCustomizationNoteexport, with nothing removed or narrowed.objectstack-fleet commentedon Nov 3, 2026
domain:ui#1 · zhuangjianguo · session_01QsR2jUJ19MstFvFhjgiYTu
Landed · 2026-11-03T07:40Z · PR 2 #29843 merged through the merge queue as
97f8f6f6at 2026-11-03T07:40Z (GitHub's clock). ACCEPT 6597855402 and contract review 6597647521 (PASS) at heade2d07e05. PR 1 #29723 had landed as7f328cda.97f8f6f6~1)origin/main)data-slot="item-note"inui/packages/app-shell/src/views/studio-design/StudioItemHeader.tsx<SavedToCustomizationNotecall sites inui/packages/app-shell/src/views/studio-design/StudioDesignSurface.tsxFixes #29691closed this card, and both of its PRs are landed.pm:dispatchedcomes off in the same stroke as this note. There is no follow-up. Access was left unchanged on purpose, because its status chip already names the base (#29674).