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: a translation item accepts any locale string ("not a locale!!" saves 200, valid) — LocaleSchema is a bare z.string() #25822
Premise checked before dispatch (domain:spec seat 2, 2026-10-26): readings and corrections in comment 6409913684 (#25822 (comment)). The goal below is unchanged.
Filing gate: ① a product defect with a live reproduction (finding class (a)). The fix narrows a published accept set, so it is Clause-② narrowing work for the spec lane.
Business reason: a translator or AI author who mistypes a locale (zh_CN, zh-cn with a space, a language name) gets a green save. Their strings are stored under a locale that no session will ever ask for, so the app silently shows untranslated text. This is the "not translated yet" failure that #4001 closed for unknown keys, still open for the locale value itself.
Reader: the packages/spec lane (src/system/translation.zod.ts, LocaleSchema, also used as the bundle map key); the next spec minor's narrowing batch.
Dedupe (open AND closed): "translation locale not validated BCP-47 any string accepted" → 5 hits, none of them this one. The nearest is #15757 (exact-match locale fallback in the validation-message bridge), a different defect.
reach: public HTTP entry, measured on a fresh stock showcase boot, main6679644, as admin.
Checklist item priority: P1
type: Bug
QA-source: #25817 · i18n.strict-translation-key-rejection · observed beside the clauses
Reproduction:
As admin, send PUT /api/v1/meta/translation/qa_bad_locale with body {"name":"qa_bad_locale","locale":"not a locale!!","objects":{"showcase_task":{"label":"x"}}}.
It answers 200 with _diagnostics.valid: true, and the read-back serves it.
Expected: 422 INVALID_METADATA, naming locale as not a BCP-47 tag, at both the save door and defineTranslation / defineTranslationBundle. That matches how the same item already refuses unknown keys.
Mechanism:LocaleSchema is z.string() with only a description of "BCP-47 Language Tag". No form check exists.
Not confirmed beyond the save and read-back: that no session resolves the stored strings.
p2: a narrowing of a published accept set (LocaleSchema gains a BCP-47 form check), not an addition, so p2 by 「协议新增 p1,其余 p2」. It ships in 18.x as a direct narrowing with its ADR-0087 conversion, with no retirement stage.
Refuse at both doors (save and defineTranslation / defineTranslationBundle), and cover the bundle map key, which uses the same schema. Measure stored rows that would stop parsing before the PR lands.
Premise check before dispatch · domain:spec seat 2 · 2026-10-26T06:40Z
Read-only premise reading on origin/main d5f4c2a2a (dispatch-runbook 派发前置). The goal of this card is unchanged; only the readings below move the landing point or the method, and the dispatch order carries them.
holds on the defect (translation.zod.ts:15 LocaleSchema is a bare z.string()), corrected twice. (1) More consumers than the card names: TranslationBundleSchema :~1989 and Platform… :~1999 (map key), TranslationConfigSchema :~2057-2061, TranslationItemSchema.locale :~2134, data/seed.zod.ts:~213, seed-loader.zod.ts:~285; readers of the open-string assumption at conversions/registry.ts:~8563/~14223, lint-liveness-properties.ts:~592, ui/…/metadata-admin/clientValidation.ts:~713. State in-scope or not for each in the PR body. (2) Runtime resolution already folds case (core fallbacks/memory-i18n.ts resolveLocale; metadata-protocol seed-loader.ts:~323), so zh-cn resolves today; zh_CN and non-tags do not.
Each count above is a re-measurable reading, not a ruling; the dev re-measures before relying on it.
Claim: PM loop round 1 · 2026-10-26T06:56Z
Session: session_01RyMY3prh9GRva1Tt37Di3i
Account: zhuangjianguo
Branch: claude/project-thread-dmzapg (card thread; the platform assigns the thread's branch and it can push only that one, written as measured instead of claude/issue-25822-<slug>)
Worktree: objectstack-issue-25822
Domain: domain:spec
Seat: domain:spec#2
File surface: packages/spec/src/system/translation.zod.ts (+ tests), packages/spec/src/conversions/registry.ts (one MAJOR_18 conversion), generated spec artefacts, the D3 entry packages/spec/src/migrations/entries/…/18.translation-locale-non-tag-refused.ts (migrations.test.ts ruling-B pin) and one JOIN row in retired-key-removal-version.pin.test.ts, one changeset; amended by the seat after the thread reported both as forced by red tests (stop on breach; explain in the report)
Container & model: M, mode:thread, model: TIER_DEFAULT — --tier: no path-derived mandate, effort: high
Clause-②: no (narrowing)
Metadata-protocol: narrowed
Responsibility: n/a — not a defect card
Thread-read: 6409913684
Premise: corrected 6409913684
Serial constraints cleared: lands before #25767 (same registry.ts); #25811 comment-only edit in registry.ts
{
"issue": 25822,
"status": "done",
"branch": "claude/project-thread-dmzapg",
"pr": "https://github.com/objectstack-ai/objectstack/pull/25983",
"session": "session_01Do245n6wxzetD6poZNSdeM",
"premise_still_valid": true,
"summary": "LocaleSchema (packages/spec/src/system/translation.zod.ts) now refuses any value that is not BCP-47 tag-shaped, using the pattern sys_user.locale already enforces; case is not judged. That narrows the translation item locale, both bundle map keys, the i18n config and seed locales. The ADR-0087 D2 conversion translation-locale-tag-canonicalized (MAJOR_18, order 76, retired from the load path, retiredAfter 18.1.0) rewrites underscore and whitespace spellings in stored rows and built artifacts and reports anything else as a TODO; a D3 entry, a minor changeset and pins ship with it. Landing point as ordered; no other producer needed a fix. Card assignee was not touched.",
"tests": "head 3e367787: pnpm --filter @objectstack/spec test -> Test Files 722 passed (722), Tests 21903 passed | 1 todo; pnpm --filter @objectstack/spec typecheck -> exit 0; new pins in src/system/translation.test.ts (accepted tags, 10 refused values as invalid_format naming @objectstack/spec 18, refusal at item locale / bundle key / platform bundle key / i18n supportedLocales, conversion TODOs and twin merge); conversions.test.ts fixture translation-locale-tag-canonicalized emits 7 notices; retired-key-removal-version.pin.test.ts JOIN row green. Ablation: n/a, a new refusal is pinned directly, no tested behaviour was removed.",
"gates": "local, head 3e367787: dispatch-gates.mjs --commands derived 92; all 92 run with exit codes captured before any pipe. 87 exit 0 on the first pass. 5 exited 3 (PREREQUISITE NOT MET: check-plugin-teardown-shape --self-test needed commit 621a4876 fetched in the shallow clone; check:doc-formula-expressions, check:dual-build-cjs-loads, check:i18n-walk-parity, check:lean-entry-closure needed built packages) and exited 0 on rerun after the fetch and the closure build. --ran reconciliation: '92 derived, 92 run, 0 NOT-MEASURED, 0 UNRUN' (a DERIVED zero). pnpm --filter @objectstack/spec check:generated: 'All 14 generated artifacts are up to date'. CI check-runs on PR #25983: in_progress at report time, not read.",
"dogfood_battery": "3e367787 · VERDICT command-exit 1 · Test Files 1 failed | 295 passed | 3 skipped (299) · Tests 1 failed | 2522 passed | 18 skipped (2541) · failure: test/authz-probe-blind-spot.test.ts > packages/runtime/src/domains/i18n.ts, control handleI18nRequest expected 3 read 4. Not this diff: 69fa23d60 (#25956, on main) changed that file, and this diff touches no runtime file.",
"mcp_calls": "5 — mcp__github__issue_read x5 (1 get, 4 get_comments), all reads; no GitHub MCP write",
"api_writes": "2 — relay pr_create (POST /repos/objectstack-ai/objectstack/pulls + POST /repos/objectstack-ai/objectstack/issues/25983/assignees, one stroke, run 40289186814); this os-dev-report comment (POST /repos/objectstack-ai/objectstack/issues/25822/comments via post-stamped.mjs)",
"deviations": "(1) File surface: 2 files outside the claim's surface, each forced by a red test: packages/spec/src/migrations/entries/semantic/18.translation-locale-non-tag-refused.ts (migrations.test.ts 'every graduated D2 conversion is named by a D3 entry of its own step (ruling B)' red without it, measured) and one JOIN row in packages/spec/src/shared/retired-key-removal-version.pin.test.ts (required for every retirement stamped with the newest published stable release). (2) Worktree: the platform branch was already checked out in the shared checkout, so that checkout was detached and the worktree ../objectstack-issue-25822 built on the branch. (3) Commit trailers are the model-free pair AGENTS.md prescribes, not the harness's model-named Co-Authored-By.",
"files_changed": [
".changeset/25822-locale-tag-shape.md",
"packages/spec/src/conversions/registry.ts",
"packages/spec/src/migrations/entries/semantic/18.translation-locale-non-tag-refused.ts",
"packages/spec/src/shared/retired-key-removal-version.pin.test.ts",
"packages/spec/src/system/translation.test.ts",
"packages/spec/src/system/translation.zod.ts"
],
"open_questions": [],
"out_of_scope_findings": [
"class: a · reach: named producer, the dogfood battery on main · evidence: packages/qa/dogfood/test/authz-probe-blind-spot.test.ts reds at 'packages/runtime/src/domains/i18n.ts — every positive control is still present in THAT file' (handleI18nRequest expected 3, read 4) after 69fa23d60 (#25956) on main; full-battery main-red, not caused by this PR · dedupe words: authz-probe-blind-spot, handleI18nRequest, i18n.ts control moved, dogfood main-red"
]
}
ACCEPT → PR #25983 comment 6412354740 (domain:spec seat 2); contract review PASS comment 6412325845 on head 2f0b44d. Ready with auto-merge. #25767 lands after this PR.
{
"issue": 25822,
"status": "done",
"branch": "claude/project-thread-dmzapg",
"pr": "https://github.com/objectstack-ai/objectstack/pull/25983",
"session": "session_01Do245n6wxzetD6poZNSdeM",
"premise_still_valid": true,
"summary": "Patch round 1 (seat, after contract review PASS 6411753197) at head 2f0b44d5: the registry.ts comments at the submitLabel and subCaption translation walks no longer call LocaleSchema an open string. They now say it judges only a tag's shape, an open-ended set the locale keys cannot be enumerated from. content/docs/ui/translations.mdx and content/docs/protocol/kernel/i18n-standard.mdx now state the accepted tag shape (BCP-47, '-' separators, refused at parse, the 18.x conversion for '_' and padded forms). Round 0: LocaleSchema (packages/spec/src/system/translation.zod.ts) now refuses any value that is not BCP-47 tag-shaped, using the pattern sys_user.locale already enforces; case is not judged. That narrows the translation item locale, both bundle map keys, the i18n config and seed locales. The ADR-0087 D2 conversion translation-locale-tag-canonicalized (MAJOR_18, order 76, retired from the load path, retiredAfter 18.1.0) rewrites underscore and whitespace spellings in stored rows and built artifacts and reports anything else as a TODO; a D3 entry, a minor changeset and pins ship with it. Landing point as ordered; no other producer needed a fix. Card assignee was not touched.",
"tests": "head 2f0b44d5 (comment and doc edits only): conversions.test.ts + translation.test.ts -> Test Files 2 passed, Tests 475 passed. Round 0, head 3e367787, unchanged source logic: head 3e367787: pnpm --filter @objectstack/spec test -> Test Files 722 passed (722), Tests 21903 passed | 1 todo; pnpm --filter @objectstack/spec typecheck -> exit 0; new pins in src/system/translation.test.ts (accepted tags, 10 refused values as invalid_format naming @objectstack/spec 18, refusal at item locale / bundle key / platform bundle key / i18n supportedLocales, conversion TODOs and twin merge); conversions.test.ts fixture translation-locale-tag-canonicalized emits 7 notices; retired-key-removal-version.pin.test.ts JOIN row green. Ablation: n/a, a new refusal is pinned directly, no tested behaviour was removed.",
"gates": "local, head 2f0b44d5: dispatch-gates.mjs --commands derived 113 (the doc edits add docs families); all 113 run, exit codes captured before any pipe. 111 exit 0 on the first pass. 2 exited 3 (PREREQUISITE NOT MET: check:skill-examples needed @objectstack/client-react built; check:dual-build-cjs-loads needed six packages built) and exited 0 on rerun after building them. --ran reconciliation: '113 derived, 113 run, 0 NOT-MEASURED, 0 UNRUN' (a DERIVED zero). CI on 2f0b44d5: not read at report time. Round 0 head 3e367787: all 48 check-runs completed, none failed.",
"dogfood_battery": "not re-run on 2f0b44d5: comment and doc edits only, no behaviour change. Round 0 on 3e367787: 3e367787 · VERDICT command-exit 1 · Test Files 1 failed | 295 passed | 3 skipped (299) · Tests 1 failed | 2522 passed | 18 skipped (2541) · failure: test/authz-probe-blind-spot.test.ts > packages/runtime/src/domains/i18n.ts, control handleI18nRequest expected 3 read 4. Not this diff: 69fa23d60 (#25956, on main) changed that file, and this diff touches no runtime file.",
"mcp_calls": "8 — mcp__github__issue_read x6 (1 get, 5 get_comments), mcp__github__pull_request_read x1 (get_check_runs), mcp__claude-code-remote__subscribe_pr_activity x1 (not GitHub); all GitHub calls are reads",
"api_writes": "3 — relay pr_create (POST /repos/objectstack-ai/objectstack/pulls + POST /repos/objectstack-ai/objectstack/issues/25983/assignees, run 40289186814); round-0 report comment 6411098423 and this round-1 report comment (POST /repos/objectstack-ai/objectstack/issues/25822/comments via post-stamped.mjs)",
"deviations": "(1) File surface: 2 files outside the claim's surface, each forced by a red test: packages/spec/src/migrations/entries/semantic/18.translation-locale-non-tag-refused.ts (migrations.test.ts 'every graduated D2 conversion is named by a D3 entry of its own step (ruling B)' red without it, measured) and one JOIN row in packages/spec/src/shared/retired-key-removal-version.pin.test.ts (required for every retirement stamped with the newest published stable release). (2) Worktree: the platform branch was already checked out in the shared checkout, so that checkout was detached and the worktree ../objectstack-issue-25822 built on the branch. (3) Commit trailers are the model-free pair AGENTS.md prescribes, not the harness's model-named Co-Authored-By.",
"files_changed": [
".changeset/25822-locale-tag-shape.md",
"content/docs/protocol/kernel/i18n-standard.mdx",
"content/docs/ui/translations.mdx",
"packages/spec/src/conversions/registry.ts",
"packages/spec/src/migrations/entries/semantic/18.translation-locale-non-tag-refused.ts",
"packages/spec/src/shared/retired-key-removal-version.pin.test.ts",
"packages/spec/src/system/translation.test.ts",
"packages/spec/src/system/translation.zod.ts"
],
"open_questions": [],
"out_of_scope_findings": [
"class: a · reach: named producer, the dogfood battery on main · evidence: packages/qa/dogfood/test/authz-probe-blind-spot.test.ts reds at 'packages/runtime/src/domains/i18n.ts — every positive control is still present in THAT file' (handleI18nRequest expected 3, read 4) after 69fa23d60 (#25956) on main; full-battery main-red, not caused by this PR · dedupe words: authz-probe-blind-spot, handleI18nRequest, i18n.ts control moved, dogfood main-red"
]
}
39a78b151, contains the merge commit (git merge-base --is-ancestor)
State: card closed by Fixes #25822; pm:dispatched removed in this stroke. #25767 (serial after this PR) is unblocked on this constraint; its thread is paused for the token hold.
Activity
objectstack-fleet commentedon Oct 25, 2026
Triage: first grade —
bug·priority:p2·domain:spec·area:i18n·pm:queue· triage seat ·session_01AavokzJ5DndAwitDXvKy4U· 2026-10-25T15:54Z⛔ Not a claim, ⛔ not a dispatch.
LocaleSchemagains a BCP-47 form check), not an addition, so p2 by 「协议新增 p1,其余 p2」. It ships in 18.x as a direct narrowing with its ADR-0087 conversion, with no retirement stage.defineTranslation/defineTranslationBundle), and cover the bundle map key, which uses the same schema. Measure stored rows that would stop parsing before the PR lands.Generated by Claude Code
objectstack-fleet commentedon Oct 26, 2026
Premise check before dispatch · domain:spec seat 2 · 2026-10-26T06:40Z
Read-only premise reading on origin/main
d5f4c2a2a(dispatch-runbook 派发前置). The goal of this card is unchanged; only the readings below move the landing point or the method, and the dispatch order carries them.holds on the defect (translation.zod.ts:15 LocaleSchema is a bare z.string()), corrected twice. (1) More consumers than the card names: TranslationBundleSchema :~1989 and Platform… :~1999 (map key), TranslationConfigSchema :~2057-2061, TranslationItemSchema.locale :~2134, data/seed.zod.ts:~213, seed-loader.zod.ts:~285; readers of the open-string assumption at conversions/registry.ts:~8563/~14223, lint-liveness-properties.ts:~592, ui/…/metadata-admin/clientValidation.ts:~713. State in-scope or not for each in the PR body. (2) Runtime resolution already folds case (core fallbacks/memory-i18n.ts resolveLocale; metadata-protocol seed-loader.ts:~323), so
zh-cnresolves today;zh_CNand non-tags do not.Each count above is a re-measurable reading, not a ruling; the dev re-measures before relying on it.
objectstack-fleet commentedon Oct 26, 2026
Claim: PM loop round 1 · 2026-10-26T06:56Z
Session:
session_01RyMY3prh9GRva1Tt37Di3iAccount:
zhuangjianguoBranch:
claude/project-thread-dmzapg(card thread; the platform assigns the thread's branch and it can push only that one, written as measured instead ofclaude/issue-25822-<slug>)Worktree:
objectstack-issue-25822Domain:
domain:specSeat:
domain:spec#2File surface:
packages/spec/src/system/translation.zod.ts (+ tests), packages/spec/src/conversions/registry.ts (one MAJOR_18 conversion), generated spec artefacts, the D3 entry packages/spec/src/migrations/entries/…/18.translation-locale-non-tag-refused.ts (migrations.test.ts ruling-B pin) and one JOIN row in retired-key-removal-version.pin.test.ts, one changeset; amended by the seat after the thread reported both as forced by red tests(stop on breach; explain in the report)Container & model:
M,mode:thread,model: TIER_DEFAULT — --tier: no path-derived mandate,effort: highClause-②: no (narrowing)
Metadata-protocol: narrowed
Responsibility: n/a — not a defect card
Thread-read: 6409913684
Premise: corrected 6409913684
Serial constraints cleared:
lands before #25767 (same registry.ts); #25811 comment-only edit in registry.tsobjectstack-fleet commentedon Oct 26, 2026
os-dev-report
{ "issue": 25822, "status": "done", "branch": "claude/project-thread-dmzapg", "pr": "https://github.com/objectstack-ai/objectstack/pull/25983", "session": "session_01Do245n6wxzetD6poZNSdeM", "premise_still_valid": true, "summary": "LocaleSchema (packages/spec/src/system/translation.zod.ts) now refuses any value that is not BCP-47 tag-shaped, using the pattern sys_user.locale already enforces; case is not judged. That narrows the translation item locale, both bundle map keys, the i18n config and seed locales. The ADR-0087 D2 conversion translation-locale-tag-canonicalized (MAJOR_18, order 76, retired from the load path, retiredAfter 18.1.0) rewrites underscore and whitespace spellings in stored rows and built artifacts and reports anything else as a TODO; a D3 entry, a minor changeset and pins ship with it. Landing point as ordered; no other producer needed a fix. Card assignee was not touched.", "tests": "head 3e367787: pnpm --filter @objectstack/spec test -> Test Files 722 passed (722), Tests 21903 passed | 1 todo; pnpm --filter @objectstack/spec typecheck -> exit 0; new pins in src/system/translation.test.ts (accepted tags, 10 refused values as invalid_format naming @objectstack/spec 18, refusal at item locale / bundle key / platform bundle key / i18n supportedLocales, conversion TODOs and twin merge); conversions.test.ts fixture translation-locale-tag-canonicalized emits 7 notices; retired-key-removal-version.pin.test.ts JOIN row green. Ablation: n/a, a new refusal is pinned directly, no tested behaviour was removed.", "gates": "local, head 3e367787: dispatch-gates.mjs --commands derived 92; all 92 run with exit codes captured before any pipe. 87 exit 0 on the first pass. 5 exited 3 (PREREQUISITE NOT MET: check-plugin-teardown-shape --self-test needed commit 621a4876 fetched in the shallow clone; check:doc-formula-expressions, check:dual-build-cjs-loads, check:i18n-walk-parity, check:lean-entry-closure needed built packages) and exited 0 on rerun after the fetch and the closure build. --ran reconciliation: '92 derived, 92 run, 0 NOT-MEASURED, 0 UNRUN' (a DERIVED zero). pnpm --filter @objectstack/spec check:generated: 'All 14 generated artifacts are up to date'. CI check-runs on PR #25983: in_progress at report time, not read.", "dogfood_battery": "3e367787 · VERDICT command-exit 1 · Test Files 1 failed | 295 passed | 3 skipped (299) · Tests 1 failed | 2522 passed | 18 skipped (2541) · failure: test/authz-probe-blind-spot.test.ts > packages/runtime/src/domains/i18n.ts, control handleI18nRequest expected 3 read 4. Not this diff: 69fa23d60 (#25956, on main) changed that file, and this diff touches no runtime file.", "mcp_calls": "5 — mcp__github__issue_read x5 (1 get, 4 get_comments), all reads; no GitHub MCP write", "api_writes": "2 — relay pr_create (POST /repos/objectstack-ai/objectstack/pulls + POST /repos/objectstack-ai/objectstack/issues/25983/assignees, one stroke, run 40289186814); this os-dev-report comment (POST /repos/objectstack-ai/objectstack/issues/25822/comments via post-stamped.mjs)", "deviations": "(1) File surface: 2 files outside the claim's surface, each forced by a red test: packages/spec/src/migrations/entries/semantic/18.translation-locale-non-tag-refused.ts (migrations.test.ts 'every graduated D2 conversion is named by a D3 entry of its own step (ruling B)' red without it, measured) and one JOIN row in packages/spec/src/shared/retired-key-removal-version.pin.test.ts (required for every retirement stamped with the newest published stable release). (2) Worktree: the platform branch was already checked out in the shared checkout, so that checkout was detached and the worktree ../objectstack-issue-25822 built on the branch. (3) Commit trailers are the model-free pair AGENTS.md prescribes, not the harness's model-named Co-Authored-By.", "files_changed": [ ".changeset/25822-locale-tag-shape.md", "packages/spec/src/conversions/registry.ts", "packages/spec/src/migrations/entries/semantic/18.translation-locale-non-tag-refused.ts", "packages/spec/src/shared/retired-key-removal-version.pin.test.ts", "packages/spec/src/system/translation.test.ts", "packages/spec/src/system/translation.zod.ts" ], "open_questions": [], "out_of_scope_findings": [ "class: a · reach: named producer, the dogfood battery on main · evidence: packages/qa/dogfood/test/authz-probe-blind-spot.test.ts reds at 'packages/runtime/src/domains/i18n.ts — every positive control is still present in THAT file' (handleI18nRequest expected 3, read 4) after 69fa23d60 (#25956) on main; full-battery main-red, not caused by this PR · dedupe words: authz-probe-blind-spot, handleI18nRequest, i18n.ts control moved, dogfood main-red" ] }Generated by Claude Code
objectstack-fleet commentedon Oct 26, 2026
ACCEPT → PR #25983 comment 6412354740 (domain:spec seat 2); contract review PASS comment 6412325845 on head 2f0b44d. Ready with auto-merge. #25767 lands after this PR.
objectstack-fleet commentedon Oct 26, 2026
os-dev-report
{ "issue": 25822, "status": "done", "branch": "claude/project-thread-dmzapg", "pr": "https://github.com/objectstack-ai/objectstack/pull/25983", "session": "session_01Do245n6wxzetD6poZNSdeM", "premise_still_valid": true, "summary": "Patch round 1 (seat, after contract review PASS 6411753197) at head 2f0b44d5: the registry.ts comments at the submitLabel and subCaption translation walks no longer call LocaleSchema an open string. They now say it judges only a tag's shape, an open-ended set the locale keys cannot be enumerated from. content/docs/ui/translations.mdx and content/docs/protocol/kernel/i18n-standard.mdx now state the accepted tag shape (BCP-47, '-' separators, refused at parse, the 18.x conversion for '_' and padded forms). Round 0: LocaleSchema (packages/spec/src/system/translation.zod.ts) now refuses any value that is not BCP-47 tag-shaped, using the pattern sys_user.locale already enforces; case is not judged. That narrows the translation item locale, both bundle map keys, the i18n config and seed locales. The ADR-0087 D2 conversion translation-locale-tag-canonicalized (MAJOR_18, order 76, retired from the load path, retiredAfter 18.1.0) rewrites underscore and whitespace spellings in stored rows and built artifacts and reports anything else as a TODO; a D3 entry, a minor changeset and pins ship with it. Landing point as ordered; no other producer needed a fix. Card assignee was not touched.", "tests": "head 2f0b44d5 (comment and doc edits only): conversions.test.ts + translation.test.ts -> Test Files 2 passed, Tests 475 passed. Round 0, head 3e367787, unchanged source logic: head 3e367787: pnpm --filter @objectstack/spec test -> Test Files 722 passed (722), Tests 21903 passed | 1 todo; pnpm --filter @objectstack/spec typecheck -> exit 0; new pins in src/system/translation.test.ts (accepted tags, 10 refused values as invalid_format naming @objectstack/spec 18, refusal at item locale / bundle key / platform bundle key / i18n supportedLocales, conversion TODOs and twin merge); conversions.test.ts fixture translation-locale-tag-canonicalized emits 7 notices; retired-key-removal-version.pin.test.ts JOIN row green. Ablation: n/a, a new refusal is pinned directly, no tested behaviour was removed.", "gates": "local, head 2f0b44d5: dispatch-gates.mjs --commands derived 113 (the doc edits add docs families); all 113 run, exit codes captured before any pipe. 111 exit 0 on the first pass. 2 exited 3 (PREREQUISITE NOT MET: check:skill-examples needed @objectstack/client-react built; check:dual-build-cjs-loads needed six packages built) and exited 0 on rerun after building them. --ran reconciliation: '113 derived, 113 run, 0 NOT-MEASURED, 0 UNRUN' (a DERIVED zero). CI on 2f0b44d5: not read at report time. Round 0 head 3e367787: all 48 check-runs completed, none failed.", "dogfood_battery": "not re-run on 2f0b44d5: comment and doc edits only, no behaviour change. Round 0 on 3e367787: 3e367787 · VERDICT command-exit 1 · Test Files 1 failed | 295 passed | 3 skipped (299) · Tests 1 failed | 2522 passed | 18 skipped (2541) · failure: test/authz-probe-blind-spot.test.ts > packages/runtime/src/domains/i18n.ts, control handleI18nRequest expected 3 read 4. Not this diff: 69fa23d60 (#25956, on main) changed that file, and this diff touches no runtime file.", "mcp_calls": "8 — mcp__github__issue_read x6 (1 get, 5 get_comments), mcp__github__pull_request_read x1 (get_check_runs), mcp__claude-code-remote__subscribe_pr_activity x1 (not GitHub); all GitHub calls are reads", "api_writes": "3 — relay pr_create (POST /repos/objectstack-ai/objectstack/pulls + POST /repos/objectstack-ai/objectstack/issues/25983/assignees, run 40289186814); round-0 report comment 6411098423 and this round-1 report comment (POST /repos/objectstack-ai/objectstack/issues/25822/comments via post-stamped.mjs)", "deviations": "(1) File surface: 2 files outside the claim's surface, each forced by a red test: packages/spec/src/migrations/entries/semantic/18.translation-locale-non-tag-refused.ts (migrations.test.ts 'every graduated D2 conversion is named by a D3 entry of its own step (ruling B)' red without it, measured) and one JOIN row in packages/spec/src/shared/retired-key-removal-version.pin.test.ts (required for every retirement stamped with the newest published stable release). (2) Worktree: the platform branch was already checked out in the shared checkout, so that checkout was detached and the worktree ../objectstack-issue-25822 built on the branch. (3) Commit trailers are the model-free pair AGENTS.md prescribes, not the harness's model-named Co-Authored-By.", "files_changed": [ ".changeset/25822-locale-tag-shape.md", "content/docs/protocol/kernel/i18n-standard.mdx", "content/docs/ui/translations.mdx", "packages/spec/src/conversions/registry.ts", "packages/spec/src/migrations/entries/semantic/18.translation-locale-non-tag-refused.ts", "packages/spec/src/shared/retired-key-removal-version.pin.test.ts", "packages/spec/src/system/translation.test.ts", "packages/spec/src/system/translation.zod.ts" ], "open_questions": [], "out_of_scope_findings": [ "class: a · reach: named producer, the dogfood battery on main · evidence: packages/qa/dogfood/test/authz-probe-blind-spot.test.ts reds at 'packages/runtime/src/domains/i18n.ts — every positive control is still present in THAT file' (handleI18nRequest expected 3, read 4) after 69fa23d60 (#25956) on main; full-battery main-red, not caused by this PR · dedupe words: authz-probe-blind-spot, handleI18nRequest, i18n.ts control moved, dogfood main-red" ] }Generated by Claude Code
objectstack-fleet commentedon Oct 26, 2026
Landed · domain:spec seat 2
39a78b151d691a538856c0f0d57304f8faa69f96origin/main39a78b151, contains the merge commit (git merge-base --is-ancestor)State: card closed by
Fixes #25822;pm:dispatchedremoved in this stroke. #25767 (serial after this PR) is unblocked on this constraint; its thread is paused for the token hold.