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
view.columns / view.sort / view.tabs repeater row properties show English column heads in every locale — the #17508 ruling-A landing for the three view repeaters #19955
Filing gate: ③ a task the maintainer directed. The maintainer's words, in the chat of session session_019c3Hi6ZMU1p6m6aA6Bz45d while handing over PR #19917 for landing: 「合并后还要补一张本地化跟进卡」. It is also a class (a) defect from the #17507 round (report 5800494895).
Hand that acts: the next domain:spec claim, dispatched in the shape ruling A of #17508 already settled (below).
Dedupe (including closed), run by the filing seat: view repeater columns sort tabs row properties localization view.form.ts metadataForms titles English Studio → 2 hits (#8042, #5084; neither is this); repeater-row-properties view enumerates no repeater row properties translation → 4 hits (#17507, closed by PR #19917 — the titles half; #17508, closed by PR #19345 — the ruling, which fenced these three repeaters out; #17506 and #17505 — sibling carriers, done). No open card covers it.
The defect
PR #19917 (merged as f5a7250b7a) gave the row items of view.columns (14 properties), view.tabs (9) and view.sort (2) an English JSON Schema title. packages/spec/src/ui/view.form.ts enumerates no row children for these three repeaters. So os i18n extract emits no metadataForms.view.fields key for any of the 25 row properties, and Studio in zh-CN / ja-JP / es-ES now shows the new English titles as the column heads. Before the merge those heads were raw keys.
packages/platform-objects/src/apps/translations/repeater-row-properties.test.ts still asserts that view is OUTSIDE its population ("view enumerates no repeater row properties yet"). That pin is the one to flip.
Already ruled — the dispatch shape is inherited, not re-asked
#17508 ruling A (decision batch #120 item 3, maintainer 「17508 A AI负责翻译就行」): one coherent landing — the *.form.ts child enumeration plus all four catalogs (en + AI-authored zh-CN / ja-JP / es-ES) in the same PR, each child's label equal to the item schema's own .meta({ title }). PR #19345 applied that ruling to fifteen carriers and fenced these three out to #17507 (report 5749897882: 「#17507 must add the leaves with the titles」). This card is that remainder.
Expected landing: packages/spec/src/ui/view.form.ts (25 row children), the four translation catalogs, and the repeater-row-properties.test.ts population (view moves inside it; the test's last case — a translated leaf is never an en echo — then covers these leaves too). Reuse the catalog's existing renderings, as PR #19345's review record did.
Triage: lands in the view metadata-form enumeration ⇒ domain:spec, bug, priority:p2, pm:queue; rationale: PR #19917 (merged f5a7250b7a) gave the 25 row properties of view.columns / view.tabs / view.sort English titles, but view.form.ts enumerates no row children for them, so os i18n extract emits no key and Studio shows those English titles as column heads in zh-CN / ja-JP / es-ES — a user-visible localisation gap the maintainer explicitly asked to be filed (「合并后还要补一张本地化跟进卡」), with the landing shape already ruled (#17508 ruling A).
Claim: seat 5 serial dispatch, one dev at a time
Session: session_01Sfe5YjBLwB9J3y8fvm2xq1
Branch: claude/issue-19955-view-repeater-row-i18n
Domain: domain:spec
Seat: domain:spec#5 (seat post #19357)
Ruling executed: #17508 ruling A (decision batch #120 item 3, maintainer 「17508 A AI负责翻译就行」), in the shape triage 5809645916 names. This card is the maintainer-directed follow-up (「合并后还要补一张本地化跟进卡」).
File surface:
packages/spec/src/ui/view.form.ts (the columns / sort / tabs repeater row children);
the four translation catalogs, regenerated where they are generated;
Stop and report on a breach.
Container & model: mode:subagent, default tier. The metadata-form enumeration and translations change no accept set.
Clause-②: no
Thread-read: 5809645916
Serial constraints read at 2026-09-24T11:04Z: among the 32 open PRs, none touches view.form.ts, the translation catalogs or repeater-row-properties.test.ts. PRs #19919, #19906, #19861 and #19809 touch packages/spec/src/ui/view.zod.ts, where the row items' titles live. The dev checks whether any of them moves a columns / tabs / sort row title.
{
"issue": 19955,
"status": "blocked",
"branch": "claude/issue-19955-view-repeater-row-i18n",
"pr": "#19968",
"head_sha": "eddaba6c2801842b0036791454e4f75d909f78be",
"session": "session_01Sfe5YjBLwB9J3y8fvm2xq1 (subagent of the dispatching seat; the parent's session id)",
"premise_still_valid": true,
"summary": "All in-surface work is done and pushed as draft PR #19968. It follows the ruled shape. (1) view.form.ts enumerates 25 row children: columns 14, sort 2, tabs 9. Each label equals the item schema's own .meta({ title }): 25 of 25 match on the built dist, same set and same order as the schema, no child declares a type. (2) The four metadata-forms catalogs gain exactly those 25 keys each (100 leaves). zh-CN / ja-JP / es-ES are hand-authored with 0 en-echoes. (3) repeater-row-properties.test.ts now counts view inside its derived population, with lit controls for view:columns / view:sort / view:tabs. BLOCKED on one thing only the seat can lift. packages/platform-objects/src/apps/translations/object-lifecycle-panel-echo-decisions.test.ts line 1115 pins the number of translated metadata-form .label leaves at 584 per locale. This landing adds 25 translated labels per locale, so it reads 609: 'zh-CN positive control: expected 609 to be 584'. That file is outside the claim's declared file surface, and the claim says stop and report on a breach, so I did NOT edit it. Test Core will be red on that one assertion. The fix is mechanical and its own comment prescribes it: the control 'moves by exactly the number of rows that landed'. Change the literal 584 to 609 and add a sentence to its comment. #19673 and #19841 moved the same literal in their own PRs, and no open PR holds the file. Premise re-checked on base 3b56070: view.form.ts declared columns (:40), sort (:42) and tabs (:132) as bare repeaters, and the pin asserted view outside its population at :147-149. The assignee arrived set to os-justin by the dispatch; I never wrote it. The newest Claim: (5812850132) names this branch.",
"census": {
"instrument": "z.toJSONSchema(getMetadataTypeSchema('view'), { unrepresentable: 'any', io: 'input' }) over the built packages/spec dist. Union arms are kept as separate candidates, and each property title is read before $ref deref. This is the repeater-item-titles.test.ts derivation. [REMOVED] tombstones are excluded (none present).",
"tree": "objectstack-ai/objectstack at base 3b56070; re-read at head eddaba6 with identical output",
"view:columns": "14, all titled: field Field, label Label, width Width (px), align Alignment, hidden Hidden, sortable Sortable, resizable Resizable, wrap Wrap Text, type Renderer Type, pinned Pinned, summary Summary, prefix Prefix, link Primary Link, action Click Action. The resolved candidates include an array-of-string arm beside the object arm, plus an integer on the form arm.",
"view:sort": "2, titled: field Field, order Direction",
"view:tabs": "9, titled: name Name, label Label, icon Icon, view List View, filter Filter, order Display Order, pinned Pinned, isDefault Default Tab, visible Visible",
"total": "25. This equals the card's 14 + 9 + 2.",
"controls": "Lit: dashboard:header.actions resolves to label/actionUrl/actionType/icon, all titled. Dark: a fabricated type resolves to no schema. Exit 0 on both runs.",
"open_prs_on_view_zod": "#19919, #19906, #19861 and #19809 all touch packages/spec/src/ui/view.zod.ts, but none changes a columns / tabs / sort row item or its title. I checked their hunk ranges, and I ran a regex over every changed line (ListColumnSchema|ViewTabSchema|this sort entry|this list column|this view tab|.meta(|tabs:|columns:|sort:). It matched 0 lines in each PR: 21, 89, 66 and 210 changed lines. The same regex matches 64 lines of base view.zod.ts (lit control) and 0 on a fabricated line set (dark control). #19809's nearest hunk is at KanbanConfigSchema (kanban limit), not ViewTabSchema. Open-PR map re-taken first-hand: 32 open PRs, 420 file rows. No open PR holds view.form.ts, the four catalogs, repeater-row-properties.test.ts or object-lifecycle-panel-echo-decisions.test.ts. The same map resolves view.zod.ts to exactly those four PRs (firing control)."
},
"keys_added": "metadataForms.view.fields: columns.field, columns.label, columns.width, columns.align, columns.hidden, columns.sortable, columns.resizable, columns.wrap, columns.type, columns.pinned, columns.summary, columns.prefix, columns.link, columns.action, sort.field, sort.order, tabs.name, tabs.label, tabs.icon, tabs.view, tabs.filter, tabs.order, tabs.pinned, tabs.isDefault, tabs.visible. Each was added to en / zh-CN / ja-JP / es-ES. Delta against the base catalogs over all 11 generated files: +100 / -0 / ~0 leaves, all under view.fields. The objects and source-hashes files are unchanged. Attribution: pnpm i18n:extract (generator) emitted the en leaves plus the fill copies. The 75 translated values are hand-written, as AGENTS.md allows for translated-locale values. A second extract kept them and dropped the 25 fill hashes it had recorded per locale. check:i18n reports all 9 bundle sets in sync.",
"renderings": {
"method": "Each new leaf was compared against every base-catalog leaf, in both metadata-forms and objects, with the same en string: reuse 38, no exact-string precedent 36, competing 1, en-echo 0.",
"reused": [
"columns.field 'Field': 字段 / フィールド / Campo",
"columns.label 'Label': 显示名称 / 表示名 / Etiqueta",
"columns.hidden 'Hidden': 隐藏 / 非表示 / Oculta",
"columns.sortable 'Sortable': 可排序 / 並び替え可能 / Ordenable",
"columns.resizable 'Resizable': 可调整大小 / サイズ変更可 / Redimensionable",
"columns.prefix 'Prefix': 前缀 / プレフィックス / Prefijo",
"sort.field 'Field': 字段 / フィールド / Campo",
"sort.order 'Direction': 排序方向 / 並び方向 / Dirección",
"tabs.name 'Name': 名称 / 名前 / Nombre",
"tabs.label 'Label': 显示名称 / 表示名 / Etiqueta",
"tabs.icon 'Icon': 图标 / アイコン / Icono",
"tabs.filter 'Filter': 筛选 / フィルター / Filtro"
],
"invented": [
"columns.width 'Width (px)': 宽度(像素) / 幅(ピクセル) / Ancho (px) (from: Width = 宽度/幅/Ancho (page.regions.width) + the catalog's unit-in-parens style (Timeout (ms) = 超时(毫秒), ms = ミリ秒 in 4 of 5 ja leaves, es keeps the abbreviation))",
"columns.align 'Alignment': 对齐方式 / 配置 / Alineación (from: no catalog precedent for alignment)",
"columns.wrap 'Wrap Text': 自动换行 / テキストの折り返し / Ajustar texto (from: no catalog precedent for wrapping)",
"columns.type 'Renderer Type': 渲染器类型 / レンダラータイプ / Tipo de renderizador (from: the catalog's X Type pattern (Action Type = 操作类型 / 操作タイプ / Tipo de acción))",
"columns.pinned 'Pinned': 固定 / 固定 / Fijada (from: no catalog precedent for pinning; one rendering shared with tabs.pinned (columna and pestaña are both feminine))",
"columns.summary 'Summary': 汇总 / 集計 / Resumen (from: Summary Operations = 汇总操作 / 集計操作 / Operaciones de resumen)",
"columns.link 'Primary Link': 主链接 / 主リンク / Enlace principal (from: Primary = 主 (主属业务单元 / 主所属) and principal (Unidad de negocio principal))",
"columns.action 'Click Action': 点击操作 / クリック時のアクション / Acción al hacer clic (from: Action = 操作 / アクション / Acción (action.label, the metadata type the value names))",
"tabs.view 'List View': 列表视图 / リストビュー / Vista de lista (from: View = 视图 / ビュー / Vista (view.label))",
"tabs.order 'Display Order': 显示顺序 / 表示順 / Orden de visualización (from: Order = 排序 / 並び順 / Orden)",
"tabs.pinned 'Pinned': 固定 / 固定 / Fijada (from: shared with columns.pinned)",
"tabs.isDefault 'Default Tab': 默认标签页 / 既定のタブ / Pestaña predeterminada (from: Tabs = 标签页 / タブ / Pestañas (view.tabs) + Default = 默认 / 既定 (既定の選択肢) / predeterminado)"
],
"departure": "tabs.visible 'Visible': zh-CN 可见 and ja-JP 表示 reuse action.visible. es-ES 'Visibilidad' is invented. The catalog's one precedent, 'Condición de visibilidad', renders action.visible, which is a CEL predicate, while tabs.visible is a boolean. And 'Visible' would be an en echo the pin refuses.",
"judgement_calls": "es 'Oculta' (feminine, for columna) rather than 'Oculto'; both exist in the catalog. ja uses タイプ, the catalog's majority form in 'X Type' compounds, and 既定 rather than デフォルト by the same majority. ja 'px' is spelled ピクセル, following ミリ秒 in 4 of 5 ja 'ms' leaves."
},
"pins": "repeater-row-properties.test.ts: 8/8 green at head. The survey lit list gains 'view', and a lit control asserts view:columns, view:sort and view:tabs are in CARRIERS. The dark view assertion is removed because view is now inside the population. Its en-echo case covers the 75 new translated leaves automatically, since the population is derived from the forms, which the suite reads from the spec dist. ABLATION (catalog leg; the catalogs are source to this suite, so no build is involved): node scripts/ablation-replace.mjs planted es-ES tabs.visible 'Visibilidad' as 'Visible'. The anchor went x1 to x0 and the replacement x0 to x1, and the blob changed from 03ececb5625b to 3af6c70b20dd. The mutated run gave '1 failed | 7 passed' on 'translated locales carry their own text for every leaf, not a copy of the source', naming 'es-ES view:tabs.visible ("Visible")'. The tool's restore proved the blob equals HEAD (03ececb5625b) and git diff HEAD is empty. The restored run gave 8/8. Only es-ES was planted, and only that leaf.",
"changeset": ".changeset/19955-view-repeater-row-i18n.md: '@objectstack/spec' patch, '@objectstack/platform-objects' patch. Both packages publish (private unset); spec ships dist, which carries viewForm, and platform-objects ships dist, which carries the catalogs. The level comes from AGENTS.md Post-Task Checklist step 3: a bug fix in a released package takes a patch, and this card is a bug. Clause-② no raises no minor floor (check-changeset-no-major exit 0). For the seat: #19345 graded the same kind of diff minor/minor as a feature. The fixed group versions in lockstep, so only the release's highest bump matters. The body carries no counts, no universal claims, and the Clause-② line.",
"tests": "All readings are at head eddaba6 on objectstack-ai/objectstack. Every exit code was captured before any pipe, and every build and test went through os-verify-lock with OS_VERIFY_LOCK_SLOT=issue-19955; no exit 99 occurred. BUILD: full turbo run build --filter=!@objectstack/docs --concurrency=2, VERDICT command-exit 0. SPEC: pnpm --filter @objectstack/spec test gives 'Test Files 529 passed (529) / Tests 15602 passed | 1 todo', which includes metadata-form-zod-reconciliation (the view nested lists are now judged against ListColumnSchema / ViewTabSchema / the sort entry) and repeater-item-titles. typecheck exit 0. check:generated gives 'All 15 generated artifacts are up to date'. PLATFORM-OBJECTS: test gives 'Test Files 1 failed | 53 passed (54) / Tests 1 failed | 882 passed (883)'. The one failure is object-lifecycle-panel-echo-decisions.test.ts 'zh-CN positive control: expected 609 to be 584', the blocked item. typecheck exit 0. CONSUMERS (they read viewForm or the catalogs): lint validate-predicate-path-refs 54/54, metadata-protocol protocol.meta-types-* 3 files 38/38, cli --project unit on the i18n-coverage / i18n-extract-emitted-files / i18n-extract files 49/49. i18n-extract-metadata-forms-flag.e2e is in the integration tier and is declared to CI. GATES: node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack derived 84 commands (7 paths vs merge base 3b56070); all 84 ran and exit 0. --ran reports '84 derived famil(ies) accounted for — 84 run, 0 NOT-MEASURED (a DERIVED zero ...)'. check:i18n reports 'OK (9 package(s) — all bundles in sync, no undeclared authoring keys)', check:i18n-stale-fill '0 stale-fill', and check:nul-bytes 'OK (scanned 9373 text file(s) ...)'. NOT MEASURED: scripts/check-issue-citations.mjs --census, because the workflow supplies a value (dispatch-gates prints it as such). LIVE CITATION GATE: node scripts/check-issue-citations.mjs --base 3b5607019f gives 'citations judged: 3 across 5 file(s) / 3 resolves'. LINT, as a declared narrowing rather than a repo-wide run: eslint --no-inline-config --format json over the 6 touched .ts files gives 6 files, 0 errors, 0 warnings. (1) Population from eslint's own config: none of the 6 is ignored, and --print-config resolves 5 or 6 rules for each. (2) The count comes from the JSON output. (3) Invariance: the resolved config has no parserOptions.project or projectService, and eslint.config.mjs states it never enables type-aware linting, so this diff cannot move a verdict on any untouched file. The .changeset .md is not linted.",
"ci": "Read via GET /commits/eddaba6c28/check-runs at 2026-09-24T12:04:42Z, latest run per name: 32 names, 12 success, 3 skipped, 17 in_progress (Build Core, Dogfood x4, Lint & Repo Gates, Temporal Conformance, Test Core 1-6, Type Check x4). Check Changeset is success. I expect Test Core to go red on the blocked assertion; the PM owns convergence.",
"mcp_calls": "0 — no MCP GitHub tool was called, read or write.",
"api_writes": "2 relay writes, both as objectstack-fleet[bot]. (1) pr_create through scripts/pm/fleet-write/dispatch.mjs (transport dispatch, run 35996634038, success), giving POST /repos/objectstack-ai/objectstack/pulls with draft forced. The payload came from a file; I read the body back and it is byte-identical (3298 chars). (2) This os-dev-report comment through scripts/pm/post-stamped.mjs from a detached worktree at origin/main, after --route read transport dispatch. Plus 4 git pushes: the empty-branch probe and three work commits. Zero label, ready, auto-merge or merge writes, as the dispatch ordered. Reads were REST GETs only.",
"open_questions": [
{
"question": "Extend the claim's file surface to packages/platform-objects/src/apps/translations/object-lifecycle-panel-echo-decisions.test.ts? Its positive control pins 584 translated metadata-form .label leaves per locale, and this landing makes it 609.",
"options": [
"A: extend the surface and move the literal 584 to 609, adding a comment sentence naming this card. It is one line plus a comment, in a file no open PR holds, and a patch round or the seat commits it on this branch.",
"B: keep the surface. #19968 stays red on Test Core, and the ruled one coherent landing cannot land."
],
"recommendation": "A. The pin is built to move by exactly the rows a landing adds, #19673 and #19841 moved it in their own PRs, and nothing else in the derived gate set or the two suites is red."
},
{
"question": "view.columns is a union with the array-of-string arm first. Does enumerating its row children stand as ruled, given what the pinned objectui does with string-array values?",
"options": [
"A: land as ruled. Object-array values keep the same column set and order and gain localisable heads. The designer's ViewVariantInspector prunes columns (VIEW_CURATED_FIELDS), so only the generic SchemaForm fallback renders this repeater.",
"B: land sort and tabs only, leaving columns heads English. That departs from the ruled shape.",
"C: land as ruled and also file an objectui card, so that a repeater whose union resolves to a scalar-items arm does not offer object-row children."
],
"recommendation": "A, with C at the seat's discretion. Here is the reading at .objectui-sha 62597c588072, from SchemaForm.tsx source and not measured in a browser. repeaterItemSchema resolves the union by value. For an empty or string-array value it picks the array-of-string arm, which is first, and ties break on order. Before this PR, such rows had no inputs (fields derived from a string item = none). Now they show the declared inputs with a {} sub-schema each. Editing one spreads the string into an object ({0:'n',...,field}), which the strict ListColumnSchema refuses at save: loud, not silent. On an empty value, the first Add pushes an object row and the object arm then renders, as before."
}
],
"out_of_scope_findings": [
"noted, not filed (drift, not a defect): packages/spec/src/kernel/repeater-item-titles.test.ts's header still says the bundle overlay 'only ever REPLACES a title that is already there', but setSchemaTitleAtPath returns { ...node, title } unconditionally. The #17508 report named #17507 as that file's carrier and it did not change it; carrier: none (承接者:无). It affects no verdict."
],
"cleanup": "Dev worktree /home/user/objectstack-issue-19955 removed without --force after rm -rf node_modules. At removal git status was empty and the local head equalled origin/claude/issue-19955-view-repeater-row-i18n (eddaba6). The report-posting worktree /home/user/objectstack-issue-19955-post (detached at origin/main 3b56070) is removed right after this post. No dev server or monitor was started; the background build, suite and gate jobs all exited before this report. Scratch files are only in the session scratchpad issue-19955/."
}
Claim addendum and seat rulings on the dev report's open questions (5813748776). Seat 5 (domain:spec, session_01Sfe5YjBLwB9J3y8fvm2xq1), 2026-09-24T12:08Z, on PR #19968.
Q1 — the counting pin outside the declared surface: A. The file surface is extended.
packages/platform-objects/src/apps/translations/object-lifecycle-panel-echo-decisions.test.ts pins the translated metadata-form .label leaves per locale.
Activity
objectstack-fleet commentedon Sep 24, 2026
分诊首次定级:
priority:p2·bug·domain:spec·pm:queue—— 维护者要求补上的本地化跟进卡,做法已由 #17508 裁定 A 定好Path:
packages/spec/src/ui/view.form.ts(columns/sort/tabs三个 repeater 的行子项)+ 四份翻译目录 +packages/platform-objects/src/apps/translations/repeater-row-properties.test.tsTriage: lands in the view metadata-form enumeration ⇒
domain:spec,bug,priority:p2,pm:queue; rationale: PR #19917 (mergedf5a7250b7a) gave the 25 row properties ofview.columns/view.tabs/view.sortEnglish titles, butview.form.tsenumerates no row children for them, soos i18n extractemits no key and Studio shows those English titles as column heads inzh-CN/ja-JP/es-ES— a user-visible localisation gap the maintainer explicitly asked to be filed (「合并后还要补一张本地化跟进卡」), with the landing shape already ruled (#17508 ruling A).分诊席(
session_01Tw7jnJinGHvoGSi8aFkhPJ,座位贴 #6015),2026-09-24T07:19Z。⛔ 不认领、不派发。本席读完了卡面(本卡尚无评论),并在最新的main(f5a7250b7a)上核对了前提。本席核对
view.form.ts里的columns(:40)、sort(:42)、tabs(:132)都只声明为type: 'repeater',没有任何行子项。repeater-row-properties.test.ts:147-149仍断言view不在范围内("view enumerates no repeater row properties yet")。落地时要翻转的正是这一条。domain:spec卡里没有改view.form.ts的。定级说明
*.form.ts的子项枚举 + 四份目录(en加上 AI 翻译的zh-CN/ja-JP/es-ES),每个子项的label等于该项 schema 自己的.meta({ title })。PR feat(spec): a repeater property panel names its columns in every locale, not only English #19345 已经按这个做法处理了 15 个 repeater,本卡是被它划出去的剩余三个。Generated by Claude Code
objectstack-fleet commentedon Sep 24, 2026
Claim: seat 5 serial dispatch, one dev at a time
Session:
session_01Sfe5YjBLwB9J3y8fvm2xq1Branch:
claude/issue-19955-view-repeater-row-i18nDomain:
domain:specSeat:
domain:spec#5(seat post #19357)Ruling executed: #17508 ruling A (decision batch #120 item 3, maintainer 「17508 A AI负责翻译就行」), in the shape triage
5809645916names. This card is the maintainer-directed follow-up (「合并后还要补一张本地化跟进卡」).File surface:
packages/spec/src/ui/view.form.ts(thecolumns/sort/tabsrepeater row children);packages/platform-objects/src/apps/translations/repeater-row-properties.test.ts;.changeset/.Stop and report on a breach.
Container & model:
mode:subagent, default tier. The metadata-form enumeration and translations change no accept set.Clause-②: no
Thread-read: 5809645916
Serial constraints read at 2026-09-24T11:04Z: among the 32 open PRs, none touches
view.form.ts, the translation catalogs orrepeater-row-properties.test.ts. PRs #19919, #19906, #19861 and #19809 touchpackages/spec/src/ui/view.zod.ts, where the row items' titles live. The dev checks whether any of them moves acolumns/tabs/sortrow title.Generated by Claude Code
objectstack-fleet commentedon Sep 24, 2026
os-dev-report
{
"issue": 19955,
"status": "blocked",
"branch": "claude/issue-19955-view-repeater-row-i18n",
"pr": "#19968",
"head_sha": "eddaba6c2801842b0036791454e4f75d909f78be",
"session": "session_01Sfe5YjBLwB9J3y8fvm2xq1 (subagent of the dispatching seat; the parent's session id)",
"premise_still_valid": true,
"summary": "All in-surface work is done and pushed as draft PR #19968. It follows the ruled shape. (1) view.form.ts enumerates 25 row children: columns 14, sort 2, tabs 9. Each label equals the item schema's own .meta({ title }): 25 of 25 match on the built dist, same set and same order as the schema, no child declares a type. (2) The four metadata-forms catalogs gain exactly those 25 keys each (100 leaves). zh-CN / ja-JP / es-ES are hand-authored with 0 en-echoes. (3) repeater-row-properties.test.ts now counts view inside its derived population, with lit controls for view:columns / view:sort / view:tabs. BLOCKED on one thing only the seat can lift. packages/platform-objects/src/apps/translations/object-lifecycle-panel-echo-decisions.test.ts line 1115 pins the number of translated metadata-form .label leaves at 584 per locale. This landing adds 25 translated labels per locale, so it reads 609: 'zh-CN positive control: expected 609 to be 584'. That file is outside the claim's declared file surface, and the claim says stop and report on a breach, so I did NOT edit it. Test Core will be red on that one assertion. The fix is mechanical and its own comment prescribes it: the control 'moves by exactly the number of rows that landed'. Change the literal 584 to 609 and add a sentence to its comment. #19673 and #19841 moved the same literal in their own PRs, and no open PR holds the file. Premise re-checked on base 3b56070: view.form.ts declared columns (:40), sort (:42) and tabs (:132) as bare repeaters, and the pin asserted view outside its population at :147-149. The assignee arrived set to os-justin by the dispatch; I never wrote it. The newest Claim: (5812850132) names this branch.",
"census": {
"instrument": "z.toJSONSchema(getMetadataTypeSchema('view'), { unrepresentable: 'any', io: 'input' }) over the built packages/spec dist. Union arms are kept as separate candidates, and each property title is read before $ref deref. This is the repeater-item-titles.test.ts derivation. [REMOVED] tombstones are excluded (none present).",
"tree": "objectstack-ai/objectstack at base 3b56070; re-read at head eddaba6 with identical output",
"view:columns": "14, all titled: field Field, label Label, width Width (px), align Alignment, hidden Hidden, sortable Sortable, resizable Resizable, wrap Wrap Text, type Renderer Type, pinned Pinned, summary Summary, prefix Prefix, link Primary Link, action Click Action. The resolved candidates include an array-of-string arm beside the object arm, plus an integer on the form arm.",
"view:sort": "2, titled: field Field, order Direction",
"view:tabs": "9, titled: name Name, label Label, icon Icon, view List View, filter Filter, order Display Order, pinned Pinned, isDefault Default Tab, visible Visible",
"total": "25. This equals the card's 14 + 9 + 2.",
"controls": "Lit: dashboard:header.actions resolves to label/actionUrl/actionType/icon, all titled. Dark: a fabricated type resolves to no schema. Exit 0 on both runs.",
"open_prs_on_view_zod": "#19919, #19906, #19861 and #19809 all touch packages/spec/src/ui/view.zod.ts, but none changes a columns / tabs / sort row item or its title. I checked their hunk ranges, and I ran a regex over every changed line (ListColumnSchema|ViewTabSchema|this sort entry|this list column|this view tab|.meta(|tabs:|columns:|sort:). It matched 0 lines in each PR: 21, 89, 66 and 210 changed lines. The same regex matches 64 lines of base view.zod.ts (lit control) and 0 on a fabricated line set (dark control). #19809's nearest hunk is at KanbanConfigSchema (kanban limit), not ViewTabSchema. Open-PR map re-taken first-hand: 32 open PRs, 420 file rows. No open PR holds view.form.ts, the four catalogs, repeater-row-properties.test.ts or object-lifecycle-panel-echo-decisions.test.ts. The same map resolves view.zod.ts to exactly those four PRs (firing control)."
},
"keys_added": "metadataForms.view.fields: columns.field, columns.label, columns.width, columns.align, columns.hidden, columns.sortable, columns.resizable, columns.wrap, columns.type, columns.pinned, columns.summary, columns.prefix, columns.link, columns.action, sort.field, sort.order, tabs.name, tabs.label, tabs.icon, tabs.view, tabs.filter, tabs.order, tabs.pinned, tabs.isDefault, tabs.visible. Each was added to en / zh-CN / ja-JP / es-ES. Delta against the base catalogs over all 11 generated files: +100 / -0 / ~0 leaves, all under view.fields. The objects and source-hashes files are unchanged. Attribution:
pnpm i18n:extract(generator) emitted the en leaves plus the fill copies. The 75 translated values are hand-written, as AGENTS.md allows for translated-locale values. A second extract kept them and dropped the 25 fill hashes it had recorded per locale. check:i18n reports all 9 bundle sets in sync.","renderings": {
"method": "Each new leaf was compared against every base-catalog leaf, in both metadata-forms and objects, with the same en string: reuse 38, no exact-string precedent 36, competing 1, en-echo 0.",
"reused": [
"columns.field 'Field': 字段 / フィールド / Campo",
"columns.label 'Label': 显示名称 / 表示名 / Etiqueta",
"columns.hidden 'Hidden': 隐藏 / 非表示 / Oculta",
"columns.sortable 'Sortable': 可排序 / 並び替え可能 / Ordenable",
"columns.resizable 'Resizable': 可调整大小 / サイズ変更可 / Redimensionable",
"columns.prefix 'Prefix': 前缀 / プレフィックス / Prefijo",
"sort.field 'Field': 字段 / フィールド / Campo",
"sort.order 'Direction': 排序方向 / 並び方向 / Dirección",
"tabs.name 'Name': 名称 / 名前 / Nombre",
"tabs.label 'Label': 显示名称 / 表示名 / Etiqueta",
"tabs.icon 'Icon': 图标 / アイコン / Icono",
"tabs.filter 'Filter': 筛选 / フィルター / Filtro"
],
"invented": [
"columns.width 'Width (px)': 宽度(像素) / 幅(ピクセル) / Ancho (px) (from: Width = 宽度/幅/Ancho (page.regions.width) + the catalog's unit-in-parens style (Timeout (ms) = 超时(毫秒), ms = ミリ秒 in 4 of 5 ja leaves, es keeps the abbreviation))",
"columns.align 'Alignment': 对齐方式 / 配置 / Alineación (from: no catalog precedent for alignment)",
"columns.wrap 'Wrap Text': 自动换行 / テキストの折り返し / Ajustar texto (from: no catalog precedent for wrapping)",
"columns.type 'Renderer Type': 渲染器类型 / レンダラータイプ / Tipo de renderizador (from: the catalog's X Type pattern (Action Type = 操作类型 / 操作タイプ / Tipo de acción))",
"columns.pinned 'Pinned': 固定 / 固定 / Fijada (from: no catalog precedent for pinning; one rendering shared with tabs.pinned (columna and pestaña are both feminine))",
"columns.summary 'Summary': 汇总 / 集計 / Resumen (from: Summary Operations = 汇总操作 / 集計操作 / Operaciones de resumen)",
"columns.link 'Primary Link': 主链接 / 主リンク / Enlace principal (from: Primary = 主 (主属业务单元 / 主所属) and principal (Unidad de negocio principal))",
"columns.action 'Click Action': 点击操作 / クリック時のアクション / Acción al hacer clic (from: Action = 操作 / アクション / Acción (action.label, the metadata type the value names))",
"tabs.view 'List View': 列表视图 / リストビュー / Vista de lista (from: View = 视图 / ビュー / Vista (view.label))",
"tabs.order 'Display Order': 显示顺序 / 表示順 / Orden de visualización (from: Order = 排序 / 並び順 / Orden)",
"tabs.pinned 'Pinned': 固定 / 固定 / Fijada (from: shared with columns.pinned)",
"tabs.isDefault 'Default Tab': 默认标签页 / 既定のタブ / Pestaña predeterminada (from: Tabs = 标签页 / タブ / Pestañas (view.tabs) + Default = 默认 / 既定 (既定の選択肢) / predeterminado)"
],
"departure": "tabs.visible 'Visible': zh-CN 可见 and ja-JP 表示 reuse action.visible. es-ES 'Visibilidad' is invented. The catalog's one precedent, 'Condición de visibilidad', renders action.visible, which is a CEL predicate, while tabs.visible is a boolean. And 'Visible' would be an en echo the pin refuses.",
"judgement_calls": "es 'Oculta' (feminine, for columna) rather than 'Oculto'; both exist in the catalog. ja uses タイプ, the catalog's majority form in 'X Type' compounds, and 既定 rather than デフォルト by the same majority. ja 'px' is spelled ピクセル, following ミリ秒 in 4 of 5 ja 'ms' leaves."
},
"pins": "repeater-row-properties.test.ts: 8/8 green at head. The survey lit list gains 'view', and a lit control asserts view:columns, view:sort and view:tabs are in CARRIERS. The dark
viewassertion is removed because view is now inside the population. Its en-echo case covers the 75 new translated leaves automatically, since the population is derived from the forms, which the suite reads from the spec dist. ABLATION (catalog leg; the catalogs are source to this suite, so no build is involved):node scripts/ablation-replace.mjsplanted es-ES tabs.visible 'Visibilidad' as 'Visible'. The anchor went x1 to x0 and the replacement x0 to x1, and the blob changed from 03ececb5625b to 3af6c70b20dd. The mutated run gave '1 failed | 7 passed' on 'translated locales carry their own text for every leaf, not a copy of the source', naming 'es-ES view:tabs.visible ("Visible")'. The tool's restore proved the blob equals HEAD (03ececb5625b) and git diff HEAD is empty. The restored run gave 8/8. Only es-ES was planted, and only that leaf.","changeset": ".changeset/19955-view-repeater-row-i18n.md: '@objectstack/spec' patch, '@objectstack/platform-objects' patch. Both packages publish (private unset); spec ships dist, which carries viewForm, and platform-objects ships dist, which carries the catalogs. The level comes from AGENTS.md Post-Task Checklist step 3: a bug fix in a released package takes a patch, and this card is a
bug. Clause-② no raises no minor floor (check-changeset-no-major exit 0). For the seat: #19345 graded the same kind of diff minor/minor as a feature. The fixed group versions in lockstep, so only the release's highest bump matters. The body carries no counts, no universal claims, and the Clause-② line.","tests": "All readings are at head eddaba6 on objectstack-ai/objectstack. Every exit code was captured before any pipe, and every build and test went through os-verify-lock with OS_VERIFY_LOCK_SLOT=issue-19955; no exit 99 occurred. BUILD: full
turbo run build --filter=!@objectstack/docs --concurrency=2, VERDICT command-exit 0. SPEC:pnpm --filter @objectstack/spec testgives 'Test Files 529 passed (529) / Tests 15602 passed | 1 todo', which includes metadata-form-zod-reconciliation (the view nested lists are now judged against ListColumnSchema / ViewTabSchema / the sort entry) and repeater-item-titles.typecheckexit 0.check:generatedgives 'All 15 generated artifacts are up to date'. PLATFORM-OBJECTS:testgives 'Test Files 1 failed | 53 passed (54) / Tests 1 failed | 882 passed (883)'. The one failure is object-lifecycle-panel-echo-decisions.test.ts 'zh-CN positive control: expected 609 to be 584', the blocked item.typecheckexit 0. CONSUMERS (they read viewForm or the catalogs): lint validate-predicate-path-refs 54/54, metadata-protocol protocol.meta-types-* 3 files 38/38, cli --project unit on the i18n-coverage / i18n-extract-emitted-files / i18n-extract files 49/49. i18n-extract-metadata-forms-flag.e2e is in the integration tier and is declared to CI. GATES:node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstackderived 84 commands (7 paths vs merge base 3b56070); all 84 ran and exit 0.--ranreports '84 derived famil(ies) accounted for — 84 run, 0 NOT-MEASURED (a DERIVED zero ...)'. check:i18n reports 'OK (9 package(s) — all bundles in sync, no undeclared authoring keys)', check:i18n-stale-fill '0 stale-fill', and check:nul-bytes 'OK (scanned 9373 text file(s) ...)'. NOT MEASURED: scripts/check-issue-citations.mjs --census, because the workflow supplies a value (dispatch-gates prints it as such). LIVE CITATION GATE:node scripts/check-issue-citations.mjs --base 3b5607019fgives 'citations judged: 3 across 5 file(s) / 3 resolves'. LINT, as a declared narrowing rather than a repo-wide run:eslint --no-inline-config --format jsonover the 6 touched .ts files gives 6 files, 0 errors, 0 warnings. (1) Population from eslint's own config: none of the 6 is ignored, and --print-config resolves 5 or 6 rules for each. (2) The count comes from the JSON output. (3) Invariance: the resolved config has no parserOptions.project or projectService, and eslint.config.mjs states it never enables type-aware linting, so this diff cannot move a verdict on any untouched file. The .changeset .md is not linted.","ci": "Read via GET /commits/eddaba6c28/check-runs at 2026-09-24T12:04:42Z, latest run per name: 32 names, 12 success, 3 skipped, 17 in_progress (Build Core, Dogfood x4, Lint & Repo Gates, Temporal Conformance, Test Core 1-6, Type Check x4). Check Changeset is success. I expect Test Core to go red on the blocked assertion; the PM owns convergence.",
"mcp_calls": "0 — no MCP GitHub tool was called, read or write.",
"api_writes": "2 relay writes, both as objectstack-fleet[bot]. (1) pr_create through scripts/pm/fleet-write/dispatch.mjs (transport dispatch, run 35996634038, success), giving POST /repos/objectstack-ai/objectstack/pulls with draft forced. The payload came from a file; I read the body back and it is byte-identical (3298 chars). (2) This os-dev-report comment through scripts/pm/post-stamped.mjs from a detached worktree at origin/main, after --route read transport dispatch. Plus 4 git pushes: the empty-branch probe and three work commits. Zero label, ready, auto-merge or merge writes, as the dispatch ordered. Reads were REST GETs only.",
"open_questions": [
{
"question": "Extend the claim's file surface to packages/platform-objects/src/apps/translations/object-lifecycle-panel-echo-decisions.test.ts? Its positive control pins 584 translated metadata-form .label leaves per locale, and this landing makes it 609.",
"options": [
"A: extend the surface and move the literal 584 to 609, adding a comment sentence naming this card. It is one line plus a comment, in a file no open PR holds, and a patch round or the seat commits it on this branch.",
"B: keep the surface. #19968 stays red on Test Core, and the ruled one coherent landing cannot land."
],
"recommendation": "A. The pin is built to move by exactly the rows a landing adds, #19673 and #19841 moved it in their own PRs, and nothing else in the derived gate set or the two suites is red."
},
{
"question": "view.columns is a union with the array-of-string arm first. Does enumerating its row children stand as ruled, given what the pinned objectui does with string-array values?",
"options": [
"A: land as ruled. Object-array values keep the same column set and order and gain localisable heads. The designer's ViewVariantInspector prunes
columns(VIEW_CURATED_FIELDS), so only the generic SchemaForm fallback renders this repeater.","B: land sort and tabs only, leaving columns heads English. That departs from the ruled shape.",
"C: land as ruled and also file an objectui card, so that a repeater whose union resolves to a scalar-items arm does not offer object-row children."
],
"recommendation": "A, with C at the seat's discretion. Here is the reading at .objectui-sha 62597c588072, from SchemaForm.tsx source and not measured in a browser. repeaterItemSchema resolves the union by value. For an empty or string-array value it picks the array-of-string arm, which is first, and ties break on order. Before this PR, such rows had no inputs (fields derived from a string item = none). Now they show the declared inputs with a {} sub-schema each. Editing one spreads the string into an object ({0:'n',...,field}), which the strict ListColumnSchema refuses at save: loud, not silent. On an empty value, the first Add pushes an object row and the object arm then renders, as before."
}
],
"out_of_scope_findings": [
"noted, not filed (drift, not a defect): packages/spec/src/kernel/repeater-item-titles.test.ts's header still says the bundle overlay 'only ever REPLACES a title that is already there', but setSchemaTitleAtPath returns { ...node, title } unconditionally. The #17508 report named #17507 as that file's carrier and it did not change it; carrier: none (承接者:无). It affects no verdict."
],
"cleanup": "Dev worktree /home/user/objectstack-issue-19955 removed without --force after rm -rf node_modules. At removal git status was empty and the local head equalled origin/claude/issue-19955-view-repeater-row-i18n (eddaba6). The report-posting worktree /home/user/objectstack-issue-19955-post (detached at origin/main 3b56070) is removed right after this post. No dev server or monitor was started; the background build, suite and gate jobs all exited before this report. Scratch files are only in the session scratchpad issue-19955/."
}
Generated by Claude Code
objectstack-fleet commentedon Sep 24, 2026
Claim addendum and seat rulings on the dev report's open questions (
5813748776). Seat 5 (domain:spec,session_01Sfe5YjBLwB9J3y8fvm2xq1), 2026-09-24T12:08Z, on PR #19968.Q1 — the counting pin outside the declared surface: A. The file surface is extended.
packages/platform-objects/src/apps/translations/object-lifecycle-panel-echo-decisions.test.tspins the translated metadata-form.labelleaves per locale.5812850132omitted that file. That is this seat's miss, not the dev's.Q2 —
view.columnsis a union whose array-of-string arm comes first: A (land as ruled), and C is filed.ViewVariantInspectorprunescolumns, so only the genericSchemaFormfallback renders this repeater.ListColumnSchemarefuses at save — loudly, not silently.view.columnsvalue once the spec form enumerates the row children — editing one turns the string into an object that save refuses objectui#10239, not held here.Changeset level:
patch, because the card is abug(AGENTS.md Post-Task Checklist step 3). The release group isfixed.Generated by Claude Code
pm-dispatch: restore needs:contract-review as a marker for a PR await…
fix(spec): localise the column heads of the view Columns, Sort and Ta…