Repository navigation
docs(spec): the email template locale docs describe the ladder #28880 landed - #29014
Conversation
…landed The SendTemplateInput docblocks, the email-template locale docblocks and served describe, and the defineStack floor warning described the old exact ladder. They now describe the fold over the built-in loader, the declared fallback rung, the exact ladder a replacement loader keeps, and the unchanged no-locale ladder. Claude-Session: https://claude.ai/code/session_01ADHkmRewLso9227jPeGYag Co-authored-by: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ADHkmRewLso9227jPeGYag Co-authored-by: Claude <noreply@anthropic.com>
📓 Docs Drift CheckThis PR changes 1 package(s): 5 hand-written doc(s) NAME something this change touched and may need an implementation-accuracy re-verification:
⛔ 3 release-owned page(s) also name something this change touched. These are read-only:
What this run could not see
Coarse fallback — 168 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): Which tree this was computed onThis run read A worktree cut from an older # while this PR is open — GitHub drops the merge commit once it closes
git fetch origin bf683c1ca629e572d49c2dacbea8b48abd20abbe && git checkout bf683c1ca629e572d49c2dacbea8b48abd20abbe
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin 0be247ce8b91ba3b9a3ce7235491b28a986b039a 0cae34aa7c45a8b997ec121a7f69f3a91ffde707 && git checkout -B drift-repro 0be247ce8b91ba3b9a3ce7235491b28a986b039a && git merge --no-ff 0cae34aa7c45a8b997ec121a7f69f3a91ffde707
node scripts/docs-audit/affected-docs.mjs --json 0be247ce8b91ba3b9a3ce7235491b28a986b039a
|
|
domain:spec#1 · os-steve · session_01ADHkmPi25XXKx92Xmg4viS Head-sha: 维护者速读
席位意见:可落地,等契约复审和 CI。 席位核对 — ACCEPT ·
|
|
triage#1 · os-zhuang · session_01AavokzJ5DndAwitDXvKy4U Contract-review-claim: Taken on the lane's Generated by Claude Code |
|
triage#1 · os-zhuang · session_01AavokzJ5DndAwitDXvKy4U Contract reviewServed-tier: Inputs read: card #28896 body and its three comments (unblock, claim as amended, os-dev-report), PR #29014 body, file list, the three PR comments (docs-drift, the seat's ACCEPT, the claim) and the net diff against ① Derived judgments
② Semver level
③ Boundary flags
④ Design judgment
Sibling ladder (#28919): no edited sentence says the notification store folds or reads the declared fallback; the one sentence that implies the platform has a single ladder is the second must-fix above. Must-fix: 2 (both in Implemented-by: VERDICT: FAIL Generated by Claude Code |
…ld is not the platform's only one Contract review round 2: RenderTemplateInput.locale still stated the old exact ladder; resolveBundleLocale is the fold plugin-email imports, not the platform's one ladder; the no-locale lowest-tag rung is the built-in loader's answer; the floor docblock gains the absent-a-row hedge; the floor warning docblock says the full ladders; one overlong line rewrapped. Claude-Session: https://claude.ai/code/session_01ADHkmRewLso9227jPeGYag Co-authored-by: Claude <noreply@anthropic.com>
|
triage#1 · os-zhuang · session_01AavokzJ5DndAwitDXvKy4U Contract-review-claim: The delta re-review of this seat's FAIL (6570572543, head Generated by Claude Code |
|
triage#1 · os-zhuang · session_01AavokzJ5DndAwitDXvKy4U Contract reviewServed-tier: This record continues this seat's FAIL on head Inputs read: card #28896 body and its three comments (no new comment since the previous record); PR #29014 body, file list (unchanged: six files), its five comments (docs-drift, the lane seat's ACCEPT, the first claim, the previous record, this round's claim); the net diff, confirmed equal to ① Derived judgments
② Semver levelChangeset unchanged by the delta: ③ Boundary flags
④ Design judgment
Should-fix 5 — the #28919 handoff. Not a tree item in this PR's surface and could not be closed here; it stays in ③ for the lane seat's finding, now with the plugin-email inline comment beside it. Sibling ladder (#28919): after the delta no sentence on any Must-fix: 0. Should-fix: 0 new; the previous five are closed in the tree (four) or handed off (one, outside this PR's surface). Implemented-by: VERDICT: PASS Generated by Claude Code |
|
domain:spec#1 · os-steve · session_01ADHkmPi25XXKx92Xmg4viS Head-sha: 维护者速读
席位意见:可落地。 席位核对 — ACCEPT (round 2) ·
|
Requested by Steve · project thread
Fixes #28896
Clause-②: no
Metadata-protocol: none
维护者速读
SendTemplateInput两段注释、email-template.zod.ts的常量与locale注释及对外 JSON schema 的 describe、defineStack缺en-US行时的提醒文字)改成 Email template resolver ignores i18n.fallbackLocale and does no language-subtag folding: en-GB / zh-TW recipients never reach en / zh-CN rows #28880 落地后的真实规则;只改文字,不改 schema、不改提醒何时触发。en-GB→en、zh-TW→zh-CN),再试栈声明的 fallback,再试en-US;旧文字还说“精确匹配、只重试en-US、不折叠”,作者照着写会做错判断。console.warn文案,运行行为不变;回滚即 revert 本 PR。packages/spec/src/system/email-template.zod.ts(describe 是对外发布的文字)、packages/spec/src/contracts/email-service.ts(SendTemplateInput.locale是唯一完整写出两条阶梯的地方)、packages/spec/src/stack.zod.ts(提醒文案)。pnpm --filter @objectstack/spec exec vitest run src/stack-email-template-locale-floor.test.ts,预期全绿(现有钉住这段文字的断言都还成立)。What changes
Text only. No schema shape, accept set, export or warning trigger changes.
enanden-USstay two rows of one bundle; only how the resolver picks the row is described anew, as landed in #28917 (e0dc0771ab).packages/spec/src/contracts/email-service.ts:SendTemplateInput.templatenow says the name is matched exactly and every rung reads one row at one tag exactly.SendTemplateInput.localecarries both ladders as the code has them (EmailService.resolveAndRenderTemplate): a named locale over the built-in registry loader folds byresolveBundleLocale(exact, case-insensitive, base language, variant expansion, first match in ascending tag order), then the declared fallback (II18nService.getFallbackLocale():i18n.fallbackLocale, elsedefaultLocale) folded the same way, thenen-US, thenTEMPLATE_NOT_FOUND; a rung resolving to a tag already tried is skipped; a replacementTemplateLoaderkeeps the exact ladder; a no-locale call keepsen-USthen the lowest tag. The twoTEMPLATE_NOT_FOUNDerror lines (sendTemplate,renderTemplate) no longer say(name, locale|en-US).packages/spec/src/system/email-template.zod.ts: theEMAIL_TEMPLATE_FLOOR_LOCALEdocblock (the floor is now the rung that depends on neither the fold nor the declared fallback), thelocaledocblock, and thelocale.describe()served in the JSON schema.packages/spec/src/stack.zod.ts(bounded in-place fix, same stale-ladder class, not in the card's list):warnEmailTemplateLocaleFloor's docblock and itsconsole.warntext said "matches exactly and retries onlyen-US— there is no language-subtag folding". The text now describes the fold, the declared fallback and the exact ladder a replacement loader keeps. Which bundles it fires on is unchanged (see Acceptance notes).packages/spec/src/stack-email-template-locale-floor.test.ts: the file's header comment only (it stated the old ladder in the present tense). No assertion changed.content/docs/references/system/email-template.mdx(thelocalerow) and a specpatchchangeset.Tests
Forced test edits: none. Every existing pin on this wording still holds (
'en-US',TEMPLATE_NOT_FOUND,/NAMES a locale/,/lowest locale tag/in the describe;'no fallback floor',"none tagged 'en-US'","carries rows for 'en-GB'"in the warning).Readings at 862c7bd
pnpm --filter @objectstack/spec test(underos-verify-lock): Test Files 789 passed (789), Tests 23325 passed | 1 todo.pnpm --filter @objectstack/plugin-email testafterpnpm --filter '@objectstack/plugin-email^...' build: Test Files 47 passed (47), Tests 764 passed (764),VERDICT command-exit 0. This includestemplate-locale-fold.test.tsandtemplate-locale-resolution.test.ts, which pin the ladder this text describes.pnpm --filter @objectstack/spec check:generated: 1 of 14 stale (check:docs) before regeneration;--fixre-check✓ check:docs.repovitest project (email-template-floor-locale-parity.pin.test.ts) is CI's (Test Core); not run locally, the file is unchanged.Acceptance notes
THE_TRAPin the floor test (defaultLocale: 'en',fallbackLocale: 'en', anenrow, noen-USrow) reaches every recipient over the built-in loader on a host whose i18n service answers that fallback, yet still warns. The warning still names a real gap (a replacementTemplateLoader, or a host that declares no fallback), and its text now says so. Whether its trigger should change is a behaviour question on an authoring diagnostic, left to the seat.packages/specthat still states the exact ladder (not touched here):content/docs/automation/email-templates.mdxL217–233 (hand-written docs);packages/metadata-core/src/item-key-discriminators.tsL13–19 (a code docblock citing the old ladder);docs/qa/platform-checklist/areas/integration-system.jsonL957 (a checklist clause asserting "EXACT match with no language-subtag folding").TemplateLoadergets neither the fold nor the declared fallback rung (pinned intemplate-locale-fold.test.ts), and the text says so.Verification
Gate list
node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstackat 862c7bd derived 106 commands; each was run with stdin closed and its exit captured before any pipe. 103 exited 0 on the first sweep; three exited 3 (prerequisite not met, nothing measured) and exited 0 after their prerequisite:check-plugin-teardown-shape.mjs --self-testaftergit fetch --depth=1 origin 621a4876(its pinned fixture),check:skill-examplesandcheck:dual-build-cjs-loadsafterturbo run build --filter='./packages/**'.--ranreconciles 106 derived, 106 run, 0 NOT-MEASURED, 0 UNRUN.pnpm --filter @objectstack/spec typecheck:VERDICT command-exit 0.origin/mainmoved 15 commits since the branch point (135054eb); none touches a file this PR changes, andgit merge-treemerges clean, so main was not merged in before opening.Generated by Claude Code