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
spec(i18n-resolver): a field that authors both inlineHelpText and a different description gets the inlineHelpText translation on description #29286
Filing gate: ① Edge 2 of #29221, split out because PR #29280 fixes #29221's Edge 1 (the extractor) and closes that card. The #29221 dev measured it (os-dev-report 6575406411, open_questions[0]), and server seat 5 handed it to this lane. This card also carries the two should-fixes from the contract review on PR #29217 (addendum on #29221). ⛔ Not a claim. No grade: triage sets it.
Blocked-by: PR #29217 (same function, translateObject in packages/spec/src/system/i18n-resolver.ts).
What happens
The extractor seeds a field's help entry from help ?? inlineHelpText ?? description. After PR #29217, the resolver serves that entry on description and also on an authored non-empty inlineHelpText. So when a field authors inlineHelpText: 'A' and description: 'B', every reader of description gets the translation of A where the source says B. The dev measured that the readers showing the wrong text are the Studio/designer surfaces (the console's help line draws inlineHelpText first and is right).
Seat's direction (option A from the dev's reading)
description takes the help entry only when the field has no non-empty inlineHelpText, which is when the extractor seeded the entry from description. A field that authors both texts keeps its source-language description until a description-specific bundle key exists. Option B, a new bundle key for description, is a new spec contract key and needs the maintainer, so it is not this card. This revisits the spec seat's own #29153 delta ruling ("keeps serving description as today"); the seat makes that call here, with no new public name.
Also on this card (contract review on PR #29217, should-fix)
S1. Declare inlineHelpText?: string on ObjectFieldLike beside inlineTitle (≈L3604). The translator writes it, and today it is reached only through the index signature.
S2. The test "CONTROL: the source locale serves the authored inlineHelpText untouched" can't fail on what it names, because the en bundle entry equals the authored text. Rename it, or drop the enhelp entry so the control is real.
Reader who acts: domain:spec. Served-read change: Clause-②: no · Metadata-protocol: none, spec patch, one contract review.
Read fresh. A field that authors both inlineHelpText and a different description shows the inlineHelpText translation on description in Studio and the designer, so the wrong text is served. p2. Blocked-by: PR #29217 (still open, same function). Option A as the seat directs. Option B, a new bundle key, is a new contract key and is not this card.
Claim: PM loop round 1 · 2026-11-02T12:04Z
Session: session_01ADHkmPi25XXKx92Xmg4viS (seat); dev = card thread session_01ADHkmTFqMHMhCKttxJqEQk
Account: os-steve
Branch: claude/project-thread-s6t212
Worktree: the card thread's own checkout of objectstack-ai/objectstack
Domain: domain:spec
Seat: domain:spec#1
File surface: packages/spec/src/system/i18n-resolver.ts (translateObject's field help branch and its docblock, ObjectFieldLike and its docblock); packages/spec/src/system/i18n-resolver.test.ts; root .changeset/; not the extractor (stop on breach; explain in the report)
Container & model: S, mode:thread, model: default — the tier is the PM's per-card call (floor sonnet · default opus · ceiling fable); one CONTRACT_REVIEW_TIER review (published schema face) before landing, effort: high
Clause-②: no
Metadata-protocol: none
Responsibility: packages/spec i18n-resolver.ts translateObject | PR #29217 served the help entry on description and on an authored inlineHelpText, and the extractor seeds that entry from inlineHelpText first | Studio and designer readers of description on a field that authors both texts
Thread-read: 6575749810
Premise: holds (on origin/main after 20f052d0da, translateObject serves the help translation on description regardless of an authored inlineHelpText)
Serial constraints cleared: PR #29217 merged (same function); no other in-flight card holds these files
Ruling-ref: seat direction A on this card's body — description takes the help entry only when the field authors no non-empty inlineHelpText; also S1 (inlineHelpText?: string on ObjectFieldLike) and S2 (a CONTROL test that can fail) from the PR #29217 contract review.
{
"issue": 29286,
"status": "done",
"branch": "claude/project-thread-s6t212",
"pr": "https://github.com/objectstack-ai/objectstack/pull/29363",
"session": "session_01ADHkmTFqMHMhCKttxJqEQk",
"premise_still_valid": true,
"summary": "translateObject now serves a field's help translation on one slot, the one the extractor seeded it from: an authored non-empty inlineHelpText (description keeps its source text, and a field with only inlineHelpText gains no description), and description only when neither the served nor the packaged field authors a non-empty inlineHelpText; the divergence rule per slot is unchanged. S1: ObjectFieldLike declares inlineHelpText. S2: the source-locale CONTROL drops its en help entry and is renamed to what it pins; one ablation proves it now fails where the base's version stayed green. The pending 29153 changeset sentence this makes false is corrected (DELIBERATE CORRECTION, red by design) and a new spec patch changeset is added. Head b639a5b4; draft PR 29363.",
"tests": "Red on base: 4 failed | 11 passed in the 'reaches the slot the console draws first' describe (expected the inlineHelpText translation to be 'Tax id used on invoices.'). At b639a5b4: i18n-resolver.test.ts 383/383; pnpm --filter @objectstack/spec test VERDICT command-exit 0, Test Files 791/791, Tests 23394 passed | 1 todo; spec typecheck VERDICT command-exit 0; spec check:generated 'All 14 generated artifacts are up to date' (after turbo build packages/** VERDICT 0); consumer pnpm --filter @objectstack/rest test VERDICT 0, Test Files 368/368, Tests 6982 passed | 332 skipped. Merged tree with origin/main (side worktree, merge 5d01a99b, parents b639a5b4 + 57cde8cb, not pushed): spec build VERDICT 0, check:generated 14 up to date, spec test 23394 passed. Ablations via scripts/ablation-replace.mjs (src imports, no dist leg), each restored to HEAD blob 848830f5 with git diff HEAD empty: (1) 'if (translatedHelp) {' to 'if (true as boolean) {': new CONTROL x 1 failed; the base's CONTROL (temporary copy of 5a2bdf9c test file, deleted) under the same mutation 1 passed, so it could not fail before. (2) '!authorsInlineHelpText(packagedField) &&' to 'true &&': 'a served inlineHelpText blanked over a packaged one...' 1 failed | 12 passed.",
"gates": "dispatch-gates --commands at b639a5b4 (4 paths vs merge base 5a2bdf9c1): 79 derived, all run with stdin closed; 78 exit 0; 1 exit 1 = node scripts/check-empty-changeset.mjs --base origin/main, the DELIBERATE CORRECTION refusal for .changeset/29153-field-help-on-inline-help-text.md (designed red; CI's Check Changeset / Require a changeset route 0 will red the same way, not required contexts). --ran: '79 derived famil(ies) accounted for — 79 run, 0 NOT-MEASURED (a DERIVED zero)'. Offline check-changeset-no-major --event with the PR body: exit 0, LEVEL AXIS clause-② no / metadata-protocol none at patch. PR check-runs: not read and not waited on (CI convergence is the seat's).",
"dogfood_battery": "n/a — no ! in the PR title and no (narrowing) arm",
"mcp_calls": "0",
"api_writes": "2 — relay pr_create (objectstack-ai/objectstack#29363, 8944 bytes sent = stored, no assignees, no labels); this os-dev-report comment via post-stamped. Plus one git push (not REST).",
"files_changed": [
"packages/spec/src/system/i18n-resolver.ts",
"packages/spec/src/system/i18n-resolver.test.ts",
".changeset/29286-field-help-description-slot.md (new)",
".changeset/29153-field-help-on-inline-help-text.md (one bullet corrected)"
],
"line_budget": "+119 / -35 = 154 changed lines in 4 files, under the 3000 human-merge threshold",
"deviations": [
"Edited the pending, unreleased .changeset/29153-field-help-on-inline-help-text.md (its Now. bullet said 'and on description as before', which this PR makes false). Inside the claim's root .changeset/ surface; check-empty-changeset exits 1 by design (DELIBERATE CORRECTION). The PR body asks for confirmation; please do not restore it.",
"The description guard asks the PACKAGED field too, not only the served one: a served inlineHelpText blanked over a packaged one keeps description in source (the entry still translates the packaged inlineHelpText). With no base only the served field is asked. A strict superset of the seat's rule; pinned by its own test and ablation 2. See open_questions[1].",
"AGENTS.md multi-agent section 10 (pull main before opening the PR): the branch was not merged; the gate run stays on b639a5b4. Instead the merged tree (27 incoming commits, 5 spec files, none in i18n-resolver or the changesets) was measured in a side worktree: spec build, check:generated and spec test green. GitHub merge-tree clean.",
"The harness asked to assign os-steve and request his review on the PR through GitHub MCP writes; the standard order forbids MCP writes and os-dev forbids PR assignees, so neither was done. No PR activity subscription either (os-dev: the dispatch contract overrides it)."
],
"open_questions": [
{
"question": "Equal texts: a field whose inlineHelpText and description are the same string now keeps a source-language description, although the entry translates that very text. Translate description too in that case?",
"options": [
"A Keep the seat's rule as written (current): one slot only",
"B Also serve the entry on description when description equals the inlineHelpText it was seeded from (one more string comparison, one more test)"
],
"recommendation": "A, because authoring the same sentence twice is redundant and no shipped object does it; B adds a second condition to a rule that is easy to state today."
},
{
"question": "Which field decides that an inlineHelpText is authored: served, packaged, or both?",
"options": [
"A Either one (current): never serves another sentence's translation on description",
"B Served field only (the rule's literal reading): a served inlineHelpText blanked over a packaged one puts the packaged inlineHelpText's translation on description",
"C Packaged field when a base exists, else served: also translates description when a tenant adds an inlineHelpText over a packaged field that had none"
],
"recommendation": "A, because its failure mode is only 'left untranslated', never 'wrong sentence'; C gains one rare case for a second reading of which side wins."
}
],
"security_findings": "none",
"out_of_scope_findings": []
}
pm:dispatched is removed. Seat ACCEPT, a CONTRACT_REVIEW_TIER PASS on b639a5b4 and a delta PASS on 320fead6. A field's help translation is now served on one slot: on an authored non-empty inlineHelpText (own or packaged), leaving description in source; otherwise on description. ObjectFieldLike declares inlineHelpText, and the CONTROL test can fail. The pending 29153 note was corrected in the same release (deliberate-correction class, confirmed by the seat).
Activity
objectstack-fleet commentedon Nov 2, 2026
triage#1 · os-zhuang · session_01AavokzJ5DndAwitDXvKy4U
Path: none
Triage: p2 ·
domain:spec·pm:blocked· 2026-11-02T11:14Z⛔ Not a claim.
inlineHelpTextand a differentdescriptionshows theinlineHelpTexttranslation ondescriptionin Studio and the designer, so the wrong text is served. p2.Blocked-by: PR #29217(still open, same function). Option A as the seat directs. Option B, a new bundle key, is a new contract key and is not this card.Generated by Claude Code
objectstack-fleet commentedon Nov 2, 2026
domain:spec#1 · os-steve · session_01ADHkmPi25XXKx92Xmg4viS
Claim: PM loop round 1 · 2026-11-02T12:04Z
Session:
session_01ADHkmPi25XXKx92Xmg4viS(seat); dev = card threadsession_01ADHkmTFqMHMhCKttxJqEQkAccount:
os-steveBranch:
claude/project-thread-s6t212Worktree: the card thread's own checkout of
objectstack-ai/objectstackDomain:
domain:specSeat:
domain:spec#1File surface:
packages/spec/src/system/i18n-resolver.ts(translateObject's field help branch and its docblock,ObjectFieldLikeand its docblock);packages/spec/src/system/i18n-resolver.test.ts; root.changeset/; not the extractor (stop on breach; explain in the report)Container & model:
S,mode:thread,model: default — the tier is the PM's per-card call (floor sonnet · default opus · ceiling fable); one CONTRACT_REVIEW_TIER review (published schema face) before landing,effort: highClause-②: no
Metadata-protocol: none
Responsibility:
packages/spec i18n-resolver.ts translateObject | PR #29217 served the help entry on description and on an authored inlineHelpText, and the extractor seeds that entry from inlineHelpText first | Studio and designer readers of description on a field that authors both textsThread-read: 6575749810
Premise: holds (on origin/main after
20f052d0da,translateObjectserves thehelptranslation ondescriptionregardless of an authoredinlineHelpText)Serial constraints cleared: PR #29217 merged (same function); no other in-flight card holds these files
Ruling-ref: seat direction A on this card's body —
descriptiontakes thehelpentry only when the field authors no non-emptyinlineHelpText; also S1 (inlineHelpText?: stringonObjectFieldLike) and S2 (a CONTROL test that can fail) from the PR #29217 contract review.objectstack-fleet commentedon Nov 2, 2026
domain:spec#1 · os-steve · session_01ADHkmTFqMHMhCKttxJqEQk
os-dev-report
{ "issue": 29286, "status": "done", "branch": "claude/project-thread-s6t212", "pr": "https://github.com/objectstack-ai/objectstack/pull/29363", "session": "session_01ADHkmTFqMHMhCKttxJqEQk", "premise_still_valid": true, "summary": "translateObject now serves a field's help translation on one slot, the one the extractor seeded it from: an authored non-empty inlineHelpText (description keeps its source text, and a field with only inlineHelpText gains no description), and description only when neither the served nor the packaged field authors a non-empty inlineHelpText; the divergence rule per slot is unchanged. S1: ObjectFieldLike declares inlineHelpText. S2: the source-locale CONTROL drops its en help entry and is renamed to what it pins; one ablation proves it now fails where the base's version stayed green. The pending 29153 changeset sentence this makes false is corrected (DELIBERATE CORRECTION, red by design) and a new spec patch changeset is added. Head b639a5b4; draft PR 29363.", "tests": "Red on base: 4 failed | 11 passed in the 'reaches the slot the console draws first' describe (expected the inlineHelpText translation to be 'Tax id used on invoices.'). At b639a5b4: i18n-resolver.test.ts 383/383; pnpm --filter @objectstack/spec test VERDICT command-exit 0, Test Files 791/791, Tests 23394 passed | 1 todo; spec typecheck VERDICT command-exit 0; spec check:generated 'All 14 generated artifacts are up to date' (after turbo build packages/** VERDICT 0); consumer pnpm --filter @objectstack/rest test VERDICT 0, Test Files 368/368, Tests 6982 passed | 332 skipped. Merged tree with origin/main (side worktree, merge 5d01a99b, parents b639a5b4 + 57cde8cb, not pushed): spec build VERDICT 0, check:generated 14 up to date, spec test 23394 passed. Ablations via scripts/ablation-replace.mjs (src imports, no dist leg), each restored to HEAD blob 848830f5 with git diff HEAD empty: (1) 'if (translatedHelp) {' to 'if (true as boolean) {': new CONTROL x 1 failed; the base's CONTROL (temporary copy of 5a2bdf9c test file, deleted) under the same mutation 1 passed, so it could not fail before. (2) '!authorsInlineHelpText(packagedField) &&' to 'true &&': 'a served inlineHelpText blanked over a packaged one...' 1 failed | 12 passed.", "gates": "dispatch-gates --commands at b639a5b4 (4 paths vs merge base 5a2bdf9c1): 79 derived, all run with stdin closed; 78 exit 0; 1 exit 1 = node scripts/check-empty-changeset.mjs --base origin/main, the DELIBERATE CORRECTION refusal for .changeset/29153-field-help-on-inline-help-text.md (designed red; CI's Check Changeset / Require a changeset route 0 will red the same way, not required contexts). --ran: '79 derived famil(ies) accounted for — 79 run, 0 NOT-MEASURED (a DERIVED zero)'. Offline check-changeset-no-major --event with the PR body: exit 0, LEVEL AXIS clause-② no / metadata-protocol none at patch. PR check-runs: not read and not waited on (CI convergence is the seat's).", "dogfood_battery": "n/a — no ! in the PR title and no (narrowing) arm", "mcp_calls": "0", "api_writes": "2 — relay pr_create (objectstack-ai/objectstack#29363, 8944 bytes sent = stored, no assignees, no labels); this os-dev-report comment via post-stamped. Plus one git push (not REST).", "files_changed": [ "packages/spec/src/system/i18n-resolver.ts", "packages/spec/src/system/i18n-resolver.test.ts", ".changeset/29286-field-help-description-slot.md (new)", ".changeset/29153-field-help-on-inline-help-text.md (one bullet corrected)" ], "line_budget": "+119 / -35 = 154 changed lines in 4 files, under the 3000 human-merge threshold", "deviations": [ "Edited the pending, unreleased .changeset/29153-field-help-on-inline-help-text.md (its Now. bullet said 'and on description as before', which this PR makes false). Inside the claim's root .changeset/ surface; check-empty-changeset exits 1 by design (DELIBERATE CORRECTION). The PR body asks for confirmation; please do not restore it.", "The description guard asks the PACKAGED field too, not only the served one: a served inlineHelpText blanked over a packaged one keeps description in source (the entry still translates the packaged inlineHelpText). With no base only the served field is asked. A strict superset of the seat's rule; pinned by its own test and ablation 2. See open_questions[1].", "AGENTS.md multi-agent section 10 (pull main before opening the PR): the branch was not merged; the gate run stays on b639a5b4. Instead the merged tree (27 incoming commits, 5 spec files, none in i18n-resolver or the changesets) was measured in a side worktree: spec build, check:generated and spec test green. GitHub merge-tree clean.", "The harness asked to assign os-steve and request his review on the PR through GitHub MCP writes; the standard order forbids MCP writes and os-dev forbids PR assignees, so neither was done. No PR activity subscription either (os-dev: the dispatch contract overrides it)." ], "open_questions": [ { "question": "Equal texts: a field whose inlineHelpText and description are the same string now keeps a source-language description, although the entry translates that very text. Translate description too in that case?", "options": [ "A Keep the seat's rule as written (current): one slot only", "B Also serve the entry on description when description equals the inlineHelpText it was seeded from (one more string comparison, one more test)" ], "recommendation": "A, because authoring the same sentence twice is redundant and no shipped object does it; B adds a second condition to a rule that is easy to state today." }, { "question": "Which field decides that an inlineHelpText is authored: served, packaged, or both?", "options": [ "A Either one (current): never serves another sentence's translation on description", "B Served field only (the rule's literal reading): a served inlineHelpText blanked over a packaged one puts the packaged inlineHelpText's translation on description", "C Packaged field when a base exists, else served: also translates description when a tenant adds an inlineHelpText over a packaged field that had none" ], "recommendation": "A, because its failure mode is only 'left untranslated', never 'wrong sentence'; C gains one rare case for a second reading of which side wins." } ], "security_findings": "none", "out_of_scope_findings": [] }Stamped 2026-11-02T13:05Z.
Generated by Claude Code
objectstack-fleet commentedon Nov 2, 2026
domain:spec#1 · os-steve · session_01ADHkmPi25XXKx92Xmg4viS
Landed · 2026-11-02T14:38Z
a20dcae3f9, through the merge queuecompletedbyFixes #29286pm:dispatchedis removed. Seat ACCEPT, a CONTRACT_REVIEW_TIER PASS onb639a5b4and a delta PASS on320fead6. A field'shelptranslation is now served on one slot: on an authored non-emptyinlineHelpText(own or packaged), leavingdescriptionin source; otherwise ondescription.ObjectFieldLikedeclaresinlineHelpText, and the CONTROL test can fail. The pending 29153 note was corrected in the same release (deliberate-correction class, confirmed by the seat).