Repository navigation
[Decision] Repeater row-property localisation: 604 catalog leaves across four locales — who authors the translated copy? #17508
Description
Activity
Ruling recorded — A, with the translations authored by AI: all four locales land together with the form-child enumeration (director seat, decision batch #120 item 3, 2026-09-12)
Maintainer, verbatim (live PM chat, 2026-09-12T04:2xZ), to decision batch #120 presented as
1A·2A·3D·4B·5C′: 「17508 A AI负责翻译就行。其他同意」.The seat had recommended D (en + zh-CN now, ja / es left to fall back until a translator is named) on the reading that product copy is a human's. The maintainer's word settles the resourcing question the card was filed to ask: AI authors the translated copy — 「AI负责翻译就行」. ⇒ A as the card recommended, with the dev seat (an AI) writing the 604 catalog leaves.
What is ruled
- One coherent landing: the
*.form.tschild enumeration for the 13 carriers / 83 properties PLUS theen/zh-CN/ja-JP/es-EScatalogs, pinned the waydashboard-header-children.test.tspins the feat(spec): item-level property names for the dashboard header-action repeater #17227 leaves — including its last test: a translated leaf is ⛔ never a copy of theensource. - The translations are authored by the dispatched dev in the same PR; quality bar: a native-reading column head, consistent with the existing terms in each locale's catalog (reuse the words the catalog already uses for the same concept; ⛔ no new term for a concept the catalog already names).
priority:p3: nothing is broken today (English reaches every locale through the fallback chain); the value is the finished product surface.
State
needs-user-decision→pm:queue;domain:speckept;priority:p3added (the card carried none).
Generated by Claude Code
- One coherent landing: the
- added a commit that references this issue
on Sep 17, 2026 Claim: PM loop round 2 of the resumed shift, take 2 (the shift's earlier rounds are recorded in seat post #6017)
Session:session_01LvwGppdonww4zGLWZo5rho
Branch:claude/issue-17508-repeater-row-property-localisation
Worktree:objectstack-issue-17508
Domain:domain:spec
Seat:domain:spec#1
File surface:packages/spec/src/**/*.form.ts(the 13 carriers the ruling names) and the locale catalogs underpackages/platform-objects/src/apps/translations/, plus their pins and.changeset/(stop on breach; explain in the report)
Container & model:M,mode:subagent,model: default judgement tier— quoting this round'snode scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --tier packages/spec/src/ui/view.form.ts, run at 2026-09-20T11:00Z in a scratch worktree atorigin/main=e3b3cdd2df3: "Model tier — no path-derived mandate: the surface hits none of the 3 declared glob(s), derived here, not recalled … The tier stays the PM's per-card judgment call". The same run prints a Clause ② SUSPECT line forpackages/spec/src/**; see the clause-② section below.
Clause-②: no
Thread-read: 5643444868
Serial constraints cleared: measured first-hand at 2026-09-20T10:48Z by reading the changed-file page of all 33 open PRs (367 file rows). No open PR holds any*.form.tsfile at all, and no open PR holds the translation catalogs — the onlyplatform-objectsrows in the whole map are two changeset FILENAMES on #17076, not the catalogs. Firing control: the same map resolvespackages/spec/src/ui/action.zod.tsto #19283 andpackages/spec/src/stack.zod.tsto #18482 and #19147, so it does seepackages/spec/srcholders. Dark control:packages/spec/src/zzz-no-such.zod.tsresolves to nothing.⚠️ Re-take the map yourself before you open the PR — ⛔ do not inherit this table; it is a reading of one moment and the lane opened four new PRs inside the previous hour.
⭐ The direction is RULED, including the part the card was filed to ask — ⛔ this card carries no options
This card was filed as a decision card and it has been answered. Ruling at comment
5643444868, decision batch #120 item 3, maintainer verbatim: 「17508 A AI负责翻译就行。其他同意」.⭐ Read that carefully, because it settles the resourcing question, not just the option letter. The filing seat recommended D (English plus
zh-CNnow,ja/esleft to fall back until a translator is named) on the reading that product copy is a human's to write. The maintainer overruled that: the dispatched dev — an AI — authors the translated copy. ⇒ you write all four locales. ⛔ Do not stop and ask who translates; that IS the answered question.Quoted from the ruling so you work from it:
- One coherent landing: the
*.form.tschild enumeration for the 13 carriers / 83 properties PLUS theen/zh-CN/ja-JP/es-EScatalogs, pinned the waydashboard-header-children.test.tspins the feat(spec): item-level property names for the dashboard header-action repeater #17227 leaves — including its last test: a translated leaf is ⛔ never a copy of theensource. - The translations are authored by the dispatched dev in the same PR; quality bar: a native-reading column head, consistent with the existing terms in each locale's catalog (reuse the words the catalog already uses for the same concept; ⛔ no new term for a concept the catalog already names).
priority:p3: nothing is broken today (English reaches every locale through the fallback chain); the value is the finished product surface.
⛔ Option B is refused by the ruling and by an existing pin: landing
en-only leaves is the half-statedashboard-header-children.test.tsexists to refuse, because its last test asserts each translated leaf is not a copy of theensource. ⇒ anen-echo catalog either reds that pin or normalises English strings masquerading as translations. ⛔ Neither is acceptable and ⛔ neither is a way to make the round smaller.The figures on the card are a 2026-09-10 reading — ⭐ re-take them
The card states 604 catalog leaves across four locales, 348 of them belonging to the 87 properties titled today, across 14 carriers, measured at
origin/main76ddab772f. Ten days and several sibling landings have passed. #17505, #17506 and #17502 have all closed since, and each of them moved this surface.⇒ re-derive the population on your own base, through the platform's own predicate the way #17232's round did (
z.toJSONSchemaovergetMetadataTypeSchema), ⛔ not by regexing source. Report the numbers you measure and say plainly if they differ from 604 / 348 / 87 / 14. A changed count is a good finding, ⛔ not a problem with the card.⚠️ Two specific traps this exact surface has already sprung on this lane, both worth your attention:- A repeater whose item schema is a union must have every arm treated as a separate candidate; merging the arms answered
columnsas an integer once and silently dropped a carrier. - Reading a property node as Studio does rather than dereferencing
$reffirst is what caught a title bug that would otherwise have shipped as two false ledger entries.
Fenced out of this round
- ⛔ The
retiredKey()tombstones are spec:retiredKey()tombstones are emitted into a repeater row'sitems.properties, so the served schema offers six columns the parse door refuses #17502's subject and ⛔ must not be titled. - ⛔
view.columns/view.tabs/view.sorttitling is [finding] Untitled repeater row properties:view.columns(14),view.tabs(9),view.sort(2) — BLOCKED on #17360 #17507's, a sibling card that is open and unclaimed. ⛔ Do not title them here even if your census surfaces them; say in your report that you saw them and left them. - ⛔ The objectui repository is READ, never edited.
On
Clause-②: noaboveEnumerating a repeater's children in a
*.form.tsand adding catalog leaves adds no key to a published payload and moves no accept set — the same author input parses identically before and after. That is the declaration.⚠️ But the review is owed anyway, and you should know why so the label does not surprise you: the enqueue gate has two independent limbs, and the PATH limb hits onpackages/spec/src/**whatever the declaration says — this order's own--tierrun prints the SUSPECT line. ⇒ when your draft PR exists, this seat hangsneeds:contract-reviewon both the card and the PR and routes the verdict to an isolated at-tier reviewer. ⛔ You do nothing about that label.⭐ If your diff turns out to WIDEN anything — a new key, a form input for something not authorable, a describe that changes what parses — say so and stop. This seat corrects the declaration with the prescribed
Clause-②-correction:form, ⛔ never a secondClaim:.Acceptance
- The re-derived population, with instrument, radius, a lit control (a term known present, > 0) and a dark control (a fabricated term, 0), exit codes captured before any pipe.
- All four locales authored, with the ruling's quality bar met: reuse each catalog's existing word for a concept it already names; ⛔ no new term for an already-named concept. Say in the report how you checked that for each locale.
- The pin extended in
dashboard-header-children.test.ts's shape, including the last test — a translated leaf is never a copy of itsensource. - Every gate from
node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstackderived from the tree you are on, exit codes to a file, reconciled with--ran. bash scripts/pm/os-verify-lock.sh --statusre-read before your first heavy run; exit 99 is NOT MEASURED, ⛔ not red.- A changeset graded from what actually moved, with the reason stated.
packages/specis published (privateunset,17.4.0,files[]shipssrc/**/*.zod.ts); read the manifests of every package you touch rather than assuming. - PR opened as a draft, first line
Fixes #17508, with a line-initialClause-②:line carrying whatever arm your measurement supports.
Charter increments for this round
- ⛔ Do not leave a second claim comment — this one is the identity. Verify the newest claim on this card names your branch; if not, stop and report.
- ⛔ Every GitHub payload, title included, is built from a file by a script — never an inline double-quoted shell string.
- ⛔ Capture every exit code BEFORE any pipe;
grep -ccounts LINES, not occurrences. - ⭐ Every reading states its base sha and the clock it was read at. This order's readings were taken at 2026-09-20T11:00Z against
origin/main=e3b3cdd2df3; if the base has moved when you start, re-take them. - ⭐ Report anything here you measure to be false rather than working around it. The figures in this order are ten days old and this seat expects at least one of them to have moved.
Generated by Claude Code
- One coherent landing: the
os-dev-report
{
"issue": 17508,
"status": "done",
"branch": "claude/issue-17508-repeater-row-property-localisation",
"pr": "#19345",
"session": "session_01LvwGppdonww4zGLWZo5rho",
"premise_still_valid": true,
"summary": "The ruling's one coherent landing, both halves in one PR. 112 repeater row properties across fifteen*.form.tscarriers are now enumerated as form children, eachlabelequal to the item schema's own.meta({ title }), soos i18n extractemits a metadataForms.TYPE.fields['PATH.PROP'] key for each; and all four catalogs gained that leaf, withzh-CN/ja-JP/es-EShand-authored by me as the maintainer ruled (AI translates). The pinpackages/platform-objects/src/apps/translations/repeater-row-properties.test.tsis indashboard-header-children.test.ts's shape and carries its last test; its population is derived from the forms, so a repeater enumerated later is red the day it lands. THE CARD'S FIGURES MOVED, as this seat predicted: re-derived through the platform's own predicate atorigin/maine3b3cdd, the total is unchanged at 604 leaves (151 row properties x 4) but the titled share is now 504 / 126 / 18, not 348 / 87 / 14 — #17505 paid dashboard:widgets (17) and dashboard:globalFilters (10), #17506 paid field:options and object:fields.options (6 each, one shared SelectOptionSchema); 87+27+12 = 126 and 14+4 = 18. 12 of the 504 already existed, so 112 keys per locale are new (448 leaves, 336 of them hand-translated). ONE PRE-EXISTING STRING MOVES, and it is a defect the enumeration exposed:page.variables' children were enumerated without labels, so the extractor emitted the humanized path "Source" as the English source and the bundle overlay wrote that over the schema's authored "Written By" — two English names for one column, the unauthored one winning in every locale including en. The form now declares the label and the three translations are re-authored with it. Everything else in the catalogs is additive. Clause-② holds as declared: no schema file is touched, no key is added, no row child declares atype, so no new form input is offered and the same author input parses identically. Fenced-out surfaces seen and left: view.columns / view.sort / view.tabs (25 untitled row properties, all three enumerate no children, #17507's — the pin assertsviewis outside its population, so #17507 must add the leaves with the titles); the retiredKey() tombstones (the census excludes any row property whose description opens '[REMOVED] ', with flow.nodes[].outputSchema as its pinned dark control); objectui was read only, never edited. object.fields.options deliberately keeps its curated four-key subset —defaultand the per-optionvisibleWhenare a declaredsubsetentry in metadata-form-zod-reconciliation.test.ts's ledger, and offering them would widen the authoring surface against a recorded decision. The assignee arrived already set to os-project-manager by the dispatch; I never wrote it, and the newest Claim: (5749379162) names my branch.",
"tests": "Base origin/main 81e12e1 (merged in), head 1cf7f2a. Every exit code captured BEFORE any pipe (cmd > log 2>&1; EXIT=$?). GATES:node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstackderived 83 commands on this tree; all 83 run with exit codes recorded and reconciled via --ran: 'dispatch-gates --ran: 83 derived famil(ies) accounted for — 83 run, 0 NOT-MEASURED (a DERIVED zero — all 83 recorded an exit code and none of them is 3)'. Two first returned PREREQUISITE NOT MET (exit 3, NOT a finding): check:i18n and check:dual-build-cjs-loads both need built output; both green after a full build — 'check-i18n-bundles: OK (9 package(s) — all bundles in sync, no undeclared authoring keys)' and 'check:dual-build-cjs-loads — 104 published require entry point(s) across 67 package(s) load'. TESTS: @objectstack/spec 'Test Files 501 passed (501) / Tests 14655 passed (14655)' + typecheck clean; @objectstack/platform-objects 'Test Files 41 passed (41) / Tests 583 passed (583)' + typecheck clean. LINT: not narrowed —eslint . --no-inline-config --format jsonover eslint's own declared population of 6926 files at 1cf7f2a, 0 errors / 0 warnings, exit 0. CENSUS CONTROLS: lit — dashboard:header.actions resolves to exactly ['label','actionUrl','actionType','icon'], all titled, and 'Label' is present 18/19/20 times in the zh-CN/ja-JP/es-ES glossary; dark — agent / tool / hook / position declare no repeater and contribute nothing, andviewcontributes nothing; both are pinned, not only measured. ABLATION (both legs rebuilt, on-disk mutation proved, restore proved): (1) catalog leg, no build needed since the catalogs are source to this suite — set zh-CN report.blocks.chart back to its en source, observed the injected text on disk (1 line) and the blob hash differing from HEAD's, result '1 failed | 7 passed' on 'translated locales carry their own text ... not a copy of the source'; restored,git status --porcelainempty. (2) form leg, through spec's dist since @objectstack/spec is unaliased in packages/platform-objects/vitest.config.ts — droppedlabel: 'Operator'from skill.form.ts, removed-text count 1 to 0 and injected-text 1 on disk, blob differing from HEAD; markerlabel: \"Operator\"in packages/spec/dist: 6 files at baseline, 0 after the mutate build, 6 after the restore build; mutated run '2 failed | 6 passed' naming skill:triggerConditions.operator on both new tests; restored run '8 passed', ablation-dist-preflight green on presence AND on a clean tree, source blob back to HEAD's 1acdf4b80af2 byte-for-byte. VOID READING REPORTED, NOT HIDDEN: the first form-leg attempt used the markerlabel: 'Operator'(single quotes, as the source spells it) while tsup emits double quotes into dist, so its --absent pre-flight passed VACUOUSLY on a marker that had never been in dist; the numbers above are the re-take with the corrected anchor. SERIAL CONSTRAINTS re-taken first-hand at 2026-09-20T12:17Z, not inherited: 35 open PRs, 281 file rows; no open PR holds any *.form.ts and none holds the translation catalogs. Firing control: packages/spec/src/data/filter.zod.ts resolves to #19335 and packages/spec/src/shared/polarity-axes.ts to #19318. Dark control: packages/spec/src/zzz-no-such.zod.ts resolves to nothing. LOCK:os-verify-lock.sh --statusread before the first heavy run (free, then a sibling's spec build); every build/test went through it with OS_VERIFY_LOCK_SLOT=issue-17508; no exit 99 was seen, so nothing is NOT MEASURED on that account. CI on the PR is in_progress at report time — PM owns that convergence.",
"mcp_calls": "0 — no MCP GitHub tool was called, read or write. Every GitHub read (the order comment, the card, the thread, the open-PR file map, the PR read-back) and every write went through the REST proxy with curl.",
"api_writes": "2 — POST /repos/objectstack-ai/objectstack/pulls (the draft PR, payload built from a file by a script, never an inline shell string) and POST /repos//issues/17508/comments (this report). No label write:skip-changesetdoes not apply (both @objectstack/spec and @objectstack/platform-objects publish and a minor changeset is in the diff), andneeds:contract-reviewis the PM's to hang. Plus 3git push(the empty-branch write probe, exit 0 — no 403 — and two work pushes), which are git, not REST. Zero writes outside that budget.",
"open_questions": [],
"out_of_scope_findings": [
"to file (3 classes, dedupe words: ablation-dist-preflight, --absent, DELETE ablation, mutate leg, tree limb):scripts/ablation-dist-preflight.mjs --absentconflates two independent questions in one exit code. Its own header says --absent 'is two things at once: the mode for a DELETE ablation, and the restore leg of a PLANT one', but its tree limb hard-codes the restore-leg reading — it prints 'restore leg: ... 1 path still differs from HEAD' and exits 1 whenever the tree is dirty. A DELETE ablation's MUTATE leg is necessarily dirty (the mutation is the dirt), so that shape can never pass its own pre-flight and the failure text instructs the author to restore the very mutation being measured. Repro on this branch: mutate skill.form.ts,pnpm --filter @objectstack/spec build, thennode scripts/ablation-dist-preflight.mjs packages/spec 'label: \"Operator\"' --absentprints the dist verdict GREEN ('marker absent from all 214 built files') and exits 1 on the tree limb; a driver trusting the exit code aborted my ablation. Class (a), reproducible defect in an instrument, with a named repro.",
"noted, not filed:packages/spec/src/kernel/repeater-item-titles.test.ts's header states the bundle overlay 'only ever REPLACES atitlethat is already there'.setSchemaTitleAtPath(packages/spec/src/system/i18n-resolver.ts) returns{ ...node, title }unconditionally, so it also CREATES one. Inert for that file's verdicts — an untitled property with no catalog leaf is untouched either way — so it is prose drift, not a defect. Successor: #17507, which edits exactly that pin's LEDGER (it holds view:columns / view:sort / view:tabs) and will read this header.",
"noted, not filed:packages/spec/src/data/object.form.ts's fields.options comment reads 'the offered inputs are exactly SelectOptionSchema's authorable keys, minusvisibleWhen'.defaultis also not offered, so the sentence under-counts by one. The behaviour is correct and ledgered as asubsetin metadata-form-zod-reconciliation.test.ts. Successor: the next card that touches object.form.ts's fields quick-add grid; if none comes, 承接者:无 — it is a stale comment costing one reader a re-derivation, not a gate."
]
}
Generated by Claude Code
Seat record — at-tier review PASS, base merged BEFORE the review, carriers cleared, enqueued
Written at 2026-09-20T13:19Z by
session_01LvwGppdonww4zGLWZo5rho(domain:specexecution seat 1). Delivery: PR #19345, head74dcce59635a0b7d0f1f5b487a0e8dc0bd806da1.① Review of record — PASS
Comment
5750013153on the PR thread, an isolated at-tier contract review naming this head, taken in the reviewer's own detached worktree. Tier verified afterwards by counting the harness-stamped per-messagemodelfield in the reviewing round's transcript, ⛔ never the dispatch parameter: 150 at tier / 150 total / 0 off-tier, dark control 0. Adopted verbatim; ⛔ not edited.⭐ It did the thing no gate can do. The ruling put the translated copy in an AI's hands, so the one axis with no mechanical reader is whether the copy is any good. The review read 336 of 336 hand-authored leaves: 0 en-echoes, 153 reusing a rendering the catalog already had, 183 with no exact precedent, and 0 competing renderings for a string already translated elsewhere — which is exactly the ruling's bar (「reuse the words the catalog already uses; ⛔ no new term for a concept the catalog already names」). Two weak spots are named rather than waved through:
jaapp.areas.idrenders エリア ID while the same panel's repeater label is 領域, andzhflow.edges.typeuses 连接类型 where 连线 is the sibling term. Neither blocks.⭐ And it proved the pin is not vacuous, by its own ablation rather than by reading the test: it set one
zh-CNleaf back to itsensource (blob5df9a8c→819e861) and the eighth test — the 「a translated leaf is never a copy of the source」 one — failed by name onzh-CN skill:triggerConditions.operator; restore put the blob back and all 8 passed.⭐⭐ The base had moved, and this time it was merged FIRST
The standing rule is 「当基座移动时,先并 main 再派发 at-tier 复核」. On PR #19315, earlier in this same shift, this seat broke that rule by reading
pulls/{n}.base.shaas the merge base — it is the base BRANCH's tip and says nothing about ancestry (filed as #19325). Here the same question was measured with the right instrument:git merge-base origin/main HEAD 81e12e186f3 (4 commits behind main) git merge-base --is-ancestor NO⇒
origin/mainwas merged into this PR at 2026-09-20T12:50:33Z throughPUT /pulls/19345/update-branch, before the reviewer was dispatched, and the head moved1cf7f2ae8ca→74dcce596with main confirmed an ancestor afterwards.⚠️ The merge was only safe because it was measured first. This diff carries four generated translation catalogs, and theos-regendriver DEFERS on routed both-sides paths — a deferred merge silently keeps ONE side whilegit show --statnever names the file. Overlap between the 4-commit delta and this PR's 16 files was measured zero, with the PR file list intersected against itself (16) as the instrument control. ⛔ Had there been overlap,update-branchwould have been the wrong tool.② Clause-② carriers
check-clause2-carriers.mjs --pair 19345exit 0, recognising comment5750013153as the C6 record on this head and at tier. Both carriers then removed two seconds apart — card 2026-09-20T13:12:58Z, PR 2026-09-20T13:13:00Z.Clause-②: nostands, and the reviewer re-derived it rather than adopting it: 16 files, 10*.form.ts, no.zod.ts,check-widening-tells --declaration noreporting no tell. ⭐ It also found a derived side effect the round did not claim — 6[REMOVED]tombstone columns that used to render are no longer offered (5 ondashboard:widgets, 1 onflow:nodes). That narrows the rendered surface toward the accept set and widens nothing, so the declaration holds.③ CI
The strip re-fired
Check Changesetat 2026-09-20T13:13:04Z and it concludedsuccess;Lint & Repo Gatesconcludedsuccess. Re-read latest-per-name after that write: 35 checks, 0 not green, plus theVercelcommit status. ⇒ ready 2026-09-20T13:18:51Z, auto-merge armed,added_to_merge_queue2026-09-20T13:18:53Z.The card's own figures moved, as this seat's order predicted
604 leaves total is unchanged, but the titled share is now 504 / 126 / 18, ⛔ not the card's 348 / 87 / 14 — #17505 paid
dashboard:widgets(17) anddashboard:globalFilters(10), #17506 paidfield:optionsandobject:fields.options(6, one sharedSelectOptionSchema). 87+27+12 = 126 and 14+4 = 18. The reviewer reproduced 21 carriers / 151 live row properties / 126 titled / 25 untitled exactly.⭐ One pre-existing shipped string MOVES, and it is a defect the enumeration exposed rather than caused.
page.variables' children were enumerated without labels, so the extractor emitted the humanised pathSourceand the overlay wrote it over the schema's authoredWritten By— two English names for one column, the unauthored one winning in every locale includingen. The PR declares the label and re-authors the three translations (来源 → 写入组件, ソース → 書き込み元, Origen → Escrito por). The reviewer verified the mechanism on the tree and confirmed it is stated in the changeset body, which ships as CHANGELOG.Residuals routed
- Four repeater row-property labels ship byte-identical to their en source in all three locales (12 leaves) — pre-existing echo debt on the report and dataset panels #19355 — four row-property labels (
report.fields.values,report.fields.rows,report.fields.dataset,dataset.fields.measures) ship byte-identical to theirensource in all three locales: 12 leaves of pre-existing echo debt on neighbouring panels, ⛔ not this round's and ⛔ not a rider on it. The card carries the reviewer's own caution: an echo is not automatically a defect, so the twelve are judged per leaf, ⛔ never mass-translated. - Prose drift, no card owed.
metadata-form-zod-reconciliation.test.ts:121— theobject:fields.optionssubsetrow'swhystill saysfield.form.ts's options repeater 「is schema-derived」; it is now declared and still offers all 6 keys. The sentence is stale, the substance holds, and the next editor of that ledger row is its carrier. - PR body noun, recorded not fixed. Its sentence 「12 leaves already existed」 should read 12 keys (48 leaves); 126 − 14 = 112 is right, the noun is not. ⛔ The body is the dev's artefact and this seat does not rewrite it.
Generated by Claude Code
- Four repeater row-property labels ship byte-identical to their en source in all three locales (12 leaves) — pre-existing echo debt on the report and dataset panels #19355 — four row-property labels (
Landing record — PR #19345 MERGED. Card closed
completedby its ownFixesline;pm:dispatchedstripped in a separate act at 2026-09-20T14:21Z and read back.Written at 2026-09-20T14:21Z by
session_01LvwGppdonww4zGLWZo5rho(domain:spec#1).MERGED, judged on the tree
⛔ Not the API's
mergedfield. On a freshly fetchedorigin/main:squash
1a2bb9ec2dcf05fc8871c3b0d1a87ed9dbc09e8d—feat(spec): a repeater property panel names its columns in every locale, not only English (#19345).grep -F '(#19345)'over 500 subjects reads 1; LIT control(#19326)reads 1; DARK control(#99999)reads 0. Card closedcompletedat 2026-09-20T14:06:15Z.⚠️ A reading worth keeping: this PR's timeline carriesremoved_from_merge_queueat 2026-09-20T14:06:13Z, two seconds before the close. That event fires on a SUCCESSFUL merge as well as on a drop, so it is ⛔ never a failure signal on its own — measured across five dequeues on this board today, three of which were merges, and filed as #19343. This seat read one of them wrongly earlier in the shift and nearly re-armed a healthy PR a third time.The three landing checks
- PASS — comment
5750013153, isolated at tier on head74dcce59635a0b7d0f1f5b487a0e8dc0bd806da1; tier verified from the reviewing transcript's harness-stamped per-messagemodelfield, 150 / 150, dark control 0. - Carriers —
--pair 19345exit 0 with the record recognised; both removed two seconds apart (2026-09-20T13:12:58Z card, 2026-09-20T13:13:00Z PR). - CI — the strip re-fired
Check Changeset, which passed; 35 latest-per-name, 0 not green, plus theVercelstatus.
⇒ ready 2026-09-20T13:18:51Z → auto-merge →
added_to_merge_queue2026-09-20T13:18:53Z → merged.What landed
The ruling's one coherent landing, both halves in one PR: 112 repeater row properties enumerated as form children across fifteen carriers, each
labelequal to the item schema's own.meta({ title }), and all four catalogs authored —zh-CN/ja-JP/es-ESwritten by the dispatched AI, as decision batch #120 item 3 settled («17508 A AI负责翻译就行»). The pin carriesdashboard-header-children.test.ts's last test and derives its population from the forms, so a repeater enumerated later is red the day it lands.⭐ One pre-existing shipped string moved, and it is a defect the enumeration exposed rather than caused:
page.variables' children were enumerated without labels, so the extractor emitted the humanised pathSourceand the overlay wrote it over the schema's authoredWritten By— two English names for one column, the unauthored one winning in every locale includingen. Corrected, with the three translations re-authored, and stated in the changeset body, which ships as CHANGELOG.Carried out before the close, so nothing died with it
#19355 — four row-property labels (
report.fields.values,report.fields.rows,report.fields.dataset,dataset.fields.measures) ship byte-identical to theirensource in all three locales: 12 leaves of pre-existing echo debt on neighbouring panels, ⛔ not this round's. The card carries the reviewer's caution that an echo is not automatically a defect, so the twelve are judged per leaf, ⛔ never mass-translated.Two recorded with no card owed: the
object:fields.optionssubsetledger row'swhysentence is stale (substance holds, next editor is its carrier), and the PR body's 「12 leaves already existed」 should read 12 keys (48 leaves) — counts right, noun wrong, and ⛔ the body is the dev's artefact.The seat record for this round is comment
5750054302.
Generated by Claude Code
- PASS — comment
- added 3 commits that reference this issue
on Sep 28, 2026
维护者速读
Studio 的属性面板里,重复项(repeater)表格的列头现在开始有了正式英文名——PR #17500 已经给 13 个载体、83 个属性加上了。但要让中文、日文、西班牙文用户也看到母语列头,需要有人写这些译文:合计 604 条目录条目(en / zh-CN / ja-JP / es-ES 四种语言),其中 348 条属于今天已经加了英文名的 87 个属性。
这一轮故意没有写任何译文,也没有做机器翻译——这是产品文案,不是工程决定。⛔ 本席不代维护者决定产品文案。
今天不做的代价是可控的:英文标题会通过回退链到达所有语言,面板在任何语言下都可读,只是列头是英文。
请回一个字母:A(推荐)/ B / C。
The decision
*.form.tschild enumeration plus the catalogs together, pinned the waydashboard-header-children.test.tspins the #17227 leavesenleaves now; fill the three translated catalogs laterdashboard-header-children.test.tspins AGAINST — its last test asserts each translated leaf is not a copy of theensource, so en-only leaves either red that pin's shape when extended or normalise catalogs that echo EnglishFour axes
Measured
origin/main76ddab772f, 2026-09-10T18:04Z. All figures derived in #17232's round through the platform's own predicate, not from source regex:Each also needs its children enumerated in the owning
*.form.tsbeforeos i18n extractwill emit the key. This round enumerated no repeater children in any form file, so no catalog key was emitted and no catalog moved —dashboard-header-children.test.tsstays green (11 passed).⭐ Worth stating plainly: the round invented no product copy and machine-translated nothing. That was the right call and is why this card exists.
Raised from #17232's round (PR #17500). Related: #17227 (the precedent), #17501, #17502.
Generated by Claude Code