Skip to content

fix(spec): docs-gen 按 JSDoc 原有行布局渲染模块描述,并让裸路径改写跳过已成型链接 (#5553, #6136) - #6224

Merged
os-zhuang merged 9 commits into
mainfrom
claude/issue-5553-file-description-rendering
Aug 7, 2026
Merged

fix(spec): docs-gen 按 JSDoc 原有行布局渲染模块描述,并让裸路径改写跳过已成型链接 (#5553, #6136)#6224
os-zhuang merged 9 commits into
mainfrom
claude/issue-5553-file-description-rendering

Conversation

@os-zhuang

@os-zhuang os-zhuang commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

Fixes #5553
Fixes #6136

两单同落 packages/spec/scripts/lib/file-description.ts(#5059/PR #6134 今日新建),同一条渲染链上的两条互不相干的缺陷,合并为一个 PR —— 分开派会各付一次 content/docs/references/** 重生成并互埋 diff。

前提复核(先于实现,对 current origin/main)

两单正文都早于 #6134 的抽取,代码形状已移位,故逐条复核:

#6134 的取块规则一字未动:185 个带模块头的源文件修改前后都渲染出描述,无一页新增或丢失开篇描述(#6134 的验收标准,已作为语料 pin 固化)。

改法

两条缺陷根因同形:变换施加的粒度错了

#5553 渲染器丢掉全部空行、把剩下的每一源码行用 \n\n 连接 —— 即宣布每一源码行自成一段。任何合法跨行的构造都被段落边界切断,而行内代码跨度不能跨空行,两边反引号因此当字面量渲染。同一段还对全文无差别转义花括号(含代码内部,那里反斜杠不是转义符而是读者看得见的字符)。

改法是不再重写布局:去掉 * 边栏后保持原样,段落切分交还 markdown 自身。issue 提的「连续非空行用空格连接」在语义上正是 markdown 的软换行规则,但字面照做会摧毁列表 —— 185 个带描述的源文件里 85 个写了列表。转义与链接解析收窄到正文:围栏/缩进代码块原样保留,正文内由 tokenizer 把行内代码跨度挡在外面。

#6136 无标题 {@link 路径} 会产出一条 markdown 链接,而它的链接文本恰好就是那条路径本身;紧随其后的裸路径改写器在整串上再跑一次,匹配到链接文本里的路径,又把它包了一层。前后瞻表达不了「不在链接内部」,故改为按 token 施加、排除已成型链接。裸路径正则本身一字未改,修复完全来自 tokenize —— 括号内路径等既有渲染因此零附带变化。

一处刻意不照抄源码布局:缩进(4 空格)代码块改用围栏输出。 MDX 为了让缩进用于排布 JSX,取消了 CommonMark 的缩进代码块,所以这种块会以正文身份进入编译器。data/date-macrosdata/context-tokens 的占位符示例正是这样写的且几乎全是花括号 —— 保持缩进则 Could not parse expression with acorn 编译失败(第一版实现实测踩到,由全量 MDX 编译检查逮住);改成转义则读者在本该是代码的地方看到 \{,正是 #5553 要修的那条。目标方言里代码块只有围栏一种拼法。

反向验证(先定方向,再逐条恢复;红集必须不相交)

恢复的缺陷 预测 实测变红
A #5553 按行切段 结构类 pin + 语料「切断跨度」 5 条,全部在 #5553
B #5553 无差别转义 代码跨度/围栏/缩进 pin + 语料「代码内反斜杠」 5 条,全部在 #5553
C #6136 改写器跑整串 2 条 {@link} pin + 语料「链接套链接」 3 条,全部在 #6136

(A∪B) ∩ C = ∅ —— 这就是「两条独立缺陷、不是一条」的证据,与 #6136 立单者在 #5059 报告里的论断一致。

一处预测落空,如实记录:我预测 A 会让「连续 @see 保持独立块」变红,实际为绿 —— 把每行切成独立段落恰好也把那几行分开了,是巧合而非该 pin 失效。

受影响的参考页(169 张)与归属

#6136 —— 2 张,各一行「另见」由「链接套链接」恢复为单个可点链接:

  • automation/etl.mdx:54See also: [../integration/connector.zod.ts](/docs/references/integration/connector) for the Enterprise Connector layer
  • integration/connector.mdx:102See also: [../automation/etl.zod.ts](/docs/references/automation/etl) for the ETL Pipeline layer (data engineering)

#5553 —— 全部 169 张(上面 2 张同时含 #5553 改动)。按变化种类计:

  • 被切断的行内代码跨度复原(4 张):automation/flow-functionsecurity/explainshared/expressionsystem/settings-client —— 每张 2 处→0。
  • 代码内 \{ 反斜杠残留清零(33 张):全语料 296 → 0;正文中合法转义的 28 处保留不动。
  • 围栏代码块恢复(32 张):@example 样例此前被拆成每行一段并逐行转义,现为真正的代码块。
  • 缩进恢复(47 张):嵌套列表恢复层级。
  • 缩进块改围栏(2 张):data/date-macrosdata/context-tokens
  • 其余为段落重新合并与列表由「松」变「紧」。
169 张页面完整清单(按 category)
  • ai (8): conversation, embedding, knowledge-document, knowledge-source, mcp, model-registry, skill, usage
  • api (23): analytics, auth, auth-endpoints, automation-api, batch, discovery, dispatcher, documentation, endpoint, errors, events, export, http-cache, metadata, odata, package-api, plugin-rest-api, query-adapter, realtime-shared, rest-server, storage, versioning, websocket
  • automation (13): bpmn-interop, builtin-node-config, control-flow, etl, execution, flow, flow-function, io-node-config, node-executor, schemaless-node-config, state-machine, time-relative-trigger, webhook
  • cloud (10): app-store, developer-portal, environment, environment-artifact, environment-package, marketplace, marketplace-admin, package, package-version, tenant
  • data (22): analytics, context-tokens, data-engine, datasource, date-macros, document, driver, driver-common, driver-memory, driver-mongo, driver-nosql, driver-sql, external-catalog, external-lookup, feed, field-value, filter, hook, query, seed, seed-loader, validation
  • identity (5): eval-user, identity, organization, position, scim
  • integration (1): connector
  • kernel (28): cli-extension, cluster, context, dependency-resolution, events-bus, events-core, events-dlq, events-handlers, events-integrations, events-queue, execution-context, metadata-customization, metadata-plugin, metadata-protection, package-artifact, package-registry, package-upgrade, plugin-capability, plugin-lifecycle-advanced, plugin-loading, plugin-registry, plugin-security, plugin-security-advanced, plugin-structure, plugin-validator, plugin-versioning, service-registry, startup-orchestrator
  • security (4): explain, permission, rls, sharing
  • shared (6): branded-types, expression, http, identifiers, mapping, protection
  • studio (3): flow-builder, object-designer, plugin
  • system (33): app-install, auth-config, book, cache, change-management, collaboration, core-services, deploy-bundle, disaster-recovery, email-config, email-template, encryption, environment-artifact, http-server, incident-response, job, logging, message-queue, metadata-persistence, metrics, migration, object-storage, registry-config, search-engine, security-context, settings-client, settings-manifest, stack-server, supplier-security, tenant, tracing, training, worker
  • ui (13): action, action-params, app, bulk-action, chart, dataset, i18n, notification, page, sharing, theme, view, widget

顺带修好的邻居门(必须,不是顺手)

scripts/escape-mdx.test.ts#5452 语料门断言「行内代码跨度里花括号必须配平」,但按提取跨度 —— 这只在模块 JSDoc 把每行当独立段落时才碰巧成立。本 PR 恢复行布局后跨度可以跨行,该门只看到开头半截,把正常跨行的跨度读成不配平并变红。改为按段落提取(空行仍是硬边界,因为代码跨度不能跨空行),并先把围栏块置空。#5452 自身的缺陷形态(同一行内被切成半对)报告方式不变,已用合成样例复核仍会报出。

验证

  • pnpm --filter @objectstack/spec test —— 330 files / 8435 tests 全绿(pin 由 14 条扩到 28 条 + 2 条新语料门)。
  • pnpm --filter @objectstack/spec typecheck —— 绿。
  • check:docs 232 files in sync ✅ / check:generated 10 artifacts up to date ✅ / check:api-surface unchanged ✅。
  • eslint 三个改动文件 —— 绿;check:nul-bytescheck:doc-authoringcheck:empty-changeset —— 绿。
  • 全量 216 张参考页经 @mdx-js/mdx 编译通过(216/216);已核对 origin/main 同样为绿,故这是「未引入回归」而非「修好了原有失败」。

范围

content/docs/references/** 重生成独立成 commit。未触碰 build-docs.ts(#5853 下轮)、lib/format-type.ts(#5340)、lib/zod-graph.tsbuild-schemas.ts(#5371)、任何 *.zod.ts 源码、content/docs/releases/。已加 changeset(@objectstack/spec: patch),与两个同类邻居 PR(#5550#6134)一致。

纯展示层,无运行时/协议/导出面语义变化。

#5553:渲染器丢掉全部空行、把剩下的每一源码行当成一个段落用 `\n\n` 连接,
任何跨行的 markdown 构造都被段落边界切断 —— 行内代码跨度不能跨空行,两边反引号
因此当字面量渲染。同一段还对全文无差别转义花括号,包括代码内部,而代码里反斜杠
不是转义符而是读者看得见的字符。改法是不再重写布局:去掉 ` * ` 边栏后保持原样,
段落切分交还给 markdown 自身;转义与链接解析收窄到正文,围栏/缩进代码块原样保留,
正文内由 tokenizer 把行内代码跨度挡在外面。

#6136:无标题 `{@link 路径}` 产出 `[路径](路由)`,链接文本就是那条路径;紧随其后的
裸路径改写器在整串上再跑一次,又把它包了一层。前后瞻表达不了「不在链接内部」,
故改为按 token 施加、排除已成型链接。

#6134 的取块规则一字未动:185 个带模块头的源文件仍全部渲染出描述,无一页增删。
纯生成物,由 `pnpm --filter @objectstack/spec gen:docs` 产出。
- #5553:4 张页面被切断的行内代码跨度复原(flow-function / explain / expression /
  settings-client),33 张页面代码内的 `\{` 反斜杠残留清零,32 张页面的 `@example`
  样例恢复成真正的代码块,47 张页面恢复嵌套缩进。
- #6136:automation/etl、integration/connector 的「另见」各恢复成单个可点链接。
无页面新增或丢失开篇描述。
该门断言「行内代码跨度里的花括号必须配平」,但按**行**切分跨度 —— 这只在
模块 JSDoc 把每一源码行当成独立段落时才碰巧成立。#5553 恢复原有行布局后跨度
可以跨行,按行切分只看到开头那半截(`update_record fields: {`),把一个正常
跨行的跨度读成不配平。改为按**段落**提取(空行仍是硬边界,因为代码跨度不能
跨空行),并先把围栏代码块置空。#5452 自身的缺陷形态(同一行内被切成半对)
报告方式不变,已用合成样例复核。
保持源码行布局后,`data/date-macros`、`data/context-tokens` 里作者手写的
4 空格代码块被原样输出,而 MDX 为了让缩进用于排布 JSX,取消了 CommonMark 的
缩进代码块:这两页的花括号因此以正文身份进入编译器,`pnpm build` 报
"Could not parse expression with acorn"。改为重新输出成围栏代码块 —— 目标方言
里代码块只有这一种拼法。反过来若改成转义,读者会在本该是代码的地方看到 `\{`,
正是 #5553 要修的那条。

新增两条语料 pin:任何 MDX 会解析的位置都不得留下未转义花括号;渲染结果中
不得出现缩进代码块。二者任一都能挡住这次回归。
纯生成物。data/date-macros、data/context-tokens 的占位符示例由缩进块变为
围栏块,花括号不再转义。全量 216 张参考页均通过 @mdx-js/mdx 编译。
@vercel

vercel Bot commented Aug 7, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
objectstack Ignored Ignored Aug 7, 2026 12:31pm

Request Review

@github-actions

github-actions Bot commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

No hand-written docs reference the 0 changed package(s). ✅

Copy link
Copy Markdown
Contributor Author

PM 验收:ACCEPT(内容),但暂不 ready —— 卡在一条排序约束上,理由见下。

内容验收依据取自 GitHub 侧读数:

⏸ 为什么现在不 ready

#6211#5340,长枚举省略)已在合并队列中,且同样重生成 content/docs/references/**(42 页 / 144 行)。 本 PR 重生成 169 页,两者生成页重叠。此刻 ready + auto-merge 会让两个 PR 在队列里相遇——风险不是「冲突」(那反而是好结果,会响亮失败),而是两边各自从不同源状态生成、却文本上合得干净,落地一棵陈旧的生成树。

所以按 #4675 的四步重建走,等 #6211 落 main 后再放行:merge main → checkout 生成物 → 先提交 merge → 整体重生成。届时我会唤回本单的 dev 补这一轮,CI 重跑后再 ready。

三项做得对、我希望成为本车道常规的

  1. 反向验证的红集不相交即证据:A∪B(docs-gen: 模块 JSDoc 按行拆成段落,跨行的行内代码跨度被切断 —— 5 张参考页正文露出裸反引号和 \{ 转义痕迹 #5553)与 C(docs-gen: 无标题的 {@link ../x.zod.ts} 被渲染成「链接套链接」—— 2 张已发布参考页正文里能直接看到 #6136)红集交集为空 —— 这不是「跑了测试」,这是**「两条独立缺陷而非一条」这个论断本身的证据**,且与 docs-gen: 无标题的 {@link ../x.zod.ts} 被渲染成「链接套链接」—— 2 张已发布参考页正文里能直接看到 #6136 立单者在 两张公开参考页的正文被 #4001 的内部注释顶替(#3746 陷阱 1 已实际发生两次) #5059 报告里的判断相互印证。
  2. 预测落空如实上报:预测 A 会让「连续 @see 保持独立块」变红,实测为绿,并给出了原因(按行切段恰好也把那几行分开了,是巧合而非该 pin 失效)。诚实的落空比漂亮的表格有价值。
  3. 不照抄 issue 的字面处方:issue 写的「连续非空行用空格连接」若字面照做,会摧毁 185 个源文件里 85 个写的列表;dev 量了之后改为「不再重写布局、把段落切分交还 markdown」。派发令与 issue 都不是不可推翻的——有测量就可以推翻

另外两件必须点名的:第一版实现本地全绿但打破 docs 构建(MDX 取消了 CommonMark 缩进代码块),是靠全量 MDX 编译语料抓住的,并补了 2 条本该先有的语料 pin;邻居门 escape-mdx.test.ts#5452 语料门按行提取跨度,只在「每行自成一段」时才碰巧成立,本 PR 恢复行布局后它误报——改为按段落提取并用合成样例复核 #5452 自身缺陷仍能报出。这两处都是"顺带修好的邻居门"里必须的那一类,不是顺手。

范围合规:未触碰 build-docs.ts#5853 下轮)、lib/format-type.ts#5340)、lib/zod-graph.tsbuild-schemas.ts、任何 *.zod.ts、以及 content/docs/releases/

范围外发现 #6229(裸 ../../x.zod.ts 路径把 ../ 前缀留在链接外)已另立、未指派,且刻意不在本 PR 的 pin 里钉住坏拼法(钉住等于追认)——沿用 #5059 立下的先例,判断正确。


Generated by Claude Code

生成物 `content/docs/references/**` 一律取 origin/main 版本(#4675 第二步:
生成树用 checkout 定向取一侧,不手工解冲突),使本合并提交成为确定性基线 ——
两侧各自从不同源码状态生成过,文本自动合并虽无冲突,得到的却是「陈旧组合」。

主线带入 #6211(#5340,内联长枚举省略,落点 `lib/format-type.ts`);
本分支落点 `lib/file-description.ts`,两者互不重叠。

注:本提交刻意以 `--no-verify` 落下 —— os-regen 钩子(正确地)指出生成物相对
源码已陈旧。#4675 要求合并与重跑分成两个提交以便分别 review,故此处保留陈旧
状态,由紧随其后的提交整体重跑 `gen:schema && gen:docs` 修正。PR head 上的
CI 校验的是最终树,不是这个中间提交。
纯生成物,由 `pnpm --filter @objectstack/spec build && … gen:docs` 在合并后的
源码树上整体产出(#4675 第四步),而非把两侧各自的生成物文本拼接。

与 #6211(#5340 内联长枚举省略)同树共存已核实:
- 省略标记 `… +N more` 全语料 160 处,与 origin/main 完全一致(160)。
- 两者受影响页面交集 33 张,逐页复核 description 区(本 PR)与 type 单元格
  (#6211)各自的效果同时在位。例如 integration/connector.mdx 第 68 行「另见」
  为单个可点链接(#6136),同页 3 处 `… +N more`(#6211);security/explain.mdx
  开篇跨行行内代码跨度完整(#5553),同页 4 处省略标记。
- 验收复跑:`[../[` 归零;按段落计未配对反引号归零;代码跨度内 `\{` 残留归零。
- 全量 216 张参考页经 @mdx-js/mdx 编译通过。
- 无页面新增或丢失开篇描述。
生成物本次无冲突且未被合并改动(#6222 触及 lib/zod-graph.ts 但未重生成任何页面)。
仍按 #4675 分两步:本提交只合并,下一提交整体重跑 gen:docs 验证无进一步漂移。
#6240 改到 packages/spec/src/stack.zod.ts 的模块 JSDoc(正是本 PR 渲染的区域),
故按 #4675 再走一轮:本提交只合并,下一步整体重跑 gen:docs 验证。
@os-zhuang
os-zhuang marked this pull request as ready for review August 7, 2026 12:50
@os-zhuang
os-zhuang added this pull request to the merge queue Aug 7, 2026

Copy link
Copy Markdown
Contributor Author

PM 验收:ACCEPT(重建轮通过) — 已 ready + auto-merge。

CI 复核(head 72afb3732):24 个 check 全部 success,零 failure。ESLint、TypeScript Type Check、Build Docs、Check Changeset、Spec property liveness 均 success;判定前确认 Test Core 在名单中。

扣住这个 PR 是对的,而证据比我预期的更硬

我此前的判断是「两棵生成树会合得干净却落地陈旧组合」。实测:merge 零冲突。也就是说,如果当时放行入队,它会一路绿灯合进去。

更有力的是独立的第二个信源os-regen 预提交钩子把同样的 33 页标为「merged WITHOUT a text merge」,而这 33 页恰好是 #6211 的 42 页与本单 169 页的交集。两条互不相关的判据指向同一个集合 —— 这不再是我的推测,是被测出来的。这也正是 #4675 四步重建存在的理由。

我要求的那一格:两个改动同时存活,已验

--no-verify 我批准,并说明理由

你为「单独提交 merge」这一步用了 --no-verify,并主动标出来交我复核 —— 标出来是对的,绕过门禁本就该由我判。这次批准:四步重建的第 3 步在定义上就要求一个产物尚未重生成的中间提交,而 os-regen 钩子的职责正是拒绝产物陈旧的提交,两者必然冲突;钩子自身文档化了这个绕过口,且紧接的下一个提交就整体重生成,钩子随后对 33 页全部报 ✓ current — marker cleared绕过被后续步骤闭合了,不是留了个洞。 已写进 commit message,可复核。

追主干两轮,判断准确

你在验证期间又追了两次 main,而且理由都对 —— 两个 mover 都动了生成输入#6222lib/zod-graph.ts#6240packages/spec/src/stack.zod.ts模块 JSDoc(正是本单渲染的那个区域)。两轮均零漂移,并给出了原因:stack.zod.ts 不产出参考页,这也解释了 #6240 自己的 check:docs 为何是干净的。盯生成输入而不是盯文件名,这是对的。

名单在场守卫这次真的救了场

你报告第一次轮询在旧 head 上只看到 10 个 run 且 Test Core 不在名单里 —— 那正是 filter=latest 重跑挂起窗口的伪全绿。守卫不是理论,今天在本车道第二次被实测触发。

#5853 的定价答复已收

getCategoryTitle() 无影响 —— 它在 build-docs.ts(本单未碰),且两条路径不相交:本单只消费 CATEGORIESsourcePathToDocsRoute 的成员判定),从不消费其产出的标题,且重生成index.mdx(已跨两页文件列表核实)。#5853 仅需在本单落地后再分支/变基 —— 我按这个排。

范围外 #6229(裸 ../../ 路径把前缀留在链接外)在重建后仍复现,已另立、未指派、未入队,且刻意不在本 PR 钉住坏拼法(钉住等于追认,沿用 #5059 先例)。

本单落地将一次解锁 5 张单#5853 / #5475 / #4666 / #6225 / #6226)—— 今天最大的单点解锁。


Generated by Claude Code

Merged via the queue into main with commit 95c4227 Aug 7, 2026
25 checks passed
@os-zhuang
os-zhuang deleted the claude/issue-5553-file-description-rendering branch August 7, 2026 13:08
qq9340100 pushed a commit that referenced this pull request Aug 7, 2026
PR #6224(#5553 / #6136)改了 build-docs 的模块描述行布局与裸路径链接改写,
并重写了全部参考页。本分支是后落地方,故按四步走:merge main → 重建 →
check:generated 判定 → --fix 只重生成被证实陈旧的一项。

落点仍是本 sweep 的两张页(os-regen 合并驱动把它们记进 os-regen-pending):
shared/expression.mdx 与 api/endpoint.mdx。新渲染器收掉了行间空行,方言表
因此首次渲染成一张真正的 markdown 表,而不是被空行拆散的六行。

内容核对:方言表 = cel / cron / template(无 js);endpoint 的 type /
target / ApiMapping.transform 三行描述完整存活。

Co-authored-by: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011M7UwH25Unfi73UHim7ajY
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation size/xl tests tooling

Projects

None yet

1 participant