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
Child record names are stored in English, so a zh-CN user reads "v2 · Clean", "Legal · Legal Counsel 1", "Wet ink · Completed" #157
Blocked-by: objectstack-ai/objectstack#26608 (a record name made of option labels cannot render in the reader's locale; measured on 18.2.0, report 6439089136)
Filing gate: ① user-visible defect, reproduced in the browser on @objectstack 18.2.0 (hotclm PR #155 branch), zh-CN console, real personas.
Symptom. The display_name of three child objects is composed by the app in English from option labels, and that stored string is what the zh-CN console shows as the record's name:
Action (as legal counsel)
Toast / list shows
Upload a clean version on 版本
合同版本"v2 · Clean"已创建; the list row reads "v1 · Draft"
Create a review on 审查与偏离
审查"Legal · Legal Counsel 1"已创建
Register a wet-ink signing round
签署记录"Wet ink · Completed"已创建
Every other word on those screens is Chinese (类别 清稿, 环节 法务, 签署方式 湿签).
Where.display_name on clm_contract_version, clm_review, clm_signature (DESIGN.md §03 "镜像 …"), and likely clm_deviation (" · "). The value is written once in one language, so a stored name cannot follow the reader's locale.
Expected. A zh-CN reader sees 「v2 · 清稿」「法务 · Legal Counsel 1」「湿签 · 已完成」.
Open question for triage. Whether this is app-side (compose the name at read time from translated labels, e.g. a formula field, if the platform can) or a platform gap (a name composed of select labels has no per-reader rendering). If the latter, file it in objectstack and cross-link (maintainer rule 2026-10-26).
Business reason. The names appear in every toast, related list and lookup for these records; a Chinese-speaking legal team reads English fragments on every save.
Reader. hotclm execution seat (PM seat #36) or triage.
Duplicate search. hotclm issues, all states, "display_name English / stored name": 0 hits. Related but different: #141 (renewal title prefix in English).
Filed from the 18.2.0 browser pass (hotclm PR #155, landed as 21f2319). Defect, user-visible, reproduced: accepted.
Route: measure first. If the platform can render a name composed of select labels per reader (a formula or display template that reads translated option labels), the fix is app-side metadata. If not, the dev files the platform gap in objectstack with the measurement (maintainer rule 2026-10-26), and this card goes pm:blocked on it. It shares src/objects/contract.hook.ts with #159, so it is dispatched after #159 lands.
Claim: PM loop round 17
Ruling-ref: none
Session: session_017nzWFRUo2U7evMkPdVniAn
Account: zhuangjianguo (the seat's linked user as GET /user answers it; the card's assignee)
Branch: claude/issue-157-child-names-per-locale
Worktree: hotclm-issue-157
Domain: repo:hotclm (single-lane sister repo — no domain:*)
Seat: repo:hotclm#1
File surface: src/objects/contract.hook.ts (the display_name composition) · src/objects/{contract-version,review,signature,deviation}.object.ts · translations — measure first; on a platform gap stop and report (the seat files it) — stop on breach; explain in the report
Container & model: S, mode:subagent, model: opus (TIER_DEFAULT; hand-derived for a sister repo), effort: medium
Clause-②: no
Metadata-protocol: none
Responsibility: this app's child record names (what a zh-CN reader sees in toasts, lists and lookups) | possibly a platform gap | every zh-CN user saving a version, review, signature or deviation
Thread-read: 6437435865
Premise: re-measured by the dev on origin/mainbc5c3e8 (@objectstack 18.2.0) with README personas first
Serial constraints cleared: #159 landed (PR #163), so contract.hook.ts is free; in flight #127 (profiles), #158 (lifecycle actions) — disjoint files.
{
"issue": 157,
"status": "blocked",
"branch": "claude/issue-157-child-names-per-locale",
"pr": null,
"session": "session_017nzWFRUo2U7evMkPdVniAn",
"premise_still_valid": true,
"summary": "No app-side metadata route exists on 18.2.0, so no code ships and the card blocks on a platform gap for the seat to file. Reproduced on origin/main bc5c3e8 with README personas in zh-CN: toasts, related lists and record H1 read 'v2 · Clean', 'Legal · Legal Counsel 1' and 'Wet ink · Completed'. The en reader sees the same strings. I measured three candidates in the browser on a throwaway, uncommitted edit, since restored with the HEAD blob hashes matching. A formula nameField renders the raw option value 'v2 · clean' in the zh-CN toast and in the H1 for both zh-CN and en-US, because CEL has no option-label function and no reader locale. A select nameField is the one per-reader seam, and only on the record H1 (湿签 / Wet ink): the save toast reads the raw value 'wet_ink', and the name is a single field, not a composite. titleFormat is inert: with nameField removed the registry auto-designates display_name, and the title still reads 'Legal · Legal Counsel 1' (it also adds the title-format-retired lint warning). File-surface note: the composition lives in src/objects/mirror.hook.ts, not contract.hook.ts. Composition per object: clm_contract_version 'v' + version_no + ' · ' + KIND[kind]; clm_review STAGE[stage] + ' · ' + sys_user.name, falling back to 'Unassigned'; clm_deviation clm_clause.title + ' · ' + STATUS[status]; clm_signature METHOD[method] + ' · ' + STATUS[status]. All four use English label maps inlined in the hook. A follow-up fix after the platform lands would touch mirror.hook.ts, the four object files and the translations.",
"platform_gap": {
"title": "A record name composed of select option labels cannot render in the reader's locale",
"symptom": "On 18.2.0 a zh-CN reader sees the English or raw option value in every surface that shows a record name: the save toast, related-list name column, record H1 and search. The name is built from select fields such as 'v2 · Clean', 'Wet ink · Completed' and 'Legal · Legal Counsel 1', and the zh bundle translates every option label.",
"what_was_tried_and_measured": [
"Stored mirror (current app; a before-hook writes English labels): toast 合同版本“v2 · Clean”已创建 · 审查“Legal · Legal Counsel 1”已创建 · 签署记录“Wet ink · Completed”已创建; H1 is the same in zh-CN and en-US; the related-list name column is the same; REST search=清稿 or 湿签 returns 0, while search=Clean or Wet finds the rows.",
"nameField pointing at a Field.formula with returnType text and expression 'v' + string(record.version_no) + ' · ' + record.kind: zh-CN toast 合同版本“v2 · clean”已创建; H1 'v2 · clean' in zh-CN and in en-US; REST returns version_title 'v2 · clean'.",
"nameField pointing at the select field itself (clm_signature.method): H1 reads 湿签 in zh-CN and 'Wet ink' in en-US, which is per-reader; the save toast reads 签署记录“wet_ink”已创建, the raw value; one field only, so no composite.",
"titleFormat '{stage} · {reviewer}' with nameField removed: toast and H1 still read 'Legal · Legal Counsel 1', because the registry designates display_name (ADR-0079 D7); validate adds the warning title-format-retired."
],
"seams": [
"spec/formula: packages/formula/src/stdlib.ts has no option-label function in the CEL library (it registers now/today/coalesce/joinNonEmpty/upper/lower/... only), and its header forbids host resolvers.",
"spec/formula: packages/formula/src/types.ts EvalContext.locale is a reserved channel for the template dialect's formatters only; a CEL formula field reads no reader locale.",
"spec/formula: packages/formula/src/template-engine.ts FORMATTERS = upper/lower/trim/number/currency/percent/date/datetime/truncate/default/json, with no 'label' formatter for a select value.",
"renderer: ui/packages/core/src/utils/record-title.ts getRecordDisplayName resolves the title from raw stored values; ui/packages/app-shell/src/console/AppContent.tsx recordSaveMessage (createdNamed toast) uses it.",
"renderer: ui/packages/components/src/renderers/layout/containers.tsx withOptionLabels (objectui#13103) labels a select nameField or titleFormat value on the record-page H1 only.",
"objectql: registry provisionPrimary designates nameField whenever a title-eligible field exists (ADR-0079 D7), so a deprecated titleFormat is never reached on such an object."
],
"expected_capability": "A display-only record name composed of select option labels that renders in each reader's locale on every name surface: toast, related list, lookup chip, search result and H1. Two possible shapes: a CEL or template label function such as label(record.kind) evaluated with the request locale for a display-only formula nameField, or a localized title template that the resolver renders. In either shape a stored field stays available for search and sort. The design belongs to the platform.",
"repro": "hotclm origin/main bc5c3e8 on @objectstack/* 18.2.0, pnpm demo:zh. As Legal Counsel 1 (clm_legal_counsel) in a zh-CN browser: contract MSA-2026-0001 > 版本 > 新建, version 2, kind 清稿, upload a file > 创建.",
"dedupe_words": [
"record title option label locale",
"nameField formula select label translation",
"getRecordDisplayName option label",
"picklist label function CEL",
"titleFormat withOptionLabels toast"
]
},
"tests": "Browser: Chromium at /opt/pw-browsers/chromium; README personas created by create-user, sys_user_position, set-user-manager and change-password, then a demo re-run. BEFORE (bc5c3e8, zh-CN), Legal Counsel 1: version POST 201, toast 合同版本“v2 · Clean”已创建, related list 'v2 · Clean | 2 | 清稿'; review POST 201, toast 审查“Legal · Legal Counsel 1”已创建; wet-ink round POST 201, toast 签署记录“Wet ink · Completed”已创建. Records Manager: version on DPA-2026-0002 POST 201, toast “v2 · Clean”; signature has no 新建 button, so NOT MEASURED (not permitted). H1 in zh-CN and en-US: 'v2 · Clean' / 'Legal · Legal Counsel 1' / 'Wet ink · Completed'. Command palette search 'Clean' returns no results in both locales: lookup surface NOT MEASURED, because the palette does not list these objects. REST search as Legal Counsel 1: Clean 2, 清稿 0, Wet 3, 湿签 0. CANDIDATES: readings are in platform_gap; the patch is saved at /tmp/claude-0/-home-claude/bc53be1b-6c43-5271-bc20-52035f64763b/scratchpad/issue-157/candidate-experiment.patch and restored; the HEAD blob hashes match and git diff HEAD is empty. After: n/a, no code change.",
"gates": "n/a: no diff on the branch (git status clean at bc5c3e8). pnpm install exit 0. The candidate boot printed the title-format-retired warning, which is why the titleFormat route is excluded.",
"dogfood_battery": "n/a: no PR",
"mcp_calls": "0",
"api_writes": "1: this os-dev-report comment via post-stamped (POST issues/157/comments). No push, no PR.",
"open_questions": [],
"out_of_scope_findings": [
"class: a · reach: browser toast in a zh-CN console after a completed wet-ink round reads 'Execution formalities outstanding: 主服务协议 — 静谧传媒 / The signing round completed, but this contract cannot be activated until these execution formalities are recorded on the signature round: Countersigned copy returned.' · evidence: src/flows/signature-record.flow.ts notify_missing title and message are English literals, and the missing-formality names render in English too · carrier: #156 (src/flows/** + flow translations, in flight), for the seat to confirm · dedupe words: notify title English zh-CN, execution formalities outstanding, flow notification translation",
"carrier: none · noted, not filed: a demo re-run on a used DB drops a seeded clm_signature row (upsert key contract+method) when a user has since completed a round with the same method. This is the README-documented family (upstream objectstack#25761)."
],
"governed_text_proposal": "none: AGENTS.md ('stored display_name mirror ... never a formula') and DESIGN.md §03 mirror wording stay accurate on 18.2.0"
}
The dev measured every route 18.2.0 offers, and none gives a per-reader name (report 6439089136):
the stored mirror (current);
a formula nameField: CEL has no option-label function and no locale;
a select field as nameField: only the H1 is translated, the toast shows the raw value;
titleFormat: unreachable under ADR-0079 D7.
No app-side workaround: storing a Chinese string or choosing a locale at write time is ruled out. Filed upstream: objectstack-ai/objectstack#26608. When it ships, the fix touches src/objects/mirror.hook.ts (where the four names are composed, not contract.hook.ts), the four object files and the translations.
Activity
objectstack-fleet commentedon Oct 27, 2026
Triage — 2026-10-27
Filed from the 18.2.0 browser pass (hotclm PR #155, landed as
21f2319). Defect, user-visible, reproduced: accepted.Route: measure first. If the platform can render a name composed of select labels per reader (a formula or display template that reads translated option labels), the fix is app-side metadata. If not, the dev files the platform gap in objectstack with the measurement (maintainer rule 2026-10-26), and this card goes
pm:blockedon it. It sharessrc/objects/contract.hook.tswith #159, so it is dispatched after #159 lands.State: →
pm:queue+bug.Generated by Claude Code
objectstack-fleet commentedon Oct 27, 2026
Claim: PM loop round 17
Ruling-ref: none
Session:
session_017nzWFRUo2U7evMkPdVniAnAccount:
zhuangjianguo(the seat's linked user asGET /useranswers it; the card's assignee)Branch:
claude/issue-157-child-names-per-localeWorktree:
hotclm-issue-157Domain:
repo:hotclm(single-lane sister repo — nodomain:*)Seat:
repo:hotclm#1File surface:
src/objects/contract.hook.ts(the display_name composition) ·src/objects/{contract-version,review,signature,deviation}.object.ts· translations — measure first; on a platform gap stop and report (the seat files it) — stop on breach; explain in the reportContainer & model:
S,mode:subagent,model: opus(TIER_DEFAULT; hand-derived for a sister repo),effort: mediumClause-②: no
Metadata-protocol: none
Responsibility:
this app's child record names (what a zh-CN reader sees in toasts, lists and lookups) | possibly a platform gap | every zh-CN user saving a version, review, signature or deviationThread-read: 6437435865
Premise: re-measured by the dev on
origin/mainbc5c3e8(@objectstack 18.2.0) with README personas firstSerial constraints cleared: #159 landed (PR #163), so
contract.hook.tsis free; in flight #127 (profiles), #158 (lifecycle actions) — disjoint files.Generated by Claude Code
objectstack-fleet commentedon Oct 27, 2026
os-dev-report
{
"issue": 157,
"status": "blocked",
"branch": "claude/issue-157-child-names-per-locale",
"pr": null,
"session": "session_017nzWFRUo2U7evMkPdVniAn",
"premise_still_valid": true,
"summary": "No app-side metadata route exists on 18.2.0, so no code ships and the card blocks on a platform gap for the seat to file. Reproduced on origin/main bc5c3e8 with README personas in zh-CN: toasts, related lists and record H1 read 'v2 · Clean', 'Legal · Legal Counsel 1' and 'Wet ink · Completed'. The en reader sees the same strings. I measured three candidates in the browser on a throwaway, uncommitted edit, since restored with the HEAD blob hashes matching. A formula nameField renders the raw option value 'v2 · clean' in the zh-CN toast and in the H1 for both zh-CN and en-US, because CEL has no option-label function and no reader locale. A select nameField is the one per-reader seam, and only on the record H1 (湿签 / Wet ink): the save toast reads the raw value 'wet_ink', and the name is a single field, not a composite. titleFormat is inert: with nameField removed the registry auto-designates display_name, and the title still reads 'Legal · Legal Counsel 1' (it also adds the title-format-retired lint warning). File-surface note: the composition lives in src/objects/mirror.hook.ts, not contract.hook.ts. Composition per object: clm_contract_version 'v' + version_no + ' · ' + KIND[kind]; clm_review STAGE[stage] + ' · ' + sys_user.name, falling back to 'Unassigned'; clm_deviation clm_clause.title + ' · ' + STATUS[status]; clm_signature METHOD[method] + ' · ' + STATUS[status]. All four use English label maps inlined in the hook. A follow-up fix after the platform lands would touch mirror.hook.ts, the four object files and the translations.",
"platform_gap": {
"title": "A record name composed of select option labels cannot render in the reader's locale",
"symptom": "On 18.2.0 a zh-CN reader sees the English or raw option value in every surface that shows a record name: the save toast, related-list name column, record H1 and search. The name is built from select fields such as 'v2 · Clean', 'Wet ink · Completed' and 'Legal · Legal Counsel 1', and the zh bundle translates every option label.",
"what_was_tried_and_measured": [
"Stored mirror (current app; a before-hook writes English labels): toast 合同版本“v2 · Clean”已创建 · 审查“Legal · Legal Counsel 1”已创建 · 签署记录“Wet ink · Completed”已创建; H1 is the same in zh-CN and en-US; the related-list name column is the same; REST search=清稿 or 湿签 returns 0, while search=Clean or Wet finds the rows.",
"nameField pointing at a Field.formula with returnType text and expression 'v' + string(record.version_no) + ' · ' + record.kind: zh-CN toast 合同版本“v2 · clean”已创建; H1 'v2 · clean' in zh-CN and in en-US; REST returns version_title 'v2 · clean'.",
"nameField pointing at the select field itself (clm_signature.method): H1 reads 湿签 in zh-CN and 'Wet ink' in en-US, which is per-reader; the save toast reads 签署记录“wet_ink”已创建, the raw value; one field only, so no composite.",
"titleFormat '{stage} · {reviewer}' with nameField removed: toast and H1 still read 'Legal · Legal Counsel 1', because the registry designates display_name (ADR-0079 D7); validate adds the warning title-format-retired."
],
"seams": [
"spec/formula: packages/formula/src/stdlib.ts has no option-label function in the CEL library (it registers now/today/coalesce/joinNonEmpty/upper/lower/... only), and its header forbids host resolvers.",
"spec/formula: packages/formula/src/types.ts EvalContext.locale is a reserved channel for the template dialect's formatters only; a CEL formula field reads no reader locale.",
"spec/formula: packages/formula/src/template-engine.ts FORMATTERS = upper/lower/trim/number/currency/percent/date/datetime/truncate/default/json, with no 'label' formatter for a select value.",
"renderer: ui/packages/core/src/utils/record-title.ts getRecordDisplayName resolves the title from raw stored values; ui/packages/app-shell/src/console/AppContent.tsx recordSaveMessage (createdNamed toast) uses it.",
"renderer: ui/packages/components/src/renderers/layout/containers.tsx withOptionLabels (objectui#13103) labels a select nameField or titleFormat value on the record-page H1 only.",
"objectql: registry provisionPrimary designates nameField whenever a title-eligible field exists (ADR-0079 D7), so a deprecated titleFormat is never reached on such an object."
],
"expected_capability": "A display-only record name composed of select option labels that renders in each reader's locale on every name surface: toast, related list, lookup chip, search result and H1. Two possible shapes: a CEL or template label function such as label(record.kind) evaluated with the request locale for a display-only formula nameField, or a localized title template that the resolver renders. In either shape a stored field stays available for search and sort. The design belongs to the platform.",
"repro": "hotclm origin/main bc5c3e8 on @objectstack/* 18.2.0, pnpm demo:zh. As Legal Counsel 1 (clm_legal_counsel) in a zh-CN browser: contract MSA-2026-0001 > 版本 > 新建, version 2, kind 清稿, upload a file > 创建.",
"dedupe_words": [
"record title option label locale",
"nameField formula select label translation",
"getRecordDisplayName option label",
"picklist label function CEL",
"titleFormat withOptionLabels toast"
]
},
"tests": "Browser: Chromium at /opt/pw-browsers/chromium; README personas created by create-user, sys_user_position, set-user-manager and change-password, then a demo re-run. BEFORE (bc5c3e8, zh-CN), Legal Counsel 1: version POST 201, toast 合同版本“v2 · Clean”已创建, related list 'v2 · Clean | 2 | 清稿'; review POST 201, toast 审查“Legal · Legal Counsel 1”已创建; wet-ink round POST 201, toast 签署记录“Wet ink · Completed”已创建. Records Manager: version on DPA-2026-0002 POST 201, toast “v2 · Clean”; signature has no 新建 button, so NOT MEASURED (not permitted). H1 in zh-CN and en-US: 'v2 · Clean' / 'Legal · Legal Counsel 1' / 'Wet ink · Completed'. Command palette search 'Clean' returns no results in both locales: lookup surface NOT MEASURED, because the palette does not list these objects. REST search as Legal Counsel 1: Clean 2, 清稿 0, Wet 3, 湿签 0. CANDIDATES: readings are in platform_gap; the patch is saved at /tmp/claude-0/-home-claude/bc53be1b-6c43-5271-bc20-52035f64763b/scratchpad/issue-157/candidate-experiment.patch and restored; the HEAD blob hashes match and git diff HEAD is empty. After: n/a, no code change.",
"gates": "n/a: no diff on the branch (git status clean at bc5c3e8). pnpm install exit 0. The candidate boot printed the title-format-retired warning, which is why the titleFormat route is excluded.",
"dogfood_battery": "n/a: no PR",
"mcp_calls": "0",
"api_writes": "1: this os-dev-report comment via post-stamped (POST issues/157/comments). No push, no PR.",
"open_questions": [],
"out_of_scope_findings": [
"class: a · reach: browser toast in a zh-CN console after a completed wet-ink round reads 'Execution formalities outstanding: 主服务协议 — 静谧传媒 / The signing round completed, but this contract cannot be activated until these execution formalities are recorded on the signature round: Countersigned copy returned.' · evidence: src/flows/signature-record.flow.ts notify_missing title and message are English literals, and the missing-formality names render in English too · carrier: #156 (src/flows/** + flow translations, in flight), for the seat to confirm · dedupe words: notify title English zh-CN, execution formalities outstanding, flow notification translation",
"carrier: none · noted, not filed: a demo re-run on a used DB drops a seeded clm_signature row (upsert key contract+method) when a user has since completed a round with the same method. This is the README-documented family (upstream objectstack#25761)."
],
"governed_text_proposal": "none: AGENTS.md ('stored display_name mirror ... never a formula') and DESIGN.md §03 mirror wording stay accurate on 18.2.0"
}
objectstack-fleet commentedon Oct 27, 2026
Blocked — platform gap · 2026-10-27
The dev measured every route 18.2.0 offers, and none gives a per-reader name (report 6439089136):
nameField: CEL has no option-label function and no locale;nameField: only the H1 is translated, the toast shows the raw value;titleFormat: unreachable under ADR-0079 D7.No app-side workaround: storing a Chinese string or choosing a locale at write time is ruled out. Filed upstream: objectstack-ai/objectstack#26608. When it ships, the fix touches
src/objects/mirror.hook.ts(where the four names are composed, notcontract.hook.ts), the four object files and the translations.State:
pm:dispatched→pm:blocked, assignee cleared.Generated by Claude Code