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
[Decision] The rail's green 「+」 looks like an add button but is a status mark: what should a customization mark look like? #30070
The maintainer: 「等我决定的都要立卡,并且从业务的角度给我具体解释和我沟通」 (2026-11-04). Measured by the seat on main63b86b385d, on the example CRM unless noted. No domain:* label is set: triage routes this card.
The question
Studio's left rail marks a customized row with a small icon: a green filled square with a plus means 新增, added in the customization package. It is not a control. A person clicks it, nothing happens, and it sits right beside an item they could not add to the menu. The maintainer did exactly this: 「还有导航上一个加号图标什么意思,点了也没反应」.
Governing text: ui/packages/app-shell/src/views/studio-design/CustomizationMark.tsx:40-44 (#29693 compacted the mark to a glyph so it never takes the row's label). No ADR fixes the glyph.
Measured
Drawn temporarily in the live rail on the automation pillar, row width 223 px:
Style
Mark width
Room for the name
Today's green filled plus
18 px
113 px
The word 新增, no background
30 px
105 px
A green package glyph
18 px
113 px
A dot is out: the automation rail already uses dots for 已启用, 未在此运行, 已停用.
Options
A. Words, no background: 新增 for added and 定制 for customized. Costs 8 px, under one character of the name.
B. A non-plus glyph: same width, but the meaning has to be learned or hovered.
The maintainer, 2026-11-04: 「30079这种不是应该在元数据应用中自己去开发自定义操作吗?你的意见是批量换负责人放到内核吗?其他全部同意」.
Ruling: option A. Customization marks use the words 新增 and 定制 with no background, and keep the tooltip. Clicking stays row selection only. needs-user-decision is removed; triage routes this card.
Claim: PM loop round 2
Session: session_01L6bhgVwQZbHRRM9CaXeKif
Account: os-sales
Branch: claude/project-thread-p3zei2 (card thread of this project; a thread can push only its designated branch — measured platform exception to claude/issue-<n>-<slug>)
Worktree: objectstack-issue-30070
Domain: domain:ui
Seat: domain:ui#5
File surface: ui/packages/app-shell/src/views/studio-design/CustomizationMark.tsx, StudioRailCustomizations.tsx and the tests that pin the mark (incl. StudioDesignSurface.oneSurface-28572.test.tsx) + ui/packages/i18n/src/namespaces/studio/{en,zh}.ts + one root .changeset/. InterfacesNavRail.tsx / StudioDesignSurface.tsx only if required (PR #30401 of domain:ui#2 edits them); ⛔ packages/**.
Container & model: M, mode:thread, model: default — dispatch-gates --tier: no path-derived mandate, effort: high
Clause-②: yes
Metadata-protocol: none
Responsibility: the compact customization mark (CustomizationMark.tsx) draws a filled green block with a plus icon that reads as an add button but is a status mark | none: no other affordance names a row's customization at a glance | everyone who opens a customized app in Studio (the maintainer clicked it once and nothing happened)
Ruling-ref: 6631229752 「Ruling: option A. Customization marks use the words 新增 and 定制 with no background, and keep the tooltip. Clicking stays row selection only.」
Thread-read: 6631605075
Premise: holds
Serial constraints cleared: #30238, #30088 and #30177 are closed; no open PR edits CustomizationMark.tsx, StudioRailCustomizations.tsx or the 28572 test; PR #30401 (domain:ui#2, #30046) edits InterfacesNavRail.tsx / StudioDesignSurface.tsx, which this card avoids. The InterfacesNavOverrideMark button (the 恢复原版 popover) keeps working.
Scope: the ruled option A only. Clause-② yes (widening) for a new short studio i18n key: the seat's TIER_DEFAULT review before the queue. Dispatch order lives in the card thread's opening message.
{
"issue": 30070,
"status": "done",
"branch": "claude/project-thread-p3zei2",
"pr": "https://github.com/objectstack-ai/objectstack/pull/30468",
"session": "session_01L6bhgXtD8kC2LpK5YoB2sK",
"premise_still_valid": true,
"summary": "Ruled option A implemented. CustomizationMark's compact branch (every pillar rail row via RailCustomizationMark, and InterfacesNavOverrideMark's popover button) now prints one short coloured word with no background and no glyph: customized reads the new studio key engine.customizationMark.customizedShort (zh 定制, en Custom), added reads the existing engine.customizationMark.added (新增 / Added). role img, accessible name (full label) and tooltip unchanged; no handler, so a click stays row selection. Mechanism hypothesis held as written (18x18 filled block, empty textContent pinned by the 28572 test).",
"tests": "On cabd8ba8 (head b3864c84 is tree-identical: evidence commit + removal). pnpm --dir ui exec vitest run over the 9 test files that name the mark + i18n studio-namespace and studio-namespace-lazy: Test Files 11 passed (11), Tests 230 passed (230), lock VERDICT command-exit 0. Ablation 1 (ablation-replace.mjs, anchor x1 to x0): compact word to {null} -> 1 failed / 26 passed (expected '' to be 'Custom'); restored, blob == HEAD, git diff HEAD empty. Ablation 2: compact classes given filled KIND_CLASS back -> 1 failed / 26 passed (not to match bg-); restored, blob == HEAD. pnpm --filter @object-ui/i18n --filter @object-ui/app-shell type-check (tsc --noEmit + tsconfig.test.json): VERDICT command-exit 0. Live rig examples/app-crm + console vite, zh-CN and en-US at 1440: before 18px filled + svg; after transparent, no svg, widths 定制 22 新增 22 Custom 40 Added 34; nav-override popover with 恢复软件包原版 still opens; clicking the 新增 mark selects its row.",
"gates": "dispatch-gates --commands --repo objectstack-ai/objectstack at cabd8ba8: 35 derived, each run, all exit 0 (incl. pnpm --dir ui exec vitest run scripts/: 170 files passed 2 skipped, 4985 tests passed 2 skipped; check:type-check-debt exit 0). --ran reconciliation: 35 derived, 35 run, 0 NOT-MEASURED, 0 UNRUN. Outside the derived list: pnpm --dir ui run check:spec-symbols exit 0; eslint on the 5 changed source files exit 0 (warnings on unchanged lines only); pnpm check:new-line-citations (ui) 0 new, exit 0. CI check-runs on PR 30468: in_progress at report time.",
"dogfood_battery": "n/a — no ! in the PR title and Clause-② is yes (widening), no (narrowing) arm",
"mcp_calls": "4 — reads only: mcp__github__issue_read x3 (issue 30070 get, get_comments x2), mcp__github__pull_request_read x1 (PR 30442 body as a layout reference); zero MCP writes",
"api_writes": "2 relay writes + 1 git push: git push -u origin claude/project-thread-p3zei2; fleet-write pr_create (run 42028931858, PR 30468, draft, no assignees, no labels); this os-dev-report comment via post-stamped.mjs",
"open_questions": [
{
"question": "English word for the compact customized mark: Custom (40 px, chosen) or Customized (61 px, cut the selected row to 'Convert Lea…' on the 223 px automations rail)?",
"options": [
"A Custom (as shipped)",
"B Customized (one en row change)"
],
"recommendation": "A, because the ruling's point is a short status word that never takes the row's name, and zh 定制 is the same short form"
}
],
"security_findings": "none",
"out_of_scope_findings": [
"carrier: none · InterfacesNavRail.tsx InterfacesNavOverrideMark doc comment still says 'the compact customized glyph' — stale wording only, file left untouched because PR 30401 (domain:ui#2) edits it; noted in the PR's Acceptance notes, not filed"
]
}
Landed at 2026-11-05T13:18Z: PR #30468 merged as 0c7e95aff5 (seat ACCEPT 6658596635 on head b3864c84, TIER_DEFAULT contract review PASS 6658291542), Fixes #30070. The merge read 2026-11-05T13:17Z on the PR.
Activity
objectstack-fleet commentedon Nov 4, 2026
epic:#26676#1 · zhuangjianguo · session_cdb7a717def74e719988f089fbaa18ff
The maintainer, 2026-11-04: 「30079这种不是应该在元数据应用中自己去开发自定义操作吗?你的意见是批量换负责人放到内核吗?其他全部同意」.
Ruling: option A. Customization marks use the words 新增 and 定制 with no background, and keep the tooltip. Clicking stays row selection only.
needs-user-decisionis removed; triage routes this card.objectstack-fleet commentedon Nov 4, 2026
triage#1 · os-zhuang · session_01AavokzJ5DndAwitDXvKy4U
Path: none
Triage: first-touch audit · p3 kept ·
domain:ui· 2026-11-04T13:15Z⛔ Not a claim.
Generated by Claude Code
objectstack-fleet commentedon Nov 5, 2026
domain:ui#5 · os-sales · session_01L6bhgVwQZbHRRM9CaXeKif
Claim: PM loop round 2
Session:
session_01L6bhgVwQZbHRRM9CaXeKifAccount:
os-salesBranch:
claude/project-thread-p3zei2(card thread of this project; a thread can push only its designated branch — measured platform exception toclaude/issue-<n>-<slug>)Worktree:
objectstack-issue-30070Domain:
domain:uiSeat:
domain:ui#5File surface:
ui/packages/app-shell/src/views/studio-design/CustomizationMark.tsx,StudioRailCustomizations.tsxand the tests that pin the mark (incl.StudioDesignSurface.oneSurface-28572.test.tsx) +ui/packages/i18n/src/namespaces/studio/{en,zh}.ts+ one root.changeset/.InterfacesNavRail.tsx/StudioDesignSurface.tsxonly if required (PR #30401 ofdomain:ui#2edits them); ⛔packages/**.Container & model:
M,mode:thread,model: default — dispatch-gates --tier: no path-derived mandate,effort: highClause-②: yes
Metadata-protocol: none
Responsibility: the compact customization mark (
CustomizationMark.tsx) draws a filled green block with a plus icon that reads as an add button but is a status mark | none: no other affordance names a row's customization at a glance | everyone who opens a customized app in Studio (the maintainer clicked it once and nothing happened)Ruling-ref: 6631229752 「Ruling: option A. Customization marks use the words 新增 and 定制 with no background, and keep the tooltip. Clicking stays row selection only.」
Thread-read: 6631605075
Premise: holds
Serial constraints cleared: #30238, #30088 and #30177 are closed; no open PR edits
CustomizationMark.tsx,StudioRailCustomizations.tsxor the 28572 test; PR #30401 (domain:ui#2, #30046) editsInterfacesNavRail.tsx/StudioDesignSurface.tsx, which this card avoids. TheInterfacesNavOverrideMarkbutton (the 恢复原版 popover) keeps working.Scope: the ruled option A only. Clause-②
yes (widening)for a new short studio i18n key: the seat's TIER_DEFAULT review before the queue. Dispatch order lives in the card thread's opening message.objectstack-fleet commentedon Nov 5, 2026
domain:ui#5 · os-sales · session_01L6bhgXtD8kC2LpK5YoB2sK
os-dev-report
{ "issue": 30070, "status": "done", "branch": "claude/project-thread-p3zei2", "pr": "https://github.com/objectstack-ai/objectstack/pull/30468", "session": "session_01L6bhgXtD8kC2LpK5YoB2sK", "premise_still_valid": true, "summary": "Ruled option A implemented. CustomizationMark's compact branch (every pillar rail row via RailCustomizationMark, and InterfacesNavOverrideMark's popover button) now prints one short coloured word with no background and no glyph: customized reads the new studio key engine.customizationMark.customizedShort (zh 定制, en Custom), added reads the existing engine.customizationMark.added (新增 / Added). role img, accessible name (full label) and tooltip unchanged; no handler, so a click stays row selection. Mechanism hypothesis held as written (18x18 filled block, empty textContent pinned by the 28572 test).", "tests": "On cabd8ba8 (head b3864c84 is tree-identical: evidence commit + removal). pnpm --dir ui exec vitest run over the 9 test files that name the mark + i18n studio-namespace and studio-namespace-lazy: Test Files 11 passed (11), Tests 230 passed (230), lock VERDICT command-exit 0. Ablation 1 (ablation-replace.mjs, anchor x1 to x0): compact word to {null} -> 1 failed / 26 passed (expected '' to be 'Custom'); restored, blob == HEAD, git diff HEAD empty. Ablation 2: compact classes given filled KIND_CLASS back -> 1 failed / 26 passed (not to match bg-); restored, blob == HEAD. pnpm --filter @object-ui/i18n --filter @object-ui/app-shell type-check (tsc --noEmit + tsconfig.test.json): VERDICT command-exit 0. Live rig examples/app-crm + console vite, zh-CN and en-US at 1440: before 18px filled + svg; after transparent, no svg, widths 定制 22 新增 22 Custom 40 Added 34; nav-override popover with 恢复软件包原版 still opens; clicking the 新增 mark selects its row.", "gates": "dispatch-gates --commands --repo objectstack-ai/objectstack at cabd8ba8: 35 derived, each run, all exit 0 (incl. pnpm --dir ui exec vitest run scripts/: 170 files passed 2 skipped, 4985 tests passed 2 skipped; check:type-check-debt exit 0). --ran reconciliation: 35 derived, 35 run, 0 NOT-MEASURED, 0 UNRUN. Outside the derived list: pnpm --dir ui run check:spec-symbols exit 0; eslint on the 5 changed source files exit 0 (warnings on unchanged lines only); pnpm check:new-line-citations (ui) 0 new, exit 0. CI check-runs on PR 30468: in_progress at report time.", "dogfood_battery": "n/a — no ! in the PR title and Clause-② is yes (widening), no (narrowing) arm", "mcp_calls": "4 — reads only: mcp__github__issue_read x3 (issue 30070 get, get_comments x2), mcp__github__pull_request_read x1 (PR 30442 body as a layout reference); zero MCP writes", "api_writes": "2 relay writes + 1 git push: git push -u origin claude/project-thread-p3zei2; fleet-write pr_create (run 42028931858, PR 30468, draft, no assignees, no labels); this os-dev-report comment via post-stamped.mjs", "open_questions": [ { "question": "English word for the compact customized mark: Custom (40 px, chosen) or Customized (61 px, cut the selected row to 'Convert Lea…' on the 223 px automations rail)?", "options": [ "A Custom (as shipped)", "B Customized (one en row change)" ], "recommendation": "A, because the ruling's point is a short status word that never takes the row's name, and zh 定制 is the same short form" } ], "security_findings": "none", "out_of_scope_findings": [ "carrier: none · InterfacesNavRail.tsx InterfacesNavOverrideMark doc comment still says 'the compact customized glyph' — stale wording only, file left untouched because PR 30401 (domain:ui#2) edits it; noted in the PR's Acceptance notes, not filed" ] }objectstack-fleet commentedon Nov 5, 2026
domain:ui#5 · os-sales · session_01L6bhgVwQZbHRRM9CaXeKif
Landed at 2026-11-05T13:18Z: PR #30468 merged as
0c7e95aff5(seat ACCEPT 6658596635 on headb3864c84, TIER_DEFAULT contract review PASS 6658291542),Fixes #30070. The merge read 2026-11-05T13:17Z on the PR.git grep -c customizedShort origin/main -- ui/packages/app-shell/src/views/studio-design/CustomizationMark.tsxState change:
pm:dispatchedremoved. Ruling A (6631229752) is implemented in full; nothing remains on the card.