实施 #5307 时给 `EmailServiceConfigSchema.appName` 写 `.describe('… ({{appName}}) …')`,重新生成参考文档后发现输出被切坏。查了一下,不是新引入的,`main` 上已有 3 处。 ## 现象(origin/main @ ed0d2aac0) `packages/spec/scripts/build-docs.ts` 把 `.describe()` 文本写进属性表的 Description 列时,对 MDX 的花括号做转义。输入 `{{var}}`,输出是**反引号只包住前半截、后半个花括号漏在外面**: ```bash grep -rn '`{{' content/docs/references/ ``` ``` content/docs/references/ai/model-registry.mdx:171:| **system** | … | optional | System prompt — supports `{{var}`} interpolation | content/docs/references/ai/model-registry.mdx:172:| **user** | … | ✅ | User prompt template — supports `{{var}`} interpolation | content/docs/references/automation/flow.mdx:106:| **outputSchema** | … | … 表达式(`{{nodeId.field}`})… | ``` 对应的源: ``` packages/spec/src/ai/model-registry.zod.ts:121: system: … .describe('System prompt — supports {{var}} interpolation'), packages/spec/src/ai/model-registry.zod.ts:122: user: … .describe('User prompt template — supports {{var}} interpolation'), ``` 即 `{{var}}` 变成 `` `{{var}` `` 后面跟一个游离的 `}`。渲染出来读者看到的是 `` {{var} `` 加一个孤立右括号,而模板语法本身要的正是**成对**的双花括号 —— 这一列恰恰是在教读者怎么写模板变量。 ## 分级 observation-class:纯生成物排版,没有运行时行为、没有校验绕过,今天没有用户因此报错;但它出现在「怎么写模板变量」这一句上,是唯一会误导人的地方。故打 `finding`、不进 `pm:queue`,交 PM 分诊。 ## 规避与代价 #5307 的 PR 已经绕开:`appName` 的 `.describe()` 改写成「the appName variable」,不带花括号,并在源码里留了一行注释指回本单。这说明代价是真实的 —— 一个 schema 作者想在描述里写模板语法,就得先知道生成器会切坏它,否则得等文档生成完再回头改。 ## 修法方向(未验证,交实施者实测) `build-docs.ts` 里做 MDX 转义的那一段。花括号在 MDX 里是 JSX 表达式定界符,所以转义本身必要;问题出在**转义边界与代码反引号包裹的先后顺序**——现在的顺序让包裹只吃掉了一个 `}`。要么整段用行内代码包住再转义,要么转义时把连续花括号当一个整体。修好后 `pnpm --filter @objectstack/spec gen:docs`,上面三处 `grep` 应归零。
Activity
chore(spec): 随行生成物 + 规避 docs 生成器的花括号转义缺陷
os-zhuang commentedon Aug 5, 2026
分诊轮判级(spec 车道 PM,
session_018fxLGQdatPbBUvCgiVxg6D,2026-08-05):晋级(摘finding挂pm:queue)。理由:docs-gen 转义顺序 bug,main 上 3 处存量恰好切坏「教读者写模板变量」的那一句;#5307 的 PR 已被迫绕写一次 —— 代价已经在发生。修法方向 issue 已写(转义边界与反引号包裹顺序),小单。Generated by Claude Code
os-zhuang commentedon Aug 5, 2026
认领:spec 车道恢复后第 1 批(batch:2)
会话:
session_018fxLGQdatPbBUvCgiVxg6D分支:
claude/issue-5452-docs-gen-brace-escapeWorktree:
objectstack-issue-5452域:
domain:spec文件面:
packages/spec/scripts/build-docs.ts+ 重生成content/docs/references/**受影响页(main 上 3 处存量:model-registry.mdx ×2、flow.mdx ×1)+ 门禁性测试。与同批 #5050 源文件不相交;references 生成物重叠按 os-regen 四步互保。修好后 #5307 在 email-config 里的绕写注释可留(它引用本单,历史成立)。
Generated by Claude Code
docs(spec): correct the measured counts in the escape-mdx pin headers (…
os-zhuang commentedon Aug 5, 2026
实施完成,draft PR #5550(会话
session_018fxLGQdatPbBUvCgiVxg6D,分支claude/issue-5452-docs-gen-brace-escape)。前提复核:基线
ed0d2aac0已前移,在origin/main@5acb93add上重核,3 处存量仍在,前提成立。两点与本单原文不同,请分诊时留意:
实际是 5 处,不是 3 处。 根因(
escapeMdxDescription用indexOf取第一个闭合符而非配对闭合符)对任何嵌套定界符都成立,不限于双花括号。另有两处同样被切开、但起手只有单个左花括号,因此本单用的`{{grep 天然看不见:content/docs/references/ai/solution-blueprint.mdx:156—— roll-upfilter例子{ status: { $in: [...] } }content/docs/references/api/analytics.mdx:70—— 已退役的query信封{ cube, query: {...} }本单的验收判据(grep 归零)不成立,也不应该成立。
grep -rn '`{{'匹配的是「反引号 + 两个左花括号」,而修好后的正确输出`{{var}}`同样以此开头 —— 修前修后都是 3 命中,变的是内容不是计数。归零只有在「参考页里根本不许出现模板变量语法」时才成立,与本单目的相反。门禁改用等价且更宽的不变量:行内代码跨度里的花括号必须配平。实测 main 224 页 5 处违例、本 PR 重生成后 0 处、零误报。反向验证两个方向都实跑:还原旧 matcher → 5 条单元用例转红;再
gen:docs→ 语料门禁转红并逐行复现 main 上那 5 行。顺带发现另立一单 #5553(不同函数、不同根因,未在本 PR 修):模块 JSDoc 走
getFileDescription,按源码行join('\n\n')成段落,跨行的行内代码跨度被段落边界切断,5 张参考页正文露出裸反引号。按派单要求,#5307 在
email-config.zod.tsappNamedescribe 里的绕写保持原样。packages/spec/authorable-surface.base.json被gen:schema顺带推进的baseRev已还原,未纳入本 PR。Generated by Claude Code
feat(spec): EmailServiceConfigSchema 补齐 CLI 实读的 queueDelivery / appNa…
fix(spec): docs-gen 把嵌套花括号整对包进行内代码,不再切成半对 (objectstack-ai#5452) (obje…
docs(pm-dispatch): 探活入例行、报告丢失直接验收、座位行自查等五处协议更新 (objectstack-ai#5597)